diff --git a/.gitignore b/.gitignore
index cfd789ec1..27196b552 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+venv/
.DS_Store
.tags
.ipynb_checkpoints
diff --git a/.travis.yml b/.travis.yml
index cfaf6580e..8683d8bee 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,21 +3,5 @@ sudo: required
services:
- docker
-install:
- - docker build -t tmppilot -f Dockerfile.openpilot .
-
script:
- - docker run
- tmppilot /bin/sh -c 'cd /tmp/openpilot/selfdrive/test/ && ./test_fingerprints.py'
- - docker run
- tmppilot /bin/sh -c 'cd /tmp/openpilot/ && pyflakes $(find . -iname "*.py" | grep -vi "^\./pyextra.*" | grep -vi "^\./panda")'
- - docker run
- tmppilot /bin/sh -c 'cd /tmp/openpilot/ && pylint $(find . -iname "*.py" | grep -vi "^\./pyextra.*" | grep -vi "^\./panda"); exit $(($? & 3))'
- - docker run tmppilot /bin/sh -c 'cd /tmp/openpilot/ && make -C cereal && python -m unittest discover common'
- - docker run tmppilot /bin/sh -c 'cd /tmp/openpilot/ && make -C cereal && python -m unittest discover selfdrive/can'
- - docker run tmppilot /bin/sh -c 'cd /tmp/openpilot/ && make -C cereal && python -m unittest discover selfdrive/boardd'
- - docker run tmppilot /bin/sh -c 'cd /tmp/openpilot/ && make -C cereal && python -m unittest discover selfdrive/controls'
- - docker run tmppilot /bin/sh -c 'cd /tmp/openpilot/ && python -m unittest discover selfdrive/loggerd'
- - docker run
- -v "$(pwd)"/selfdrive/test/tests/plant/out:/tmp/openpilot/selfdrive/test/tests/plant/out
- tmppilot /bin/sh -c 'cd /tmp/openpilot/selfdrive/test/tests/plant && OPTEST=1 ./test_longitudinal.py'
+ - ./run_docker_tests.sh
diff --git a/Dockerfile.openpilot b/Dockerfile.openpilot
index f4c667fa0..edf6d4786 100644
--- a/Dockerfile.openpilot
+++ b/Dockerfile.openpilot
@@ -4,32 +4,45 @@ ENV PYTHONUNBUFFERED 1
RUN apt-get update && apt-get install -y \
autoconf \
build-essential \
- clang \
- wget \
bzip2 \
+ clang \
git \
- libglib2.0-0 \
- libtool \
- python-pip \
- libzmq5-dev \
+ libarchive-dev \
+ libavcodec-dev \
+ libavdevice-dev \
+ libavfilter-dev \
+ libavresample-dev \
+ libavutil-dev \
libffi-dev \
- libusb-1.0-0 \
+ libglib2.0-0 \
libssl-dev \
+ libswscale-dev \
+ libtool \
+ libusb-1.0-0 \
+ libzmq5-dev \
ocl-icd-libopencl1 \
ocl-icd-opencl-dev \
- opencl-headers
+ opencl-headers \
+ pkg-config \
+ python-pip \
+ wget
COPY phonelibs/install_capnp.sh /tmp/install_capnp.sh
RUN /tmp/install_capnp.sh
RUN pip install --upgrade pip==18.0
-RUN pip install numpy==1.11.2 scipy==0.18.1 matplotlib==2.1.2
+RUN pip install pipenv==2018.11.26
-COPY requirements_openpilot.txt /tmp/
-RUN pip install -r /tmp/requirements_openpilot.txt
+COPY Pipfile /tmp/
+COPY Pipfile.lock /tmp/
+RUN cd /tmp && pipenv install --deploy --system
ENV PYTHONPATH /tmp/openpilot:$PYTHONPATH
+RUN git clone --branch v0.6 https://github.com/commaai/openpilot-tools.git /tmp/openpilot/tools
+RUN pip install -r /tmp/openpilot/tools/requirements.txt
+RUN pip install fastcluster==1.1.20 scipy==0.19.1
+
COPY ./.pylintrc /tmp/openpilot/.pylintrc
COPY ./common /tmp/openpilot/common
COPY ./cereal /tmp/openpilot/cereal
diff --git a/Pipfile b/Pipfile
new file mode 100644
index 000000000..614968710
--- /dev/null
+++ b/Pipfile
@@ -0,0 +1,140 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[dev-packages]
+ipython = "<6.0"
+aenum = "*"
+azure-batch = "==4.1.3"
+azure-common = "==1.1.16"
+azure-nspkg = "==3.0.1"
+azure-storage-blob = "==1.3.1"
+azure-storage-common = "==1.3.0"
+azure-storage-nspkg = "==3.0.0"
+bincopy = "*"
+bleach = "==1.5.0"
+boto = "*"
+"boto3" = "*"
+celery = "*"
+control = "*"
+datadog = "*"
+decorator = "*"
+dlib = "*"
+dominate = "*"
+elasticsearch = "*"
+entium = "==0.1.4"
+fasteners = "*"
+future = "*"
+futures = "*"
+gevent = "*"
+pycocotools = {git = "https://github.com/cocodataset/cocoapi.git",subdirectory = "PythonAPI"}
+gunicorn = "*"
+"h5py" = "*"
+hexdump = "*"
+"html5lib" = "==0.9999999"
+imageio = "*"
+intervaltree = "*"
+ipykernel = "<5.0"
+joblib = "*"
+json-logging-py = "*"
+jupyter = "*"
+libarchive = "*"
+lru-dict = "*"
+lxml = "*"
+matplotlib = "==2.2.3"
+"mpld3" = "*"
+msgpack-python = "*"
+nbstripout = "*"
+nose-parameterized = "*"
+numpy = "==1.14.5"
+osmium = "==2.15.0"
+pbr = "==5.1.3"
+percache = "*"
+pprofile = "*"
+psutil = "*"
+pycurl = "*"
+git-pylint-commit-hook = "==2.5.1"
+pymongo = "*"
+"pynmea2" = "*"
+pypolyline = "==0.1.17"
+pysendfile = "*"
+python-logstash = "*"
+pyvcd = "*"
+redis = "*"
+redlock = "*"
+"s2sphere" = "*"
+scikit-image = "*"
+"subprocess32" = "*"
+supervisor = "*"
+tenacity = "*"
+tensorflow-gpu = "==1.13.0rc0"
+"transforms3d" = "*"
+utm = "*"
+"v4l2" = "*"
+visdom = "*"
+PyJWT = "==1.4.1"
+PyMySQL = "==0.9.2"
+Theano = "*"
+Werkzeug = "*"
+"backports.lzma" = "*"
+Flask-Cors = "*"
+Flask-SocketIO = "*"
+"GeoAlchemy2" = "*"
+Keras = ">=2.1.6"
+keras-maskrcnn = "*"
+keras-retinanet = "*"
+Pygments = "*"
+PyNaCl = "*"
+"PySDL2" = "*"
+reverse_geocoder = "*"
+Shapely = "*"
+SQLAlchemy = "==1.2.7"
+uWSGI = "*"
+scipy = "*"
+fastcluster = "==1.1.25"
+backports-abc = "*"
+pygame = "*"
+simplejson = "*"
+
+[packages]
+overpy = {git = "https://github.com/commaai/python-overpy.git",ref = "f86529af402d4642e1faeb146671c40284007323"}
+atomicwrites = "*"
+cffi = "*"
+crcmod = "*"
+hexdump = "*"
+libusb1 = "*"
+numpy = "*"
+psutil = "*"
+pycapnp = "*"
+cryptography = "*"
+pyserial = "*"
+python-dateutil = "*"
+pyzmq = "*"
+raven = "*"
+requests = "*"
+setproctitle = "*"
+six = "*"
+smbus2 = "*"
+sympy = "*"
+tqdm = "*"
+Cython = "*"
+PyYAML = "*"
+websocket_client = "*"
+Logentries = {git = "https://github.com/commaai/le_python.git",ref = "5eef8f5be5929d33973e1b10e686fa0cdcd6792f"}
+urllib3 = "*"
+chardet = "*"
+idna = "*"
+gunicorn = "*"
+utm = "*"
+json-rpc = "*"
+Flask = "*"
+PyJWT = "*"
+"Jinja2" = "*"
+nose = "*"
+pyflakes = "*"
+pylint = "*"
+pycryptodome = "*"
+
+[requires]
+python_version = "2.7"
diff --git a/Pipfile.lock b/Pipfile.lock
new file mode 100644
index 000000000..e4623df10
--- /dev/null
+++ b/Pipfile.lock
@@ -0,0 +1,2810 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "72c6a6eac19abf85ca5f272d04761f8336150d5bec599423c4b16891c99cb0bf"
+ },
+ "pipfile-spec": 6,
+ "requires": {
+ "python_version": "2.7"
+ },
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "asn1crypto": {
+ "hashes": [
+ "sha256:2f1adbb7546ed199e3c90ef23ec95c5cf3585bac7d11fb7eb562a3fe89c64e87",
+ "sha256:9d5c20441baf0cb60a4ac34cc447c6c189024b6b4c6cd7877034f4965c464e49"
+ ],
+ "version": "==0.24.0"
+ },
+ "astroid": {
+ "hashes": [
+ "sha256:87de48a92e29cedf7210ffa853d11441e7ad94cb47bacd91b023499b51cbc756",
+ "sha256:d25869fc7f44f1d9fb7d24fd7ea0639656f5355fc3089cd1f3d18c6ec6b124c7"
+ ],
+ "version": "==1.6.6"
+ },
+ "atomicwrites": {
+ "hashes": [
+ "sha256:03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4",
+ "sha256:75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6"
+ ],
+ "index": "pypi",
+ "version": "==1.3.0"
+ },
+ "backports.functools-lru-cache": {
+ "hashes": [
+ "sha256:9d98697f088eb1b0fa451391f91afb5e3ebde16bbdb272819fd091151fda4f1a",
+ "sha256:f0b0e4eba956de51238e17573b7087e852dfe9854afd2e9c873f73fc0ca0a6dd"
+ ],
+ "markers": "python_version < '3.2'",
+ "version": "==1.5"
+ },
+ "certifi": {
+ "hashes": [
+ "sha256:59b7658e26ca9c7339e00f8f4636cdfe59d34fa37b9b04f6f9e9926b3cece1a5",
+ "sha256:b26104d6835d1f5e49452a26eb2ff87fe7090b89dfcaee5ea2212697e1e1d7ae"
+ ],
+ "version": "==2019.3.9"
+ },
+ "cffi": {
+ "hashes": [
+ "sha256:041c81822e9f84b1d9c401182e174996f0bae9991f33725d059b771744290774",
+ "sha256:046ef9a22f5d3eed06334d01b1e836977eeef500d9b78e9ef693f9380ad0b83d",
+ "sha256:066bc4c7895c91812eff46f4b1c285220947d4aa46fa0a2651ff85f2afae9c90",
+ "sha256:066c7ff148ae33040c01058662d6752fd73fbc8e64787229ea8498c7d7f4041b",
+ "sha256:2444d0c61f03dcd26dbf7600cf64354376ee579acad77aef459e34efcb438c63",
+ "sha256:300832850b8f7967e278870c5d51e3819b9aad8f0a2c8dbe39ab11f119237f45",
+ "sha256:34c77afe85b6b9e967bd8154e3855e847b70ca42043db6ad17f26899a3df1b25",
+ "sha256:46de5fa00f7ac09f020729148ff632819649b3e05a007d286242c4882f7b1dc3",
+ "sha256:4aa8ee7ba27c472d429b980c51e714a24f47ca296d53f4d7868075b175866f4b",
+ "sha256:4d0004eb4351e35ed950c14c11e734182591465a33e960a4ab5e8d4f04d72647",
+ "sha256:4e3d3f31a1e202b0f5a35ba3bc4eb41e2fc2b11c1eff38b362de710bcffb5016",
+ "sha256:50bec6d35e6b1aaeb17f7c4e2b9374ebf95a8975d57863546fa83e8d31bdb8c4",
+ "sha256:55cad9a6df1e2a1d62063f79d0881a414a906a6962bc160ac968cc03ed3efcfb",
+ "sha256:5662ad4e4e84f1eaa8efce5da695c5d2e229c563f9d5ce5b0113f71321bcf753",
+ "sha256:59b4dc008f98fc6ee2bb4fd7fc786a8d70000d058c2bbe2698275bc53a8d3fa7",
+ "sha256:73e1ffefe05e4ccd7bcea61af76f36077b914f92b76f95ccf00b0c1b9186f3f9",
+ "sha256:a1f0fd46eba2d71ce1589f7e50a9e2ffaeb739fb2c11e8192aa2b45d5f6cc41f",
+ "sha256:a2e85dc204556657661051ff4bab75a84e968669765c8a2cd425918699c3d0e8",
+ "sha256:a5457d47dfff24882a21492e5815f891c0ca35fefae8aa742c6c263dac16ef1f",
+ "sha256:a8dccd61d52a8dae4a825cdbb7735da530179fea472903eb871a5513b5abbfdc",
+ "sha256:ae61af521ed676cf16ae94f30fe202781a38d7178b6b4ab622e4eec8cefaff42",
+ "sha256:b012a5edb48288f77a63dba0840c92d0504aa215612da4541b7b42d849bc83a3",
+ "sha256:d2c5cfa536227f57f97c92ac30c8109688ace8fa4ac086d19d0af47d134e2909",
+ "sha256:d42b5796e20aacc9d15e66befb7a345454eef794fdb0737d1af593447c6c8f45",
+ "sha256:dee54f5d30d775f525894d67b1495625dd9322945e7fee00731952e0368ff42d",
+ "sha256:e070535507bd6aa07124258171be2ee8dfc19119c28ca94c9dfb7efd23564512",
+ "sha256:e1ff2748c84d97b065cc95429814cdba39bcbd77c9c85c89344b317dc0d9cbff",
+ "sha256:ed851c75d1e0e043cbf5ca9a8e1b13c4c90f3fbd863dacb01c0808e2b5204201"
+ ],
+ "index": "pypi",
+ "version": "==1.12.3"
+ },
+ "chardet": {
+ "hashes": [
+ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
+ "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
+ ],
+ "index": "pypi",
+ "version": "==3.0.4"
+ },
+ "click": {
+ "hashes": [
+ "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13",
+ "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"
+ ],
+ "version": "==7.0"
+ },
+ "configparser": {
+ "hashes": [
+ "sha256:8be81d89d6e7b4c0d4e44bcc525845f6da25821de80cb5e06e7e0238a2899e32",
+ "sha256:da60d0014fd8c55eb48c1c5354352e363e2d30bbf7057e5e171a468390184c75"
+ ],
+ "markers": "python_version == '2.7'",
+ "version": "==3.7.4"
+ },
+ "contextlib2": {
+ "hashes": [
+ "sha256:509f9419ee91cdd00ba34443217d5ca51f5a364a404e1dce9e8979cea969ca48",
+ "sha256:f5260a6e679d2ff42ec91ec5252f4eeffdcf21053db9113bd0a8e4d953769c00"
+ ],
+ "markers": "python_version < '3.2'",
+ "version": "==0.5.5"
+ },
+ "crcmod": {
+ "hashes": [
+ "sha256:dc7051a0db5f2bd48665a990d3ec1cc305a466a77358ca4492826f41f283601e"
+ ],
+ "index": "pypi",
+ "version": "==1.7"
+ },
+ "cryptography": {
+ "hashes": [
+ "sha256:24b61e5fcb506424d3ec4e18bca995833839bf13c59fc43e530e488f28d46b8c",
+ "sha256:25dd1581a183e9e7a806fe0543f485103232f940fcfc301db65e630512cce643",
+ "sha256:3452bba7c21c69f2df772762be0066c7ed5dc65df494a1d53a58b683a83e1216",
+ "sha256:41a0be220dd1ed9e998f5891948306eb8c812b512dc398e5a01846d855050799",
+ "sha256:5751d8a11b956fbfa314f6553d186b94aa70fdb03d8a4d4f1c82dcacf0cbe28a",
+ "sha256:5f61c7d749048fa6e3322258b4263463bfccefecb0dd731b6561cb617a1d9bb9",
+ "sha256:72e24c521fa2106f19623a3851e9f89ddfdeb9ac63871c7643790f872a305dfc",
+ "sha256:7b97ae6ef5cba2e3bb14256625423413d5ce8d1abb91d4f29b6d1a081da765f8",
+ "sha256:961e886d8a3590fd2c723cf07be14e2a91cf53c25f02435c04d39e90780e3b53",
+ "sha256:96d8473848e984184b6728e2c9d391482008646276c3ff084a1bd89e15ff53a1",
+ "sha256:ae536da50c7ad1e002c3eee101871d93abdc90d9c5f651818450a0d3af718609",
+ "sha256:b0db0cecf396033abb4a93c95d1602f268b3a68bb0a9cc06a7cff587bb9a7292",
+ "sha256:cfee9164954c186b191b91d4193989ca994703b2fff406f71cf454a2d3c7327e",
+ "sha256:e6347742ac8f35ded4a46ff835c60e68c22a536a8ae5c4422966d06946b6d4c6",
+ "sha256:f27d93f0139a3c056172ebb5d4f9056e770fdf0206c2f422ff2ebbad142e09ed",
+ "sha256:f57b76e46a58b63d1c6375017f4564a28f19a5ca912691fd2e4261b3414b618d"
+ ],
+ "index": "pypi",
+ "version": "==2.7"
+ },
+ "cython": {
+ "hashes": [
+ "sha256:0afa0b121b89de619e71587e25702e2b7068d7da2164c47e6eee80c17823a62f",
+ "sha256:1c608ba76f7a20cc9f0c021b7fe5cb04bc1a70327ae93a9298b1bc3e0edddebe",
+ "sha256:26229570d6787ff3caa932fe9d802960f51a89239b990d275ae845405ce43857",
+ "sha256:2a9deafa437b6154cac2f25bb88e0bfd075a897c8dc847669d6f478d7e3ee6b1",
+ "sha256:2f28396fbce6d9d68a40edbf49a6729cf9d92a4d39ff0f501947a89188e9099f",
+ "sha256:3983dd7b67297db299b403b29b328d9e03e14c4c590ea90aa1ad1d7b35fb178b",
+ "sha256:4100a3f8e8bbe47d499cdac00e56d5fe750f739701ea52dc049b6c56f5421d97",
+ "sha256:51abfaa7b6c66f3f18028876713c8804e73d4c2b6ceddbcbcfa8ec62429377f0",
+ "sha256:61c24f4554efdb8fb1ac6c8e75dab301bcdf2b7b739ed0c2b267493bb43163c5",
+ "sha256:700ccf921b2fdc9b23910e95b5caae4b35767685e0812343fa7172409f1b5830",
+ "sha256:7b41eb2e792822a790cb2a171df49d1a9e0baaa8e81f58077b7380a273b93d5f",
+ "sha256:803987d3b16d55faa997bfc12e8b97f1091f145930dee229b020487aed8a1f44",
+ "sha256:99af5cfcd208c81998dcf44b3ca466dee7e17453cfb50e98b87947c3a86f8753",
+ "sha256:9faea1cca34501c7e139bc7ef8e504d532b77865c58592493e2c154a003b450f",
+ "sha256:a7ba4c9a174db841cfee9a0b92563862a0301d7ca543334666c7266b541f141a",
+ "sha256:b26071c2313d1880599c69fd831a07b32a8c961ba69d7ccbe5db1cd8d319a4ca",
+ "sha256:b49dc8e1116abde13a3e6a9eb8da6ab292c5a3325155fb872e39011b110b37e6",
+ "sha256:bd40def0fd013569887008baa6da9ca428e3d7247adeeaeada153006227bb2e7",
+ "sha256:bfd0db770e8bd4e044e20298dcae6dfc42561f85d17ee546dcd978c8b23066ae",
+ "sha256:c2fad1efae5889925c8fd7867fdd61f59480e4e0b510f9db096c912e884704f1",
+ "sha256:c81aea93d526ccf6bc0b842c91216ee9867cd8792f6725a00f19c8b5837e1715",
+ "sha256:da786e039b4ad2bce3d53d4799438cf1f5e01a0108f1b8d78ac08e6627281b1a",
+ "sha256:deab85a069397540987082d251e9c89e0e5b2e3e044014344ff81f60e211fc4b",
+ "sha256:e3f1e6224c3407beb1849bdc5ae3150929e593e4cffff6ca41c6ec2b10942c80",
+ "sha256:e74eb224e53aae3943d66e2d29fe42322d5753fd4c0641329bccb7efb3a46552",
+ "sha256:ee697c7ea65cb14915a64f36874da8ffc2123df43cf8bc952172e04a26656cd6",
+ "sha256:f37792b16d11606c28e428460bd6a3d14b8917b109e77cdbe4ca78b0b9a52c87",
+ "sha256:fd2906b54cbf879c09d875ad4e4687c58d87f5ed03496063fec1c9065569fd5d"
+ ],
+ "index": "pypi",
+ "version": "==0.29.10"
+ },
+ "enum34": {
+ "hashes": [
+ "sha256:2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850",
+ "sha256:644837f692e5f550741432dd3f223bbb9852018674981b1664e5dc339387588a",
+ "sha256:6bd0f6ad48ec2aa117d3d141940d484deccda84d4fcd884f5c3d93c23ecd8c79",
+ "sha256:8ad8c4783bf61ded74527bffb48ed9b54166685e4230386a9ed9b1279e2df5b1"
+ ],
+ "markers": "python_version < '3'",
+ "version": "==1.1.6"
+ },
+ "flask": {
+ "hashes": [
+ "sha256:ad7c6d841e64296b962296c2c2dabc6543752985727af86a975072dea984b6f3",
+ "sha256:e7d32475d1de5facaa55e3958bc4ec66d3762076b074296aa50ef8fdc5b9df61"
+ ],
+ "index": "pypi",
+ "version": "==1.0.3"
+ },
+ "futures": {
+ "hashes": [
+ "sha256:9ec02aa7d674acb8618afb127e27fde7fc68994c0437ad759fa094a574adb265",
+ "sha256:ec0a6cb848cc212002b9828c3e34c675e0c9ff6741dc445cab6fdd4e1085d1f1"
+ ],
+ "markers": "python_version < '3.2'",
+ "version": "==3.2.0"
+ },
+ "gunicorn": {
+ "hashes": [
+ "sha256:aa8e0b40b4157b36a5df5e599f45c9c76d6af43845ba3b3b0efe2c70473c2471",
+ "sha256:fa2662097c66f920f53f70621c6c58ca4a3c4d3434205e608e121b5b3b71f4f3"
+ ],
+ "index": "pypi",
+ "version": "==19.9.0"
+ },
+ "hexdump": {
+ "hashes": [
+ "sha256:d781a43b0c16ace3f9366aade73e8ad3a7bd5137d58f0b45ab2d3f54876f20db"
+ ],
+ "index": "pypi",
+ "version": "==3.3"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407",
+ "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"
+ ],
+ "index": "pypi",
+ "version": "==2.8"
+ },
+ "ipaddress": {
+ "hashes": [
+ "sha256:64b28eec5e78e7510698f6d4da08800a5c575caa4a286c93d651c5d3ff7b6794",
+ "sha256:b146c751ea45cad6188dd6cf2d9b757f6f4f8d6ffb96a023e6f2e26eea02a72c"
+ ],
+ "markers": "python_version < '3'",
+ "version": "==1.0.22"
+ },
+ "isort": {
+ "hashes": [
+ "sha256:c40744b6bc5162bbb39c1257fe298b7a393861d50978b565f3ccd9cb9de0182a",
+ "sha256:f57abacd059dc3bd666258d1efb0377510a89777fda3e3274e3c01f7c03ae22d"
+ ],
+ "version": "==4.3.20"
+ },
+ "itsdangerous": {
+ "hashes": [
+ "sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19",
+ "sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749"
+ ],
+ "version": "==1.1.0"
+ },
+ "jinja2": {
+ "hashes": [
+ "sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013",
+ "sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b"
+ ],
+ "index": "pypi",
+ "version": "==2.10.1"
+ },
+ "json-rpc": {
+ "hashes": [
+ "sha256:bc84451268b48a576d3138744322a8ce673eccadf7424edf4d446b1ddb59e58c",
+ "sha256:d6ed3dae670a12e4caa738d309807357d22e2f6e222bb34e8ef019e8b5b1228b"
+ ],
+ "index": "pypi",
+ "version": "==1.12.1"
+ },
+ "lazy-object-proxy": {
+ "hashes": [
+ "sha256:159a745e61422217881c4de71f9eafd9d703b93af95618635849fe469a283661",
+ "sha256:23f63c0821cc96a23332e45dfaa83266feff8adc72b9bcaef86c202af765244f",
+ "sha256:3b11be575475db2e8a6e11215f5aa95b9ec14de658628776e10d96fa0b4dac13",
+ "sha256:3f447aff8bc61ca8b42b73304f6a44fa0d915487de144652816f950a3f1ab821",
+ "sha256:4ba73f6089cd9b9478bc0a4fa807b47dbdb8fad1d8f31a0f0a5dbf26a4527a71",
+ "sha256:4f53eadd9932055eac465bd3ca1bd610e4d7141e1278012bd1f28646aebc1d0e",
+ "sha256:64483bd7154580158ea90de5b8e5e6fc29a16a9b4db24f10193f0c1ae3f9d1ea",
+ "sha256:6f72d42b0d04bfee2397aa1862262654b56922c20a9bb66bb76b6f0e5e4f9229",
+ "sha256:7c7f1ec07b227bdc561299fa2328e85000f90179a2f44ea30579d38e037cb3d4",
+ "sha256:7c8b1ba1e15c10b13cad4171cfa77f5bb5ec2580abc5a353907780805ebe158e",
+ "sha256:8559b94b823f85342e10d3d9ca4ba5478168e1ac5658a8a2f18c991ba9c52c20",
+ "sha256:a262c7dfb046f00e12a2bdd1bafaed2408114a89ac414b0af8755c696eb3fc16",
+ "sha256:acce4e3267610c4fdb6632b3886fe3f2f7dd641158a843cf6b6a68e4ce81477b",
+ "sha256:be089bb6b83fac7f29d357b2dc4cf2b8eb8d98fe9d9ff89f9ea6012970a853c7",
+ "sha256:bfab710d859c779f273cc48fb86af38d6e9210f38287df0069a63e40b45a2f5c",
+ "sha256:c10d29019927301d524a22ced72706380de7cfc50f767217485a912b4c8bd82a",
+ "sha256:dd6e2b598849b3d7aee2295ac765a578879830fb8966f70be8cd472e6069932e",
+ "sha256:e408f1eacc0a68fed0c08da45f31d0ebb38079f043328dce69ff133b95c29dc1"
+ ],
+ "version": "==1.4.1"
+ },
+ "libusb1": {
+ "hashes": [
+ "sha256:adf64a4f3f5c94643a1286f8153bcf4bc787c348b38934aacd7fe17fbeebc571"
+ ],
+ "index": "pypi",
+ "version": "==1.7.1"
+ },
+ "logentries": {
+ "git": "https://github.com/commaai/le_python.git",
+ "ref": "5eef8f5be5929d33973e1b10e686fa0cdcd6792f"
+ },
+ "markupsafe": {
+ "hashes": [
+ "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473",
+ "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161",
+ "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235",
+ "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5",
+ "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff",
+ "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b",
+ "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1",
+ "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e",
+ "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183",
+ "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66",
+ "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1",
+ "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1",
+ "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e",
+ "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b",
+ "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905",
+ "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735",
+ "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d",
+ "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e",
+ "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d",
+ "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c",
+ "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21",
+ "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2",
+ "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5",
+ "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b",
+ "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6",
+ "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f",
+ "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f",
+ "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"
+ ],
+ "version": "==1.1.1"
+ },
+ "mccabe": {
+ "hashes": [
+ "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42",
+ "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"
+ ],
+ "version": "==0.6.1"
+ },
+ "mpmath": {
+ "hashes": [
+ "sha256:fc17abe05fbab3382b61a123c398508183406fa132e0223874578e20946499f6"
+ ],
+ "version": "==1.1.0"
+ },
+ "nose": {
+ "hashes": [
+ "sha256:9ff7c6cc443f8c51994b34a667bbcf45afd6d945be7477b52e97516fd17c53ac",
+ "sha256:dadcddc0aefbf99eea214e0f1232b94f2fa9bd98fa8353711dacb112bfcbbb2a",
+ "sha256:f1bffef9cbc82628f6e7d7b40d7e255aefaa1adb6a1b1d26c69a8b79e6208a98"
+ ],
+ "index": "pypi",
+ "version": "==1.3.7"
+ },
+ "numpy": {
+ "hashes": [
+ "sha256:0778076e764e146d3078b17c24c4d89e0ecd4ac5401beff8e1c87879043a0633",
+ "sha256:141c7102f20abe6cf0d54c4ced8d565b86df4d3077ba2343b61a6db996cefec7",
+ "sha256:14270a1ee8917d11e7753fb54fc7ffd1934f4d529235beec0b275e2ccf00333b",
+ "sha256:27e11c7a8ec9d5838bc59f809bfa86efc8a4fd02e58960fa9c49d998e14332d5",
+ "sha256:2a04dda79606f3d2f760384c38ccd3d5b9bb79d4c8126b67aff5eb09a253763e",
+ "sha256:3c26010c1b51e1224a3ca6b8df807de6e95128b0908c7e34f190e7775455b0ca",
+ "sha256:52c40f1a4262c896420c6ea1c6fda62cf67070e3947e3307f5562bd783a90336",
+ "sha256:6e4f8d9e8aa79321657079b9ac03f3cf3fd067bf31c1cca4f56d49543f4356a5",
+ "sha256:7242be12a58fec245ee9734e625964b97cf7e3f2f7d016603f9e56660ce479c7",
+ "sha256:7dc253b542bfd4b4eb88d9dbae4ca079e7bf2e2afd819ee18891a43db66c60c7",
+ "sha256:94f5bd885f67bbb25c82d80184abbf7ce4f6c3c3a41fbaa4182f034bba803e69",
+ "sha256:a89e188daa119ffa0d03ce5123dee3f8ffd5115c896c2a9d4f0dbb3d8b95bfa3",
+ "sha256:ad3399da9b0ca36e2f24de72f67ab2854a62e623274607e37e0ce5f5d5fa9166",
+ "sha256:b0348be89275fd1d4c44ffa39530c41a21062f52299b1e3ee7d1c61f060044b8",
+ "sha256:b5554368e4ede1856121b0dfa35ce71768102e4aa55e526cb8de7f374ff78722",
+ "sha256:cbddc56b2502d3f87fda4f98d948eb5b11f36ff3902e17cb6cc44727f2200525",
+ "sha256:d79f18f41751725c56eceab2a886f021d70fd70a6188fd386e29a045945ffc10",
+ "sha256:dc2ca26a19ab32dc475dbad9dfe723d3a64c835f4c23f625c2b6566ca32b9f29",
+ "sha256:dd9bcd4f294eb0633bb33d1a74febdd2b9018b8b8ed325f861fffcd2c7660bb8",
+ "sha256:e8baab1bc7c9152715844f1faca6744f2416929de10d7639ed49555a85549f52",
+ "sha256:ec31fe12668af687b99acf1567399632a7c47b0e17cfb9ae47c098644ef36797",
+ "sha256:f12b4f7e2d8f9da3141564e6737d79016fe5336cc92de6814eba579744f65b0a",
+ "sha256:f58ac38d5ca045a377b3b377c84df8175ab992c970a53332fa8ac2373df44ff7"
+ ],
+ "index": "pypi",
+ "version": "==1.16.4"
+ },
+ "overpy": {
+ "git": "https://github.com/commaai/python-overpy.git",
+ "ref": "f86529af402d4642e1faeb146671c40284007323"
+ },
+ "psutil": {
+ "hashes": [
+ "sha256:028a1ec3c6197eadd11e7b46e8cc2f0720dc18ac6d7aabdb8e8c0d6c9704f000",
+ "sha256:503e4b20fa9d3342bcf58191bbc20a4a5ef79ca7df8972e6197cc14c5513e73d",
+ "sha256:863a85c1c0a5103a12c05a35e59d336e1d665747e531256e061213e2e90f63f3",
+ "sha256:954f782608bfef9ae9f78e660e065bd8ffcfaea780f9f2c8a133bb7cb9e826d7",
+ "sha256:b6e08f965a305cd84c2d07409bc16fbef4417d67b70c53b299116c5b895e3f45",
+ "sha256:bc96d437dfbb8865fc8828cf363450001cb04056bbdcdd6fc152c436c8a74c61",
+ "sha256:cf49178021075d47c61c03c0229ac0c60d5e2830f8cab19e2d88e579b18cdb76",
+ "sha256:d5350cb66690915d60f8b233180f1e49938756fb2d501c93c44f8fb5b970cc63",
+ "sha256:eba238cf1989dfff7d483c029acb0ac4fcbfc15de295d682901f0e2497e6781a"
+ ],
+ "index": "pypi",
+ "version": "==5.6.3"
+ },
+ "pycapnp": {
+ "hashes": [
+ "sha256:44e14a5ace399cf1753acb8bbce558b8c895c48fd2102d266c34eaff286824cf"
+ ],
+ "index": "pypi",
+ "version": "==0.6.4"
+ },
+ "pycparser": {
+ "hashes": [
+ "sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3"
+ ],
+ "version": "==2.19"
+ },
+ "pycryptodome": {
+ "hashes": [
+ "sha256:0281dc6a65a4d0d9e439f54e0ad5faf27bfdc2ebe9ead36912bac74a0920fa2e",
+ "sha256:02af9b284f5c9a55f06f5e4532c16c9b7bd958e293e93969934d864ef7bd87ee",
+ "sha256:09da99372fb69762e4b9690291176a166cc351793e2e1c9405d29ca291503aa8",
+ "sha256:0c2400ccfc049c3f24e65d4f02bb4208d86e408011019e455fab7f50d2b226c9",
+ "sha256:2081dd6dce6b21bf3596427edaedd4f2561dce616893b162ed2c674f3a3ca70a",
+ "sha256:28b86ec9fdb005a2a18e4862a3a7277046738825ee8dc89cda5657e75a396089",
+ "sha256:2d790c0d4c0d5edcf5fbab4e2af7b03757e40c5ae8d217f0dfe9ddea37fe130f",
+ "sha256:2f24906153dca16528cf5515b1afa9ef635423d5a654904e861765f88ca667b6",
+ "sha256:30d283939896fa4bacbdb9fa86e6fd51e9a5b953a511e210b38481f697f289f5",
+ "sha256:31f78b67f97830d137f74813c0502a181a03b43a32ed124049bb20428176c307",
+ "sha256:33c1f3a380fd38ab4dd4372bef17e98002b360b52814bb1b077693b1bd06ec87",
+ "sha256:34091e9a6650c44e25339f22fc821396f19f152f65be2546edd823a093fb5a04",
+ "sha256:567fb73951ab6865a2eb1a0060b54be1e27302574f6c65879525bdf53fab49e1",
+ "sha256:5bc40f8aa7ba8ca7f833ad2477b9d84e1bfd2630b22a46d9bbd221982f8c3ac0",
+ "sha256:6b0a0ccf33c7a6100c569667c888335a4aaf0d22218cb97b4963a65d70f6c343",
+ "sha256:71b93157f1ce93fc7cfff9359b76def2b4826a7ef7a7f95e070161368e7f584a",
+ "sha256:7d939d511b7dac29b2d936706786771ecb8256e43fade5cdb0e8bc58f02b86cf",
+ "sha256:7fbc5a93d52e4c51487f4648b00dc41700adb144d10fc567b05f852e76c243ad",
+ "sha256:9cb94b8f9c915a5d2b273d612a25a8e5d67b49543f8eb6bcec0275ac46cda421",
+ "sha256:a585ea1722f9731e75881d5ffcc51d11c794d244ac57e7c2a9cbb8d5ac729302",
+ "sha256:a6458dd7a10ae51f6fce56bdfc79bf6d3b54556237045d09e77fbda9d6d37864",
+ "sha256:a9fb92e948128bce0239b87c6efcf2cb1c5a703d0b41dd6835211e6fafd1c5df",
+ "sha256:b0b6b4ca1c53e7d6ca9f2720919f63837f05e7a5f92912a2bc29bfd03ed3b54f",
+ "sha256:b7d22c8d648aaa3a7ec785eda544402141eb78ac5ffbba4cbe2c3a1f52276870",
+ "sha256:bc9560574a868cfa2ba781b7bb0b4685b08ea251697abfc49070ffc05e1cbee6",
+ "sha256:c0c5a576f3f7b7de3f86889cb47eb51b59dc11db9cf1e2a0f51eb4d988010ea4",
+ "sha256:e1c91c2fa942a71c98a7a1f462de6dbbe82f34b9267eb8131314d97bd13bf0d4",
+ "sha256:ec936361ad78aa95382c313df95777795b8185aac5dd3ec5463363ea94b556fc"
+ ],
+ "index": "pypi",
+ "version": "==3.8.2"
+ },
+ "pyflakes": {
+ "hashes": [
+ "sha256:17dbeb2e3f4d772725c777fabc446d5634d1038f234e77343108ce445ea69ce0",
+ "sha256:d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2"
+ ],
+ "index": "pypi",
+ "version": "==2.1.1"
+ },
+ "pyjwt": {
+ "hashes": [
+ "sha256:5c6eca3c2940464d106b99ba83b00c6add741c9becaec087fb7ccdefea71350e",
+ "sha256:8d59a976fb773f3e6a39c85636357c4f0e242707394cadadd9814f5cbaa20e96"
+ ],
+ "index": "pypi",
+ "version": "==1.7.1"
+ },
+ "pylint": {
+ "hashes": [
+ "sha256:02c2b6d268695a8b64ad61847f92e611e6afcff33fd26c3a2125370c4662905d",
+ "sha256:ee1e85575587c5b58ddafa25e1c1b01691ef172e139fc25585e5d3f02451da93"
+ ],
+ "index": "pypi",
+ "version": "==1.9.4"
+ },
+ "pyserial": {
+ "hashes": [
+ "sha256:6e2d401fdee0eab996cf734e67773a0143b932772ca8b42451440cfed942c627",
+ "sha256:e0770fadba80c31013896c7e6ef703f72e7834965954a78e71a3049488d4d7d8"
+ ],
+ "index": "pypi",
+ "version": "==3.4"
+ },
+ "python-dateutil": {
+ "hashes": [
+ "sha256:7e6584c74aeed623791615e26efd690f29817a27c73085b78e4bad02493df2fb",
+ "sha256:c89805f6f4d64db21ed966fda138f8a5ed7a4fdbc1a8ee329ce1b74e3c74da9e"
+ ],
+ "index": "pypi",
+ "version": "==2.8.0"
+ },
+ "pyyaml": {
+ "hashes": [
+ "sha256:57acc1d8533cbe51f6662a55434f0dbecfa2b9eaf115bede8f6fd00115a0c0d3",
+ "sha256:588c94b3d16b76cfed8e0be54932e5729cc185caffaa5a451e7ad2f7ed8b4043",
+ "sha256:68c8dd247f29f9a0d09375c9c6b8fdc64b60810ebf07ba4cdd64ceee3a58c7b7",
+ "sha256:70d9818f1c9cd5c48bb87804f2efc8692f1023dac7f1a1a5c61d454043c1d265",
+ "sha256:86a93cccd50f8c125286e637328ff4eef108400dd7089b46a7be3445eecfa391",
+ "sha256:a0f329125a926876f647c9fa0ef32801587a12328b4a3c741270464e3e4fa778",
+ "sha256:a3c252ab0fa1bb0d5a3f6449a4826732f3eb6c0270925548cac342bc9b22c225",
+ "sha256:b4bb4d3f5e232425e25dda21c070ce05168a786ac9eda43768ab7f3ac2770955",
+ "sha256:cd0618c5ba5bda5f4039b9398bb7fb6a317bb8298218c3de25c47c4740e4b95e",
+ "sha256:ceacb9e5f8474dcf45b940578591c7f3d960e82f926c707788a570b51ba59190",
+ "sha256:fe6a88094b64132c4bb3b631412e90032e8cfe9745a58370462240b8cb7553cd"
+ ],
+ "index": "pypi",
+ "version": "==5.1.1"
+ },
+ "pyzmq": {
+ "hashes": [
+ "sha256:1651e52ed91f0736afd6d94ef9f3259b5534ce8beddb054f3d5ca989c4ef7c4f",
+ "sha256:5ccb9b3d4cd20c000a9b75689d5add8cd3bce67fcbd0f8ae1b59345247d803af",
+ "sha256:5e120c4cd3872e332fb35d255ad5998ebcee32ace4387b1b337416b6b90436c7",
+ "sha256:5e2a3707c69a7281a9957f83718815fd74698cba31f6d69f9ed359921f662221",
+ "sha256:63d51add9af8d0442dc90f916baf98fdc04e3b0a32afec4bfc83f8d85e72959f",
+ "sha256:65c5a0bdc49e20f7d6b03a661f71e2fda7a99c51270cafe71598146d09810d0d",
+ "sha256:66828fabe911aa545d919028441a585edb7c9c77969a5fea6722ef6e6ece38ab",
+ "sha256:7d79427e82d9dad6e9b47c0b3e7ae5f9d489b1601e3a36ea629bb49501a4daf3",
+ "sha256:824ee5d3078c4eae737ffc500fbf32f2b14e6ec89b26b435b7834febd70120cf",
+ "sha256:89dc0a83cccec19ff3c62c091e43e66e0183d1e6b4658c16ee4e659518131494",
+ "sha256:8b319805f6f7c907b101c864c3ca6cefc9db8ce0791356f180b1b644c7347e4c",
+ "sha256:90facfb379ab47f94b19519c1ecc8ec8d10813b69d9c163117944948bdec5d15",
+ "sha256:a0a178c7420021fc0730180a914a4b4b3092ce9696ceb8e72d0f60f8ce1655dd",
+ "sha256:a7a89591ae315baccb8072f216614b3e59aed7385aef4393a6c741783d6ee9cf",
+ "sha256:ba2578f0ae582452c02ed9fac2dc477b08e80ce05d2c0885becf5fff6651ccb0",
+ "sha256:c69b0055c55702f5b0b6b354133e8325b9a56dbc80e1be2d240bead253fb9825",
+ "sha256:ca434e1858fe222380221ddeb81e86f45522773344c9da63c311d17161df5e06",
+ "sha256:d4b8ecfc3d92f114f04d5c40f60a65e5196198b827503341521dda12d8b14939",
+ "sha256:d706025c47b09a54f005953ebe206f6d07a22516776faa4f509aaff681cc5468",
+ "sha256:d8f27e958f8a2c0c8ffd4d8855c3ce8ac3fa1e105f0491ce31729aa2b3229740",
+ "sha256:dbd264298f76b9060ce537008eb989317ca787c857e23cbd1b3ddf89f190a9b1",
+ "sha256:e926d66f0df8fdbf03ba20583af0f215e475c667fb033d45fd031c66c63e34c9",
+ "sha256:efc3bd48237f973a749f7312f68062f1b4ca5c2032a0673ca3ea8e46aa77187b",
+ "sha256:f59bc782228777cbfe04555707a9c56d269c787ed25d6d28ed9d0fbb41cb1ad2",
+ "sha256:f8da5322f4ff5f667a0d5a27e871b560c6637153c81e318b35cb012b2a98835c"
+ ],
+ "index": "pypi",
+ "version": "==18.0.1"
+ },
+ "raven": {
+ "hashes": [
+ "sha256:3fa6de6efa2493a7c827472e984ce9b020797d0da16f1db67197bcc23c8fae54",
+ "sha256:44a13f87670836e153951af9a3c80405d36b43097db869a36e92809673692ce4"
+ ],
+ "index": "pypi",
+ "version": "==6.10.0"
+ },
+ "requests": {
+ "hashes": [
+ "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4",
+ "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31"
+ ],
+ "index": "pypi",
+ "version": "==2.22.0"
+ },
+ "setproctitle": {
+ "hashes": [
+ "sha256:6283b7a58477dd8478fbb9e76defb37968ee4ba47b05ec1c053cb39638bd7398",
+ "sha256:6a035eddac62898786aed2c2eee7334c28cfc8106e8eb29fdd117cac56c6cdf0"
+ ],
+ "index": "pypi",
+ "version": "==1.1.10"
+ },
+ "singledispatch": {
+ "hashes": [
+ "sha256:5b06af87df13818d14f08a028e42f566640aef80805c3b50c5056b086e3c2b9c",
+ "sha256:833b46966687b3de7f438c761ac475213e53b306740f1abfaa86e1d1aae56aa8"
+ ],
+ "markers": "python_version < '3.4'",
+ "version": "==3.4.0.3"
+ },
+ "six": {
+ "hashes": [
+ "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c",
+ "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"
+ ],
+ "index": "pypi",
+ "version": "==1.12.0"
+ },
+ "smbus2": {
+ "hashes": [
+ "sha256:4d5aae2f65d39056bb44e8906d5c503f8ee7e02fadb0a6433f1091a9ce528dde"
+ ],
+ "index": "pypi",
+ "version": "==0.2.3"
+ },
+ "sympy": {
+ "hashes": [
+ "sha256:71a11e5686ae7ab6cb8feb5bd2651ef4482f8fd43a7c27e645a165e4353b23e1",
+ "sha256:f9b00ec76151c98470e84f1da2d7d03633180b71fb318428ddccce1c867d3eaa"
+ ],
+ "index": "pypi",
+ "version": "==1.4"
+ },
+ "tqdm": {
+ "hashes": [
+ "sha256:0a860bf2683fdbb4812fe539a6c22ea3f1777843ea985cb8c3807db448a0f7ab",
+ "sha256:e288416eecd4df19d12407d0c913cbf77aa8009d7fddb18f632aded3bdbdda6b"
+ ],
+ "index": "pypi",
+ "version": "==4.32.1"
+ },
+ "urllib3": {
+ "hashes": [
+ "sha256:b246607a25ac80bedac05c6f282e3cdaf3afb65420fd024ac94435cabe6e18d1",
+ "sha256:dbe59173209418ae49d485b87d1681aefa36252ee85884c31346debd19463232"
+ ],
+ "index": "pypi",
+ "version": "==1.25.3"
+ },
+ "utm": {
+ "hashes": [
+ "sha256:a6608a67df84418fd959a79b228b90ab55b2ae877827f9c210947104c5a75d0e"
+ ],
+ "index": "pypi",
+ "version": "==0.4.2"
+ },
+ "websocket-client": {
+ "hashes": [
+ "sha256:1151d5fb3a62dc129164292e1227655e4bbc5dd5340a5165dfae61128ec50aa9",
+ "sha256:1fd5520878b68b84b5748bb30e592b10d0a91529d5383f74f4964e72b297fd3a"
+ ],
+ "index": "pypi",
+ "version": "==0.56.0"
+ },
+ "werkzeug": {
+ "hashes": [
+ "sha256:865856ebb55c4dcd0630cdd8f3331a1847a819dda7e8c750d3db6f2aa6c0209c",
+ "sha256:a0b915f0815982fb2a09161cb8f31708052d0951c3ba433ccc5e1aa276507ca6"
+ ],
+ "version": "==0.15.4"
+ },
+ "wrapt": {
+ "hashes": [
+ "sha256:4aea003270831cceb8a90ff27c4031da6ead7ec1886023b80ce0dfe0adf61533"
+ ],
+ "version": "==1.11.1"
+ }
+ },
+ "develop": {
+ "absl-py": {
+ "hashes": [
+ "sha256:b943d1c567743ed0455878fcd60bc28ac9fae38d129d1ccfad58079da00b8951"
+ ],
+ "version": "==0.7.1"
+ },
+ "adal": {
+ "hashes": [
+ "sha256:82e84fa0b442caf8131f1e87a7ebee2546f57ab16a8917a599a02b6e455cb1b0",
+ "sha256:b6edd095be66561382bdaa59d40b04490e93149fb3b7fa44c1fa5504eed5b8b9"
+ ],
+ "version": "==1.2.1"
+ },
+ "aenum": {
+ "hashes": [
+ "sha256:3df9b84cce5dc9ed77c337079f97b66c44c0053eb87d6f4d46b888dc45801e38",
+ "sha256:7a77c205c4bc9d7fe9bd73b3193002d724aebf5909fa0d297534208953891ec8",
+ "sha256:a3208e4b28db3a7b232ff69b934aef2ea1bf27286d9978e1e597d46f490e4687"
+ ],
+ "index": "pypi",
+ "version": "==2.1.2"
+ },
+ "amqp": {
+ "hashes": [
+ "sha256:aa4409446139676943a2eaa27d5f58caf750f4ca5a89f888c452afd86be6a67d",
+ "sha256:cbb6f87d53cac612a594f982b717cc1c54c6a1e17943a0a0d32dc6cc9e2120c8"
+ ],
+ "version": "==2.5.0"
+ },
+ "asn1crypto": {
+ "hashes": [
+ "sha256:2f1adbb7546ed199e3c90ef23ec95c5cf3585bac7d11fb7eb562a3fe89c64e87",
+ "sha256:9d5c20441baf0cb60a4ac34cc447c6c189024b6b4c6cd7877034f4965c464e49"
+ ],
+ "version": "==0.24.0"
+ },
+ "astor": {
+ "hashes": [
+ "sha256:0e41295809baf43ae8303350e031aff81ae52189b6f881f36d623fa8b2f1960e",
+ "sha256:37a6eed8b371f1228db08234ed7f6cfdc7817a3ed3824797e20cbb11dc2a7862"
+ ],
+ "version": "==0.8.0"
+ },
+ "astroid": {
+ "hashes": [
+ "sha256:87de48a92e29cedf7210ffa853d11441e7ad94cb47bacd91b023499b51cbc756",
+ "sha256:d25869fc7f44f1d9fb7d24fd7ea0639656f5355fc3089cd1f3d18c6ec6b124c7"
+ ],
+ "version": "==1.6.6"
+ },
+ "attrs": {
+ "hashes": [
+ "sha256:69c0dbf2ed392de1cb5ec704444b08a5ef81680a61cb899dc08127123af36a79",
+ "sha256:f0b870f674851ecbfbbbd364d6b5cbdff9dcedbc7f3f5e18a6891057f21fe399"
+ ],
+ "version": "==19.1.0"
+ },
+ "azure-batch": {
+ "hashes": [
+ "sha256:017be21a9e6db92473d2e33170d5dd445596fc70d706f73552ac9c6b57a6ef1c",
+ "sha256:cd71c7ebb5beab174b6225bbf79ae18d6db0c8d63227a7e514da0a75f138364c"
+ ],
+ "index": "pypi",
+ "version": "==4.1.3"
+ },
+ "azure-common": {
+ "hashes": [
+ "sha256:2606ae77ff81c0036965b92ec2efe03eaec02a66714140ca0f7aa401b8b9bbb0",
+ "sha256:c908621a71eb4ee9fab0962e35d3c27a18f09a854d8359c2f32c15b3f4fc576e"
+ ],
+ "index": "pypi",
+ "version": "==1.1.16"
+ },
+ "azure-nspkg": {
+ "hashes": [
+ "sha256:a908f96a695b12e31b6c56cda0bb8e6d2a054283c350881667f300b8563ece33",
+ "sha256:af81fd4512be5ad0834b8e82c43bbe80b016bd295a8794fac28d69bf243357e0",
+ "sha256:ce4173e06f2f423775c4ca8a635e9a89b5fe8e4ba9fefbbe2a1e0d525072392c"
+ ],
+ "index": "pypi",
+ "version": "==3.0.1"
+ },
+ "azure-storage-blob": {
+ "hashes": [
+ "sha256:308058abfd789f5830d91f6407eb00a7b04925b2b9af267aecfb46c335802cdc",
+ "sha256:8cab5420ba6646ead09fdb497646f735b12645cba8efed96a86f7b370e175ade"
+ ],
+ "index": "pypi",
+ "version": "==1.3.1"
+ },
+ "azure-storage-common": {
+ "hashes": [
+ "sha256:585658ebc784e843a285732a69aa69ef922e17c3063460c2c7b27c89f377004c",
+ "sha256:a412a78618e82bf99030ce56f1f2d5fc6c2c2eec7ee1beda86ce6ea5f2c9196b"
+ ],
+ "index": "pypi",
+ "version": "==1.3.0"
+ },
+ "azure-storage-nspkg": {
+ "hashes": [
+ "sha256:4fc4685aef941eab2f7fb53824254cca2e38f2a1bf33cda0c8ae654fe15827d6",
+ "sha256:855315c038c0e695868025127e1b3057a1f984af9ccfbaeac4fbfd6c5dd3b466"
+ ],
+ "index": "pypi",
+ "version": "==3.0.0"
+ },
+ "backports-abc": {
+ "hashes": [
+ "sha256:033be54514a03e255df75c5aee8f9e672f663f93abb723444caec8fe43437bde",
+ "sha256:52089f97fe7a9aa0d3277b220c1d730a85aefd64e1b2664696fe35317c5470a7"
+ ],
+ "index": "pypi",
+ "version": "==0.5"
+ },
+ "backports.functools-lru-cache": {
+ "hashes": [
+ "sha256:9d98697f088eb1b0fa451391f91afb5e3ebde16bbdb272819fd091151fda4f1a",
+ "sha256:f0b0e4eba956de51238e17573b7087e852dfe9854afd2e9c873f73fc0ca0a6dd"
+ ],
+ "markers": "python_version < '3.2'",
+ "version": "==1.5"
+ },
+ "backports.lzma": {
+ "hashes": [
+ "sha256:50829db66f0445442f6c796bba0ca62d1f87f54760c4682b6d1489e729a43744"
+ ],
+ "index": "pypi",
+ "version": "==0.0.13"
+ },
+ "backports.shutil-get-terminal-size": {
+ "hashes": [
+ "sha256:0975ba55054c15e346944b38956a4c9cbee9009391e41b86c68990effb8c1f64",
+ "sha256:713e7a8228ae80341c70586d1cc0a8caa5207346927e23d09dcbcaf18eadec80"
+ ],
+ "markers": "python_version == '2.7'",
+ "version": "==1.0.0"
+ },
+ "backports.weakref": {
+ "hashes": [
+ "sha256:81bc9b51c0abc58edc76aefbbc68c62a787918ffe943a37947e162c3f8e19e82",
+ "sha256:bc4170a29915f8b22c9e7c4939701859650f2eb84184aee80da329ac0b9825c2"
+ ],
+ "version": "==1.0.post1"
+ },
+ "billiard": {
+ "hashes": [
+ "sha256:756bf323f250db8bf88462cd042c992ba60d8f5e07fc5636c24ba7d6f4261d84"
+ ],
+ "version": "==3.6.0.0"
+ },
+ "bincopy": {
+ "hashes": [
+ "sha256:61d02c09910635599127056d2707c22bfa310cb31f935fbfdda406639017717e",
+ "sha256:a0e31dc5de70bffaf717bb76b136857eb78ea138fb49dc5a1bf06303f103dff8"
+ ],
+ "index": "pypi",
+ "version": "==16.0.0"
+ },
+ "bleach": {
+ "hashes": [
+ "sha256:978e758599b54cd3caa2e160d74102879b230ea8dc93871d0783721eef58bc65",
+ "sha256:e67f46adcec78dbc3c04462f3aba3213a673d5652eba2609ed1ef15492a44b8d"
+ ],
+ "index": "pypi",
+ "version": "==1.5.0"
+ },
+ "boto": {
+ "hashes": [
+ "sha256:147758d41ae7240dc989f0039f27da8ca0d53734be0eb869ef16e3adcfa462e8",
+ "sha256:ea0d3b40a2d852767be77ca343b58a9e3a4b00d9db440efb8da74b4e58025e5a"
+ ],
+ "index": "pypi",
+ "version": "==2.49.0"
+ },
+ "boto3": {
+ "hashes": [
+ "sha256:794a9a4b6a9e40c1ac57a377de609872d28d62afe4295c48cdc1b1c92f96ab8e",
+ "sha256:962b078568cc520869ea2842f307864c9abc30ad5ed160e12b2a89debf220161"
+ ],
+ "index": "pypi",
+ "version": "==1.9.168"
+ },
+ "botocore": {
+ "hashes": [
+ "sha256:675f2b66af486dd02f5825601bb0c8378773999f8705c6f75450849ca41fed80",
+ "sha256:c3fc314c0e0aa13aa024d272d991e23d37550050abf96b3c7dea889ed1743723"
+ ],
+ "version": "==1.12.168"
+ },
+ "celery": {
+ "hashes": [
+ "sha256:4c4532aa683f170f40bd76f928b70bc06ff171a959e06e71bf35f2f9d6031ef9",
+ "sha256:528e56767ae7e43a16cfef24ee1062491f5754368d38fcfffa861cdb9ef219be"
+ ],
+ "index": "pypi",
+ "version": "==4.3.0"
+ },
+ "certifi": {
+ "hashes": [
+ "sha256:59b7658e26ca9c7339e00f8f4636cdfe59d34fa37b9b04f6f9e9926b3cece1a5",
+ "sha256:b26104d6835d1f5e49452a26eb2ff87fe7090b89dfcaee5ea2212697e1e1d7ae"
+ ],
+ "version": "==2019.3.9"
+ },
+ "cffi": {
+ "hashes": [
+ "sha256:041c81822e9f84b1d9c401182e174996f0bae9991f33725d059b771744290774",
+ "sha256:046ef9a22f5d3eed06334d01b1e836977eeef500d9b78e9ef693f9380ad0b83d",
+ "sha256:066bc4c7895c91812eff46f4b1c285220947d4aa46fa0a2651ff85f2afae9c90",
+ "sha256:066c7ff148ae33040c01058662d6752fd73fbc8e64787229ea8498c7d7f4041b",
+ "sha256:2444d0c61f03dcd26dbf7600cf64354376ee579acad77aef459e34efcb438c63",
+ "sha256:300832850b8f7967e278870c5d51e3819b9aad8f0a2c8dbe39ab11f119237f45",
+ "sha256:34c77afe85b6b9e967bd8154e3855e847b70ca42043db6ad17f26899a3df1b25",
+ "sha256:46de5fa00f7ac09f020729148ff632819649b3e05a007d286242c4882f7b1dc3",
+ "sha256:4aa8ee7ba27c472d429b980c51e714a24f47ca296d53f4d7868075b175866f4b",
+ "sha256:4d0004eb4351e35ed950c14c11e734182591465a33e960a4ab5e8d4f04d72647",
+ "sha256:4e3d3f31a1e202b0f5a35ba3bc4eb41e2fc2b11c1eff38b362de710bcffb5016",
+ "sha256:50bec6d35e6b1aaeb17f7c4e2b9374ebf95a8975d57863546fa83e8d31bdb8c4",
+ "sha256:55cad9a6df1e2a1d62063f79d0881a414a906a6962bc160ac968cc03ed3efcfb",
+ "sha256:5662ad4e4e84f1eaa8efce5da695c5d2e229c563f9d5ce5b0113f71321bcf753",
+ "sha256:59b4dc008f98fc6ee2bb4fd7fc786a8d70000d058c2bbe2698275bc53a8d3fa7",
+ "sha256:73e1ffefe05e4ccd7bcea61af76f36077b914f92b76f95ccf00b0c1b9186f3f9",
+ "sha256:a1f0fd46eba2d71ce1589f7e50a9e2ffaeb739fb2c11e8192aa2b45d5f6cc41f",
+ "sha256:a2e85dc204556657661051ff4bab75a84e968669765c8a2cd425918699c3d0e8",
+ "sha256:a5457d47dfff24882a21492e5815f891c0ca35fefae8aa742c6c263dac16ef1f",
+ "sha256:a8dccd61d52a8dae4a825cdbb7735da530179fea472903eb871a5513b5abbfdc",
+ "sha256:ae61af521ed676cf16ae94f30fe202781a38d7178b6b4ab622e4eec8cefaff42",
+ "sha256:b012a5edb48288f77a63dba0840c92d0504aa215612da4541b7b42d849bc83a3",
+ "sha256:d2c5cfa536227f57f97c92ac30c8109688ace8fa4ac086d19d0af47d134e2909",
+ "sha256:d42b5796e20aacc9d15e66befb7a345454eef794fdb0737d1af593447c6c8f45",
+ "sha256:dee54f5d30d775f525894d67b1495625dd9322945e7fee00731952e0368ff42d",
+ "sha256:e070535507bd6aa07124258171be2ee8dfc19119c28ca94c9dfb7efd23564512",
+ "sha256:e1ff2748c84d97b065cc95429814cdba39bcbd77c9c85c89344b317dc0d9cbff",
+ "sha256:ed851c75d1e0e043cbf5ca9a8e1b13c4c90f3fbd863dacb01c0808e2b5204201"
+ ],
+ "index": "pypi",
+ "version": "==1.12.3"
+ },
+ "chardet": {
+ "hashes": [
+ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
+ "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
+ ],
+ "index": "pypi",
+ "version": "==3.0.4"
+ },
+ "click": {
+ "hashes": [
+ "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13",
+ "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"
+ ],
+ "version": "==7.0"
+ },
+ "cloudpickle": {
+ "hashes": [
+ "sha256:603244e0f552b72a267d47a7d9b347b27a3430f58a0536037a290e7e0e212ecf",
+ "sha256:b8ba7e322f2394b9bbbdc1c976e6442c2c02acc784cb9e553cee9186166a6890"
+ ],
+ "version": "==1.2.1"
+ },
+ "configparser": {
+ "hashes": [
+ "sha256:8be81d89d6e7b4c0d4e44bcc525845f6da25821de80cb5e06e7e0238a2899e32",
+ "sha256:da60d0014fd8c55eb48c1c5354352e363e2d30bbf7057e5e171a468390184c75"
+ ],
+ "markers": "python_version == '2.7'",
+ "version": "==3.7.4"
+ },
+ "control": {
+ "hashes": [
+ "sha256:726e8c36a253a54c8886df31f860d740d70de4f8b041421d5df078c3bff3aadb"
+ ],
+ "index": "pypi",
+ "version": "==0.8.2"
+ },
+ "cryptography": {
+ "hashes": [
+ "sha256:24b61e5fcb506424d3ec4e18bca995833839bf13c59fc43e530e488f28d46b8c",
+ "sha256:25dd1581a183e9e7a806fe0543f485103232f940fcfc301db65e630512cce643",
+ "sha256:3452bba7c21c69f2df772762be0066c7ed5dc65df494a1d53a58b683a83e1216",
+ "sha256:41a0be220dd1ed9e998f5891948306eb8c812b512dc398e5a01846d855050799",
+ "sha256:5751d8a11b956fbfa314f6553d186b94aa70fdb03d8a4d4f1c82dcacf0cbe28a",
+ "sha256:5f61c7d749048fa6e3322258b4263463bfccefecb0dd731b6561cb617a1d9bb9",
+ "sha256:72e24c521fa2106f19623a3851e9f89ddfdeb9ac63871c7643790f872a305dfc",
+ "sha256:7b97ae6ef5cba2e3bb14256625423413d5ce8d1abb91d4f29b6d1a081da765f8",
+ "sha256:961e886d8a3590fd2c723cf07be14e2a91cf53c25f02435c04d39e90780e3b53",
+ "sha256:96d8473848e984184b6728e2c9d391482008646276c3ff084a1bd89e15ff53a1",
+ "sha256:ae536da50c7ad1e002c3eee101871d93abdc90d9c5f651818450a0d3af718609",
+ "sha256:b0db0cecf396033abb4a93c95d1602f268b3a68bb0a9cc06a7cff587bb9a7292",
+ "sha256:cfee9164954c186b191b91d4193989ca994703b2fff406f71cf454a2d3c7327e",
+ "sha256:e6347742ac8f35ded4a46ff835c60e68c22a536a8ae5c4422966d06946b6d4c6",
+ "sha256:f27d93f0139a3c056172ebb5d4f9056e770fdf0206c2f422ff2ebbad142e09ed",
+ "sha256:f57b76e46a58b63d1c6375017f4564a28f19a5ca912691fd2e4261b3414b618d"
+ ],
+ "index": "pypi",
+ "version": "==2.7"
+ },
+ "cycler": {
+ "hashes": [
+ "sha256:1d8a5ae1ff6c5cf9b93e8811e581232ad8920aeec647c37316ceac982b08cb2d",
+ "sha256:cd7b2d1018258d7247a71425e9f26463dfb444d411c39569972f4ce586b0c9d8"
+ ],
+ "version": "==0.10.0"
+ },
+ "cython": {
+ "hashes": [
+ "sha256:0afa0b121b89de619e71587e25702e2b7068d7da2164c47e6eee80c17823a62f",
+ "sha256:1c608ba76f7a20cc9f0c021b7fe5cb04bc1a70327ae93a9298b1bc3e0edddebe",
+ "sha256:26229570d6787ff3caa932fe9d802960f51a89239b990d275ae845405ce43857",
+ "sha256:2a9deafa437b6154cac2f25bb88e0bfd075a897c8dc847669d6f478d7e3ee6b1",
+ "sha256:2f28396fbce6d9d68a40edbf49a6729cf9d92a4d39ff0f501947a89188e9099f",
+ "sha256:3983dd7b67297db299b403b29b328d9e03e14c4c590ea90aa1ad1d7b35fb178b",
+ "sha256:4100a3f8e8bbe47d499cdac00e56d5fe750f739701ea52dc049b6c56f5421d97",
+ "sha256:51abfaa7b6c66f3f18028876713c8804e73d4c2b6ceddbcbcfa8ec62429377f0",
+ "sha256:61c24f4554efdb8fb1ac6c8e75dab301bcdf2b7b739ed0c2b267493bb43163c5",
+ "sha256:700ccf921b2fdc9b23910e95b5caae4b35767685e0812343fa7172409f1b5830",
+ "sha256:7b41eb2e792822a790cb2a171df49d1a9e0baaa8e81f58077b7380a273b93d5f",
+ "sha256:803987d3b16d55faa997bfc12e8b97f1091f145930dee229b020487aed8a1f44",
+ "sha256:99af5cfcd208c81998dcf44b3ca466dee7e17453cfb50e98b87947c3a86f8753",
+ "sha256:9faea1cca34501c7e139bc7ef8e504d532b77865c58592493e2c154a003b450f",
+ "sha256:a7ba4c9a174db841cfee9a0b92563862a0301d7ca543334666c7266b541f141a",
+ "sha256:b26071c2313d1880599c69fd831a07b32a8c961ba69d7ccbe5db1cd8d319a4ca",
+ "sha256:b49dc8e1116abde13a3e6a9eb8da6ab292c5a3325155fb872e39011b110b37e6",
+ "sha256:bd40def0fd013569887008baa6da9ca428e3d7247adeeaeada153006227bb2e7",
+ "sha256:bfd0db770e8bd4e044e20298dcae6dfc42561f85d17ee546dcd978c8b23066ae",
+ "sha256:c2fad1efae5889925c8fd7867fdd61f59480e4e0b510f9db096c912e884704f1",
+ "sha256:c81aea93d526ccf6bc0b842c91216ee9867cd8792f6725a00f19c8b5837e1715",
+ "sha256:da786e039b4ad2bce3d53d4799438cf1f5e01a0108f1b8d78ac08e6627281b1a",
+ "sha256:deab85a069397540987082d251e9c89e0e5b2e3e044014344ff81f60e211fc4b",
+ "sha256:e3f1e6224c3407beb1849bdc5ae3150929e593e4cffff6ca41c6ec2b10942c80",
+ "sha256:e74eb224e53aae3943d66e2d29fe42322d5753fd4c0641329bccb7efb3a46552",
+ "sha256:ee697c7ea65cb14915a64f36874da8ffc2123df43cf8bc952172e04a26656cd6",
+ "sha256:f37792b16d11606c28e428460bd6a3d14b8917b109e77cdbe4ca78b0b9a52c87",
+ "sha256:fd2906b54cbf879c09d875ad4e4687c58d87f5ed03496063fec1c9065569fd5d"
+ ],
+ "index": "pypi",
+ "version": "==0.29.10"
+ },
+ "datadog": {
+ "hashes": [
+ "sha256:0e33727bd9ef0b8201359accdf12f61fb58ab541bf4062693aca16653f8e7a0a",
+ "sha256:995e51d142ae3624c86c78369b268f23386bb207df5345d718c241718387875c"
+ ],
+ "index": "pypi",
+ "version": "==0.29.3"
+ },
+ "decorator": {
+ "hashes": [
+ "sha256:86156361c50488b84a3f148056ea716ca587df2f0de1d34750d35c21312725de",
+ "sha256:f069f3a01830ca754ba5258fde2278454a0b5b79e0d7f5c13b3b97e57d4acff6"
+ ],
+ "index": "pypi",
+ "version": "==4.4.0"
+ },
+ "defusedxml": {
+ "hashes": [
+ "sha256:6687150770438374ab581bb7a1b327a847dd9c5749e396102de3fad4e8a3ef93",
+ "sha256:f684034d135af4c6cbb949b8a4d2ed61634515257a67299e5f940fbaa34377f5"
+ ],
+ "version": "==0.6.0"
+ },
+ "dlib": {
+ "hashes": [
+ "sha256:92587c81b0165e933593f505fdf099dface0d0f8ec874b1d8655fc774598911f"
+ ],
+ "index": "pypi",
+ "version": "==19.17.0"
+ },
+ "docutils": {
+ "hashes": [
+ "sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6",
+ "sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274",
+ "sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6"
+ ],
+ "version": "==0.14"
+ },
+ "dominate": {
+ "hashes": [
+ "sha256:4076735c0745fe771e57b2313dbb4bfeec42731816ee23cee509f66e8912aa51",
+ "sha256:4b9fd42d2824b79761799590697db45bf93daad511b130c50513af38da33df9b"
+ ],
+ "index": "pypi",
+ "version": "==2.3.5"
+ },
+ "elasticsearch": {
+ "hashes": [
+ "sha256:cbc73831c63fa2824538df76fcb2c4be007b43dbd9e7788ae70ea6d24109925b",
+ "sha256:d1b176b87a7fb75dca82978c82a4023e8b21cbc98f4018cb51190fb0b8b43764"
+ ],
+ "index": "pypi",
+ "version": "==7.0.2"
+ },
+ "entium": {
+ "hashes": [
+ "sha256:233f39c6b5477e0c6fffd8d5cb7fc9df9deab80c79c7fb77e91f6d046782b0ce",
+ "sha256:4b14b4810a97ab041b629a0b59d21a98f5e197ee623d7b14925755ec4fd6888a"
+ ],
+ "index": "pypi",
+ "version": "==0.1.4"
+ },
+ "entrypoints": {
+ "hashes": [
+ "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19",
+ "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451"
+ ],
+ "version": "==0.3"
+ },
+ "enum34": {
+ "hashes": [
+ "sha256:2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850",
+ "sha256:644837f692e5f550741432dd3f223bbb9852018674981b1664e5dc339387588a",
+ "sha256:6bd0f6ad48ec2aa117d3d141940d484deccda84d4fcd884f5c3d93c23ecd8c79",
+ "sha256:8ad8c4783bf61ded74527bffb48ed9b54166685e4230386a9ed9b1279e2df5b1"
+ ],
+ "markers": "python_version < '3'",
+ "version": "==1.1.6"
+ },
+ "fastcluster": {
+ "hashes": [
+ "sha256:0024b1304d4618a32900473b809265694bc6d0a10bfbc272407443318644d405",
+ "sha256:0b33b076ea98939742e0734e944c903c8c67af3eecd5a9f8b4349407c1affdd3",
+ "sha256:244d400a81d23b48f2b825e50e99e1ff3c7d2be2acc40942e3359b4deef68483",
+ "sha256:2bb3bf8e1c7af42e47ef24bc2386a1d3e6ec8dc5e6be4123a491a36b89227b49",
+ "sha256:539d84d43fbe541a38d94c84bf0469c430cb7cda488364941ce57f680a07b091",
+ "sha256:5e7d81385bbc2148c554c4aaa32e26a00fbadc1190d5bad9c8719f6432629307",
+ "sha256:642e4d92220c1deede1e89409c5ad366e4a3f3ed55fff0a4e325d4eb2574d65a",
+ "sha256:66c868fdfc161e5c45cdf399f1274216602ea82c9fc46c632c9602dbaa149840",
+ "sha256:6952c9d25b3ea60d6a53ee92205e7f16cc6baf7caa4776fb1e55dc6e8e2965f2",
+ "sha256:8606da6f6f51f81c3b4e000edeb8668711a1769a6ebf3c99ab98f9c6d2fb7534",
+ "sha256:8d552d29ed054ce20f5bb0445b51bd7b6b8088fdae334625b4a9950189dcc2bf",
+ "sha256:922735fde2848a6f0478c6968048a16a5d3d6ba6e1d1a9596d578b59dce719d7",
+ "sha256:9f3cd227a9ebeec090e4186a63e46cd87d121968bd1d45ea8a7c2d483bc082fb",
+ "sha256:a382cb411610ca06a69e7b131239f0bb02961fec762d5b6804e653a32cd5ab52",
+ "sha256:a986b3afe823bcaea3dad9de1485b176c6dd5b0e2f154ede71aaf6635e82e159",
+ "sha256:b1902ab52418c6f4c2f3f7439aea711c6b5aa9bbb4c97b6d4b0c6f5e5c894342",
+ "sha256:bb56f6c7343bbb68beb1ffd13abdb87ce7a84ab391b3a4e63ed5c02b2d1ce46f",
+ "sha256:c2e5d11f5f96e6861fd632246f18bc6592ac439f236caffd4d2a75697a6f8969",
+ "sha256:c61973bb16117ee16b7642ff9da8e0899fb4d5eb5d0cc9c56d3269551ccd6307",
+ "sha256:d2deec11a6625c5578325f4dd10980e2981d1f1d1e658c7c79f2497377f92bdf",
+ "sha256:e0f2feb03f67b12f25538aa05b1150c7a2c1cd1c21ad7d0bde94e8169ef46627",
+ "sha256:e32e7287c47291eca2c83cd5cc6a5007eff2da00c12ac21fd721a16d0c428059",
+ "sha256:e889ea36c4e469ff3fb2a6a868c8e557fc988a81cd1cf3d09876107e59ee9cbd",
+ "sha256:e96f3b65e3748f2be06aa0977a00872ddeca4f8959703126f2b103978243bbdd"
+ ],
+ "index": "pypi",
+ "version": "==1.1.25"
+ },
+ "fasteners": {
+ "hashes": [
+ "sha256:007e4d2b2d4a10093f67e932e5166722d2eab83b77724156e92ad013c6226574",
+ "sha256:3a176da6b70df9bb88498e1a18a9e4a8579ed5b9141207762368a1017bf8f5ef"
+ ],
+ "index": "pypi",
+ "version": "==0.15"
+ },
+ "flask": {
+ "hashes": [
+ "sha256:ad7c6d841e64296b962296c2c2dabc6543752985727af86a975072dea984b6f3",
+ "sha256:e7d32475d1de5facaa55e3958bc4ec66d3762076b074296aa50ef8fdc5b9df61"
+ ],
+ "index": "pypi",
+ "version": "==1.0.3"
+ },
+ "flask-cors": {
+ "hashes": [
+ "sha256:72170423eb4612f0847318afff8c247b38bd516b7737adfc10d1c2cdbb382d16",
+ "sha256:f4d97201660e6bbcff2d89d082b5b6d31abee04b1b3003ee073a6fd25ad1d69a"
+ ],
+ "index": "pypi",
+ "version": "==3.0.8"
+ },
+ "flask-socketio": {
+ "hashes": [
+ "sha256:aced332903522a52822fb1e21744549510ce8b26e074422d4cd9aff68e43be5b",
+ "sha256:f6f7e0205f0dd92d98a87e3f6d26d94ade29ca380ba383b505070674c804ae2e"
+ ],
+ "index": "pypi",
+ "version": "==4.1.0"
+ },
+ "funcsigs": {
+ "hashes": [
+ "sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca",
+ "sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50"
+ ],
+ "markers": "python_version < '3.3'",
+ "version": "==1.0.2"
+ },
+ "functools32": {
+ "hashes": [
+ "sha256:89d824aa6c358c421a234d7f9ee0bd75933a67c29588ce50aaa3acdf4d403fa0",
+ "sha256:f6253dfbe0538ad2e387bd8fdfd9293c925d63553f5813c4e587745416501e6d"
+ ],
+ "markers": "python_version < '3'",
+ "version": "==3.2.3.post2"
+ },
+ "future": {
+ "hashes": [
+ "sha256:67045236dcfd6816dc439556d009594abf643e5eb48992e36beac09c2ca659b8"
+ ],
+ "index": "pypi",
+ "version": "==0.17.1"
+ },
+ "futures": {
+ "hashes": [
+ "sha256:9ec02aa7d674acb8618afb127e27fde7fc68994c0437ad759fa094a574adb265",
+ "sha256:ec0a6cb848cc212002b9828c3e34c675e0c9ff6741dc445cab6fdd4e1085d1f1"
+ ],
+ "markers": "python_version < '3.2'",
+ "version": "==3.2.0"
+ },
+ "gast": {
+ "hashes": [
+ "sha256:fe939df4583692f0512161ec1c880e0a10e71e6a232da045ab8edd3756fbadf0"
+ ],
+ "version": "==0.2.2"
+ },
+ "geoalchemy2": {
+ "hashes": [
+ "sha256:0d1c9ea3ec13f6a522ccc3ffd2569ac524a6c6e80bab883e8805b28c48e77143",
+ "sha256:4dc4c6c2bda0fc82cccab4aaff185a6570e13a5351d85e29e12984a55d4138ee"
+ ],
+ "index": "pypi",
+ "version": "==0.6.3"
+ },
+ "gevent": {
+ "hashes": [
+ "sha256:0774babec518a24d9a7231d4e689931f31b332c4517a771e532002614e270a64",
+ "sha256:0e1e5b73a445fe82d40907322e1e0eec6a6745ca3cea19291c6f9f50117bb7ea",
+ "sha256:0ff2b70e8e338cf13bedf146b8c29d475e2a544b5d1fe14045aee827c073842c",
+ "sha256:107f4232db2172f7e8429ed7779c10f2ed16616d75ffbe77e0e0c3fcdeb51a51",
+ "sha256:14b4d06d19d39a440e72253f77067d27209c67e7611e352f79fe69e0f618f76e",
+ "sha256:1b7d3a285978b27b469c0ff5fb5a72bcd69f4306dbbf22d7997d83209a8ba917",
+ "sha256:1eb7fa3b9bd9174dfe9c3b59b7a09b768ecd496debfc4976a9530a3e15c990d1",
+ "sha256:2711e69788ddb34c059a30186e05c55a6b611cb9e34ac343e69cf3264d42fe1c",
+ "sha256:28a0c5417b464562ab9842dd1fb0cc1524e60494641d973206ec24d6ec5f6909",
+ "sha256:3249011d13d0c63bea72d91cec23a9cf18c25f91d1f115121e5c9113d753fa12",
+ "sha256:44089ed06a962a3a70e96353c981d628b2d4a2f2a75ea5d90f916a62d22af2e8",
+ "sha256:4bfa291e3c931ff3c99a349d8857605dca029de61d74c6bb82bd46373959c942",
+ "sha256:50024a1ee2cf04645535c5ebaeaa0a60c5ef32e262da981f4be0546b26791950",
+ "sha256:53b72385857e04e7faca13c613c07cab411480822ac658d97fd8a4ddbaf715c8",
+ "sha256:74b7528f901f39c39cdbb50cdf08f1a2351725d9aebaef212a29abfbb06895ee",
+ "sha256:7d0809e2991c9784eceeadef01c27ee6a33ca09ebba6154317a257353e3af922",
+ "sha256:896b2b80931d6b13b5d9feba3d4eebc67d5e6ec54f0cf3339d08487d55d93b0e",
+ "sha256:8d9ec51cc06580f8c21b41fd3f2b3465197ba5b23c00eb7d422b7ae0380510b0",
+ "sha256:9f7a1e96fec45f70ad364e46de32ccacab4d80de238bd3c2edd036867ccd48ad",
+ "sha256:ab4dc33ef0e26dc627559786a4fba0c2227f125db85d970abbf85b77506b3f51",
+ "sha256:d1e6d1f156e999edab069d79d890859806b555ce4e4da5b6418616322f0a3df1",
+ "sha256:d752bcf1b98174780e2317ada12013d612f05116456133a6acf3e17d43b71f05",
+ "sha256:e5bcc4270671936349249d26140c267397b7b4b1381f5ec8b13c53c5b53ab6e1"
+ ],
+ "index": "pypi",
+ "version": "==1.4.0"
+ },
+ "git-pylint-commit-hook": {
+ "hashes": [
+ "sha256:e1d39e7856b3ef0a0269121ca210dc3f5a97da158b322411e8e1185918a91b3c"
+ ],
+ "index": "pypi",
+ "version": "==2.5.1"
+ },
+ "greenlet": {
+ "hashes": [
+ "sha256:000546ad01e6389e98626c1367be58efa613fa82a1be98b0c6fc24b563acc6d0",
+ "sha256:0d48200bc50cbf498716712129eef819b1729339e34c3ae71656964dac907c28",
+ "sha256:23d12eacffa9d0f290c0fe0c4e81ba6d5f3a5b7ac3c30a5eaf0126bf4deda5c8",
+ "sha256:37c9ba82bd82eb6a23c2e5acc03055c0e45697253b2393c9a50cef76a3985304",
+ "sha256:51503524dd6f152ab4ad1fbd168fc6c30b5795e8c70be4410a64940b3abb55c0",
+ "sha256:8041e2de00e745c0e05a502d6e6db310db7faa7c979b3a5877123548a4c0b214",
+ "sha256:81fcd96a275209ef117e9ec91f75c731fa18dcfd9ffaa1c0adbdaa3616a86043",
+ "sha256:853da4f9563d982e4121fed8c92eea1a4594a2299037b3034c3c898cb8e933d6",
+ "sha256:8b4572c334593d449113f9dc8d19b93b7b271bdbe90ba7509eb178923327b625",
+ "sha256:9416443e219356e3c31f1f918a91badf2e37acf297e2fa13d24d1cc2380f8fbc",
+ "sha256:9854f612e1b59ec66804931df5add3b2d5ef0067748ea29dc60f0efdcda9a638",
+ "sha256:99a26afdb82ea83a265137a398f570402aa1f2b5dfb4ac3300c026931817b163",
+ "sha256:a19bf883b3384957e4a4a13e6bd1ae3d85ae87f4beb5957e35b0be287f12f4e4",
+ "sha256:a9f145660588187ff835c55a7d2ddf6abfc570c2651c276d3d4be8a2766db490",
+ "sha256:ac57fcdcfb0b73bb3203b58a14501abb7e5ff9ea5e2edfa06bb03035f0cff248",
+ "sha256:bcb530089ff24f6458a81ac3fa699e8c00194208a724b644ecc68422e1111939",
+ "sha256:beeabe25c3b704f7d56b573f7d2ff88fc99f0138e43480cecdfcaa3b87fe4f87",
+ "sha256:d634a7ea1fc3380ff96f9e44d8d22f38418c1c381d5fac680b272d7d90883720",
+ "sha256:d97b0661e1aead761f0ded3b769044bb00ed5d33e1ec865e891a8b128bf7c656"
+ ],
+ "markers": "platform_python_implementation == 'CPython'",
+ "version": "==0.4.15"
+ },
+ "grpcio": {
+ "hashes": [
+ "sha256:0232add03144dd3cf9b660e2718244cb8e175370dca4d3855cb4e489a7811b53",
+ "sha256:0f20e6dcb1b8662cdca033bb97c0a8116a5343e3ebc7f71c5fe7f89039978350",
+ "sha256:10b07a623d33d4966f45c85d410bc6a79c5ac6341f06c3beda6c22be12cbfe07",
+ "sha256:10c0476d5a52d21f402fc073745dc43b87cc8e080a1f49bbff4e1059019310fb",
+ "sha256:289dae0b35c59d191c524e976dd0a6f8c995d2062e72621eb866ad0f4472a635",
+ "sha256:2be726f16142d358a0df1e81d583d6820ee561a7856a79cca2fbe49989308be7",
+ "sha256:4338d2a81f5b4ca022e085040b3cfce19419a5ce44aa7e6810ac1df05365bed7",
+ "sha256:4c535b46f20e66bee3097583231977e721acdfcb1671d1490c99b7be8902ce18",
+ "sha256:557154aef70a0e979700cc9528bc8b606b668084a29a0d57dbc4b06b078a2f1c",
+ "sha256:5bfdd7e6647498f979dc46583723c852d97b25afe995d55aa1c76a5f9816bc1f",
+ "sha256:87d8943ae7aa6ca5bbad732867d7f17d2550e4966a0c15b52088e8b579422e47",
+ "sha256:89d8719d8de4d137678f7caa979e1b0a6fd4026f8096ceef8c2d164bbabefaf2",
+ "sha256:9c3f4af989ce860710ac1864dc2e867dd87e6cee51a2368df1b253596868e52f",
+ "sha256:9da52c3c728883aee429bb7c315049f50b2139f680cd86bb1165418e4f93a982",
+ "sha256:9e9736659987beab42d18525ed10d21f80a1ba8389eac03425fbfd5684e6bbf0",
+ "sha256:9ebcbb1a054cab362d29d3be571d43d6b9b23302d9fc4b43e5327000da1680a9",
+ "sha256:a93e08636623e24c939851e2e0c0140b14f524b2980c9cdc4ea52b70a871c7e0",
+ "sha256:ac322d86d1a079e0a118d544443ee16f320af0062c191b4754c0c6ec2fc79310",
+ "sha256:b1fb101459868f52df6b61e7bb13375e50badf17a160e39fe1d51ae19e53f461",
+ "sha256:b39aac96cceac624a23d540473835086a3ffa77c91030189988c073488434493",
+ "sha256:b65507bc273c6dbf539175a786a344cc0ac78d50e5584f72c6599733f8a3301f",
+ "sha256:be5bb6e47417e537c884a2e2ff2e1a8b2c064a998fcfdfcc67528d4e63e7ebaf",
+ "sha256:c92de6a28a909c4f460dc1bbbcb50d676cf0b1f40224b222761f73fdd851b522",
+ "sha256:c9f5962eb7fa7607b20eb0e4f59ed35829bd600fc0eacb626a6db83229a3e445",
+ "sha256:d00bdf9c546ed6e649f785c55b05288e8b2dbb6bf2eb74b6c579fa0d591d35bd",
+ "sha256:da804b1dd8293bd9d61b1e6ea989c887ba042a808a4fbdd80001cfa059aafed2",
+ "sha256:ead6c5aa3e807345913649c3be395aaca2bbb2d225f18b8f31f37eab225508f6",
+ "sha256:eb4d81550ce6f826af4ec6e8d98be347fe96291d718bf115c3f254621ae8d98d",
+ "sha256:ef6a18ec8fd32ec81748fe720544ea2fb2d2dc50fd6d06739d5e2eb8f0626a1c",
+ "sha256:fad42835656e0b6d3b7ffc900598e776722e30f43b7234a48f2576ca30f31a47",
+ "sha256:fb98dbfee0d963b49ae5754554028cf62e6bd695f22de16d242ba9d2f0b7339b",
+ "sha256:fb9cd9bb8d26dc17c2dd715a46bca3a879ec8283879b164e85863110dc6e3b2a"
+ ],
+ "version": "==1.21.1"
+ },
+ "gunicorn": {
+ "hashes": [
+ "sha256:aa8e0b40b4157b36a5df5e599f45c9c76d6af43845ba3b3b0efe2c70473c2471",
+ "sha256:fa2662097c66f920f53f70621c6c58ca4a3c4d3434205e608e121b5b3b71f4f3"
+ ],
+ "index": "pypi",
+ "version": "==19.9.0"
+ },
+ "h5py": {
+ "hashes": [
+ "sha256:05750b91640273c69989c657eaac34b091abdd75efc8c4824c82aaf898a2da0a",
+ "sha256:082a27208aa3a2286e7272e998e7e225b2a7d4b7821bd840aebf96d50977abbb",
+ "sha256:08e2e8297195f9e813e894b6c63f79372582787795bba2014a2db6a2de95f713",
+ "sha256:0dd2adeb2e9de5081eb8dcec88874e7fd35dae9a21557be3a55a3c7d491842a4",
+ "sha256:0f94de7a10562b991967a66bbe6dda9808e18088676834c0a4dcec3fdd3bcc6f",
+ "sha256:106e42e2e01e486a3d32eeb9ba0e3a7f65c12fa8998d63625fa41fb8bdc44cdb",
+ "sha256:1606c66015f04719c41a9863c156fc0e6b992150de21c067444bcb82e7d75579",
+ "sha256:1854c4beff9961e477e133143c5e5e355dac0b3ebf19c52cf7cc1b1ef757703c",
+ "sha256:1e9fb6f1746500ea91a00193ce2361803c70c6b13f10aae9a33ad7b5bd28e800",
+ "sha256:2cca17e80ddb151894333377675db90cd0279fa454776e0a4f74308376afd050",
+ "sha256:30e365e8408759db3778c361f1e4e0fe8e98a875185ae46c795a85e9bafb9cdf",
+ "sha256:3206bac900e16eda81687d787086f4ffd4f3854980d798e191a9868a6510c3ae",
+ "sha256:3c23d72058647cee19b30452acc7895621e2de0a0bd5b8a1e34204b9ea9ed43c",
+ "sha256:407b5f911a83daa285bbf1ef78a9909ee5957f257d3524b8606be37e8643c5f0",
+ "sha256:4162953714a9212d373ac953c10e3329f1e830d3c7473f2a2e4f25dd6241eef0",
+ "sha256:5fc7aba72a51b2c80605eba1c50dbf84224dcd206279d30a75c154e5652e1fe4",
+ "sha256:713ac19307e11de4d9833af0c4bd6778bde0a3d967cafd2f0f347223711c1e31",
+ "sha256:71b946d80ef3c3f12db157d7778b1fe74a517ca85e94809358b15580983c2ce2",
+ "sha256:8cc4aed71e20d87e0a6f02094d718a95252f11f8ed143bc112d22167f08d4040",
+ "sha256:9d41ca62daf36d6b6515ab8765e4c8c4388ee18e2a665701fef2b41563821002",
+ "sha256:a744e13b000f234cd5a5b2a1f95816b819027c57f385da54ad2b7da1adace2f3",
+ "sha256:b087ee01396c4b34e9dc41e3a6a0442158206d383c19c7d0396d52067b17c1cb",
+ "sha256:b0f03af381d33306ce67d18275b61acb4ca111ced645381387a02c8a5ee1b796",
+ "sha256:b9e4b8dfd587365bdd719ae178fa1b6c1231f81280b1375eef8626dfd8761bf3",
+ "sha256:c5dd4ec75985b99166c045909e10f0534704d102848b1d9f0992720e908928e7",
+ "sha256:d2b82f23cd862a9d05108fe99967e9edfa95c136f532a71cb3d28dc252771f50",
+ "sha256:e58a25764472af07b7e1c4b10b0179c8ea726446c7141076286e41891bf3a563",
+ "sha256:f3b49107fbfc77333fc2b1ef4d5de2abcd57e7ea3a1482455229494cf2da56ce"
+ ],
+ "index": "pypi",
+ "version": "==2.9.0"
+ },
+ "hexdump": {
+ "hashes": [
+ "sha256:d781a43b0c16ace3f9366aade73e8ad3a7bd5137d58f0b45ab2d3f54876f20db"
+ ],
+ "index": "pypi",
+ "version": "==3.3"
+ },
+ "html5lib": {
+ "hashes": [
+ "sha256:2612a191a8d5842bfa057e41ba50bbb9dcb722419d2408c78cff4758d0754868"
+ ],
+ "index": "pypi",
+ "version": "==0.9999999"
+ },
+ "humanfriendly": {
+ "hashes": [
+ "sha256:23057b10ad6f782e7bc3a20e3cb6768ab919f619bbdc0dd75691121bbde5591d",
+ "sha256:33ee8ceb63f1db61cce8b5c800c531e1a61023ac5488ccde2ba574a85be00a85"
+ ],
+ "version": "==4.18"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407",
+ "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"
+ ],
+ "index": "pypi",
+ "version": "==2.8"
+ },
+ "imageio": {
+ "hashes": [
+ "sha256:1a2bbbb7cd38161340fa3b14d806dfbf914abf3ee6fd4592af2afb87d049f209",
+ "sha256:42e65aadfc3d57a1043615c92bdf6319b67589e49a0aae2b985b82144aceacad"
+ ],
+ "index": "pypi",
+ "version": "==2.5.0"
+ },
+ "intervaltree": {
+ "hashes": [
+ "sha256:cb4f61c81dcb4fea6c09903f3599015a83c9bdad1f0bbd232495e6681e19e273"
+ ],
+ "index": "pypi",
+ "version": "==3.0.2"
+ },
+ "ipaddress": {
+ "hashes": [
+ "sha256:64b28eec5e78e7510698f6d4da08800a5c575caa4a286c93d651c5d3ff7b6794",
+ "sha256:b146c751ea45cad6188dd6cf2d9b757f6f4f8d6ffb96a023e6f2e26eea02a72c"
+ ],
+ "markers": "python_version < '3'",
+ "version": "==1.0.22"
+ },
+ "ipykernel": {
+ "hashes": [
+ "sha256:56d82987472f4b14ab0214e4aef55def006671885d285cd8821f2600861215a6",
+ "sha256:59b0855082d021f533cff477e1bb619e663b6aab11309a05bf88eaec9f53faed",
+ "sha256:699103c8e64886e3ec7053f2a6aa83bb90426063526f63a818732ff385202bad"
+ ],
+ "index": "pypi",
+ "version": "==4.10.0"
+ },
+ "ipython": {
+ "hashes": [
+ "sha256:0371b7e4bd74954a35086eac949beeac5b1c9f5ce231e2e77df2286a293765e3",
+ "sha256:37101b8cbe072fe17bff100bc03d096404e4a9a0357097aeb5b61677c042cab1",
+ "sha256:4bac649857611baaaf76bc82c173aa542f7486446c335fe1a6c05d0d491c8906"
+ ],
+ "index": "pypi",
+ "version": "==5.8.0"
+ },
+ "ipython-genutils": {
+ "hashes": [
+ "sha256:72dd37233799e619666c9f639a9da83c34013a73e8bbc79a7a6348d93c61fab8",
+ "sha256:eb2e116e75ecef9d4d228fdc66af54269afa26ab4463042e33785b887c628ba8"
+ ],
+ "version": "==0.2.0"
+ },
+ "ipywidgets": {
+ "hashes": [
+ "sha256:0f2b5cde9f272cb49d52f3f0889fdd1a7ae1e74f37b48dac35a83152780d2b7b",
+ "sha256:a3e224f430163f767047ab9a042fc55adbcab0c24bbe6cf9f306c4f89fdf0ba3"
+ ],
+ "version": "==7.4.2"
+ },
+ "isodate": {
+ "hashes": [
+ "sha256:2e364a3d5759479cdb2d37cce6b9376ea504db2ff90252a2e5b7cc89cc9ff2d8",
+ "sha256:aa4d33c06640f5352aca96e4b81afd8ab3b47337cc12089822d6f322ac772c81"
+ ],
+ "version": "==0.6.0"
+ },
+ "isort": {
+ "hashes": [
+ "sha256:c40744b6bc5162bbb39c1257fe298b7a393861d50978b565f3ccd9cb9de0182a",
+ "sha256:f57abacd059dc3bd666258d1efb0377510a89777fda3e3274e3c01f7c03ae22d"
+ ],
+ "version": "==4.3.20"
+ },
+ "itsdangerous": {
+ "hashes": [
+ "sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19",
+ "sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749"
+ ],
+ "version": "==1.1.0"
+ },
+ "jinja2": {
+ "hashes": [
+ "sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013",
+ "sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b"
+ ],
+ "index": "pypi",
+ "version": "==2.10.1"
+ },
+ "jmespath": {
+ "hashes": [
+ "sha256:3720a4b1bd659dd2eecad0666459b9788813e032b83e7ba58578e48254e0a0e6",
+ "sha256:bde2aef6f44302dfb30320115b17d030798de8c4110e28d5cf6cf91a7a31074c"
+ ],
+ "version": "==0.9.4"
+ },
+ "joblib": {
+ "hashes": [
+ "sha256:21e0c34a69ad7fde4f2b1f3402290e9ec46f545f15f1541c582edfe05d87b63a",
+ "sha256:315d6b19643ec4afd4c41c671f9f2d65ea9d787da093487a81ead7b0bac94524"
+ ],
+ "index": "pypi",
+ "version": "==0.13.2"
+ },
+ "json-logging-py": {
+ "hashes": [
+ "sha256:118b1fe1f4eacaea6370e5b9710d0f6d0c0a4599aef9d5b9875a6a579974fc9a"
+ ],
+ "index": "pypi",
+ "version": "==0.2"
+ },
+ "jsonschema": {
+ "hashes": [
+ "sha256:0c0a81564f181de3212efa2d17de1910f8732fa1b71c42266d983cd74304e20d",
+ "sha256:a5f6559964a3851f59040d3b961de5e68e70971afb88ba519d27e6a039efff1a"
+ ],
+ "version": "==3.0.1"
+ },
+ "jupyter": {
+ "hashes": [
+ "sha256:3e1f86076bbb7c8c207829390305a2b1fe836d471ed54be66a3b8c41e7f46cc7",
+ "sha256:5b290f93b98ffbc21c0c7e749f054b3267782166d72fa5e3ed1ed4eaf34a2b78",
+ "sha256:d9dc4b3318f310e34c82951ea5d6683f67bed7def4b259fafbfe4f1beb1d8e5f"
+ ],
+ "index": "pypi",
+ "version": "==1.0.0"
+ },
+ "jupyter-client": {
+ "hashes": [
+ "sha256:b5f9cb06105c1d2d30719db5ffb3ea67da60919fb68deaefa583deccd8813551",
+ "sha256:c44411eb1463ed77548bc2d5ec0d744c9b81c4a542d9637c7a52824e2121b987"
+ ],
+ "version": "==5.2.4"
+ },
+ "jupyter-console": {
+ "hashes": [
+ "sha256:3f928b817fc82cda95e431eb4c2b5eb21be5c483c2b43f424761a966bb808094",
+ "sha256:545dedd3aaaa355148093c5609f0229aeb121b4852995c2accfa64fe3e0e55cd"
+ ],
+ "version": "==5.2.0"
+ },
+ "jupyter-core": {
+ "hashes": [
+ "sha256:927d713ffa616ea11972534411544589976b2493fc7e09ad946e010aa7eb9970",
+ "sha256:ba70754aa680300306c699790128f6fbd8c306ee5927976cbe48adacf240c0b7"
+ ],
+ "version": "==4.4.0"
+ },
+ "keras": {
+ "hashes": [
+ "sha256:794d0c92c6c4122f1f0fcf3a7bc2f49054c6a54ddbef8d8ffafca62795d760b6",
+ "sha256:90b610a3dbbf6d257b20a079eba3fdf2eed2158f64066a7c6f7227023fd60bc9"
+ ],
+ "index": "pypi",
+ "version": "==2.2.4"
+ },
+ "keras-applications": {
+ "hashes": [
+ "sha256:5579f9a12bcde9748f4a12233925a59b93b73ae6947409ff34aa2ba258189fe5",
+ "sha256:df4323692b8c1174af821bf906f1e442e63fa7589bf0f1230a0b6bdc5a810c95"
+ ],
+ "version": "==1.0.8"
+ },
+ "keras-maskrcnn": {
+ "hashes": [
+ "sha256:7cbadcf5d8a41e64ebd19157253f0357f2c46f289584c6f58fd38a19f7cc3509"
+ ],
+ "index": "pypi",
+ "version": "==0.2.1"
+ },
+ "keras-preprocessing": {
+ "hashes": [
+ "sha256:44aee5f2c4d80c3b29f208359fcb336df80f293a0bb6b1c738da43ca206656fb",
+ "sha256:5a8debe01d840de93d49e05ccf1c9b81ae30e210d34dacbcc47aeb3049b528e5"
+ ],
+ "version": "==1.1.0"
+ },
+ "keras-resnet": {
+ "hashes": [
+ "sha256:8ce27ba782d1b45b127af51208aefdceb2de8d2c54646bac5fc786506ce558c0"
+ ],
+ "version": "==0.2.0"
+ },
+ "keras-retinanet": {
+ "hashes": [
+ "sha256:257b77ca46c6846d8e9260e4eb1c77ab9b564c512bb5ebe23e72fc46b5c41899"
+ ],
+ "index": "pypi",
+ "version": "==0.5.0"
+ },
+ "kiwisolver": {
+ "hashes": [
+ "sha256:05b5b061e09f60f56244adc885c4a7867da25ca387376b02c1efc29cc16bcd0f",
+ "sha256:26f4fbd6f5e1dabff70a9ba0d2c4bd30761086454aa30dddc5b52764ee4852b7",
+ "sha256:3b2378ad387f49cbb328205bda569b9f87288d6bc1bf4cd683c34523a2341efe",
+ "sha256:400599c0fe58d21522cae0e8b22318e09d9729451b17ee61ba8e1e7c0346565c",
+ "sha256:47b8cb81a7d18dbaf4fed6a61c3cecdb5adec7b4ac292bddb0d016d57e8507d5",
+ "sha256:53eaed412477c836e1b9522c19858a8557d6e595077830146182225613b11a75",
+ "sha256:58e626e1f7dfbb620d08d457325a4cdac65d1809680009f46bf41eaf74ad0187",
+ "sha256:5a52e1b006bfa5be04fe4debbcdd2688432a9af4b207a3f429c74ad625022641",
+ "sha256:5c7ca4e449ac9f99b3b9d4693debb1d6d237d1542dd6a56b3305fe8a9620f883",
+ "sha256:682e54f0ce8f45981878756d7203fd01e188cc6c8b2c5e2cf03675390b4534d5",
+ "sha256:79bfb2f0bd7cbf9ea256612c9523367e5ec51d7cd616ae20ca2c90f575d839a2",
+ "sha256:7f4dd50874177d2bb060d74769210f3bce1af87a8c7cf5b37d032ebf94f0aca3",
+ "sha256:8944a16020c07b682df861207b7e0efcd2f46c7488619cb55f65882279119389",
+ "sha256:8aa7009437640beb2768bfd06da049bad0df85f47ff18426261acecd1cf00897",
+ "sha256:939f36f21a8c571686eb491acfffa9c7f1ac345087281b412d63ea39ca14ec4a",
+ "sha256:9733b7f64bd9f807832d673355f79703f81f0b3e52bfce420fc00d8cb28c6a6c",
+ "sha256:a02f6c3e229d0b7220bd74600e9351e18bc0c361b05f29adae0d10599ae0e326",
+ "sha256:a0c0a9f06872330d0dd31b45607197caab3c22777600e88031bfe66799e70bb0",
+ "sha256:acc4df99308111585121db217681f1ce0eecb48d3a828a2f9bbf9773f4937e9e",
+ "sha256:b64916959e4ae0ac78af7c3e8cef4becee0c0e9694ad477b4c6b3a536de6a544",
+ "sha256:d3fcf0819dc3fea58be1fd1ca390851bdb719a549850e708ed858503ff25d995",
+ "sha256:d52e3b1868a4e8fd18b5cb15055c76820df514e26aa84cc02f593d99fef6707f",
+ "sha256:db1a5d3cc4ae943d674718d6c47d2d82488ddd94b93b9e12d24aabdbfe48caee",
+ "sha256:e3a21a720791712ed721c7b95d433e036134de6f18c77dbe96119eaf7aa08004",
+ "sha256:e8bf074363ce2babeb4764d94f8e65efd22e6a7c74860a4f05a6947afc020ff2",
+ "sha256:f16814a4a96dc04bf1da7d53ee8d5b1d6decfc1a92a63349bb15d37b6a263dd9",
+ "sha256:f2b22153870ca5cf2ab9c940d7bc38e8e9089fa0f7e5856ea195e1cf4ff43d5a",
+ "sha256:f790f8b3dff3d53453de6a7b7ddd173d2e020fb160baff578d578065b108a05f"
+ ],
+ "version": "==1.1.0"
+ },
+ "kombu": {
+ "hashes": [
+ "sha256:056a31cc95b10ca4eb0d4ebcba714007b1db1c6c45c8e2d139fe91933481b00b",
+ "sha256:af5b0f892b081f49d95c772a241fb7687f4cc3e42c94328f118dffb1f4e161e5"
+ ],
+ "version": "==4.6.1"
+ },
+ "lazy-object-proxy": {
+ "hashes": [
+ "sha256:159a745e61422217881c4de71f9eafd9d703b93af95618635849fe469a283661",
+ "sha256:23f63c0821cc96a23332e45dfaa83266feff8adc72b9bcaef86c202af765244f",
+ "sha256:3b11be575475db2e8a6e11215f5aa95b9ec14de658628776e10d96fa0b4dac13",
+ "sha256:3f447aff8bc61ca8b42b73304f6a44fa0d915487de144652816f950a3f1ab821",
+ "sha256:4ba73f6089cd9b9478bc0a4fa807b47dbdb8fad1d8f31a0f0a5dbf26a4527a71",
+ "sha256:4f53eadd9932055eac465bd3ca1bd610e4d7141e1278012bd1f28646aebc1d0e",
+ "sha256:64483bd7154580158ea90de5b8e5e6fc29a16a9b4db24f10193f0c1ae3f9d1ea",
+ "sha256:6f72d42b0d04bfee2397aa1862262654b56922c20a9bb66bb76b6f0e5e4f9229",
+ "sha256:7c7f1ec07b227bdc561299fa2328e85000f90179a2f44ea30579d38e037cb3d4",
+ "sha256:7c8b1ba1e15c10b13cad4171cfa77f5bb5ec2580abc5a353907780805ebe158e",
+ "sha256:8559b94b823f85342e10d3d9ca4ba5478168e1ac5658a8a2f18c991ba9c52c20",
+ "sha256:a262c7dfb046f00e12a2bdd1bafaed2408114a89ac414b0af8755c696eb3fc16",
+ "sha256:acce4e3267610c4fdb6632b3886fe3f2f7dd641158a843cf6b6a68e4ce81477b",
+ "sha256:be089bb6b83fac7f29d357b2dc4cf2b8eb8d98fe9d9ff89f9ea6012970a853c7",
+ "sha256:bfab710d859c779f273cc48fb86af38d6e9210f38287df0069a63e40b45a2f5c",
+ "sha256:c10d29019927301d524a22ced72706380de7cfc50f767217485a912b4c8bd82a",
+ "sha256:dd6e2b598849b3d7aee2295ac765a578879830fb8966f70be8cd472e6069932e",
+ "sha256:e408f1eacc0a68fed0c08da45f31d0ebb38079f043328dce69ff133b95c29dc1"
+ ],
+ "version": "==1.4.1"
+ },
+ "libarchive": {
+ "hashes": [
+ "sha256:37e8cca1eb85d30583cdcffc58116d83abc09be7549d5d6c9ead563c0a8d7b04"
+ ],
+ "index": "pypi",
+ "version": "==0.4.6"
+ },
+ "lru-dict": {
+ "hashes": [
+ "sha256:365457660e3d05b76f1aba3e0f7fedbfcd6528e97c5115a351ddd0db488354cc"
+ ],
+ "index": "pypi",
+ "version": "==1.1.6"
+ },
+ "lxml": {
+ "hashes": [
+ "sha256:06c7616601430aa140a69f97e3116308fffe0848f543b639a5ec2e8920ae72fd",
+ "sha256:177202792f9842374a8077735c69c41a4282183f7851443d2beb8ee310720819",
+ "sha256:19317ad721ceb9e39847d11131903931e2794e447d4751ebb0d9236f1b349ff2",
+ "sha256:36d206e62f3e5dbaafd4ec692b67157e271f5da7fd925fda8515da675eace50d",
+ "sha256:387115b066c797c85f9861a9613abf50046a15aac16759bc92d04f94acfad082",
+ "sha256:3ce1c49d4b4a7bc75fb12acb3a6247bb7a91fe420542e6d671ba9187d12a12c2",
+ "sha256:4d2a5a7d6b0dbb8c37dab66a8ce09a8761409c044017721c21718659fa3365a1",
+ "sha256:58d0a1b33364d1253a88d18df6c0b2676a1746d27c969dc9e32d143a3701dda5",
+ "sha256:62a651c618b846b88fdcae0533ec23f185bb322d6c1845733f3123e8980c1d1b",
+ "sha256:69ff21064e7debc9b1b1e2eee8c2d686d042d4257186d70b338206a80c5bc5ea",
+ "sha256:7060453eba9ba59d821625c6af6a266bd68277dce6577f754d1eb9116c094266",
+ "sha256:7d26b36a9c4bce53b9cfe42e67849ae3c5c23558bc08363e53ffd6d94f4ff4d2",
+ "sha256:83b427ad2bfa0b9705e02a83d8d607d2c2f01889eb138168e462a3a052c42368",
+ "sha256:923d03c84534078386cf50193057aae98fa94cace8ea7580b74754493fda73ad",
+ "sha256:b773715609649a1a180025213f67ffdeb5a4878c784293ada300ee95a1f3257b",
+ "sha256:baff149c174e9108d4a2fee192c496711be85534eab63adb122f93e70aa35431",
+ "sha256:bca9d118b1014b4c2d19319b10a3ebed508ff649396ce1855e1c96528d9b2fa9",
+ "sha256:ce580c28845581535dc6000fc7c35fdadf8bea7ccb57d6321b044508e9ba0685",
+ "sha256:d34923a569e70224d88e6682490e24c842907ba2c948c5fd26185413cbe0cd96",
+ "sha256:dd9f0e531a049d8b35ec5e6c68a37f1ba6ec3a591415e6804cbdf652793d15d7",
+ "sha256:ecb805cbfe9102f3fd3d2ef16dfe5ae9e2d7a7dfbba92f4ff1e16ac9784dbfb0",
+ "sha256:ede9aad2197a0202caff35d417b671f5f91a3631477441076082a17c94edd846",
+ "sha256:ef2d1fc370400e0aa755aab0b20cf4f1d0e934e7fd5244f3dd4869078e4942b9",
+ "sha256:f2fec194a49bfaef42a548ee657362af5c7a640da757f6f452a35da7dd9f923c"
+ ],
+ "index": "pypi",
+ "version": "==4.3.4"
+ },
+ "markdown": {
+ "hashes": [
+ "sha256:2e50876bcdd74517e7b71f3e7a76102050edec255b3983403f1a63e7c8a41e7a",
+ "sha256:56a46ac655704b91e5b7e6326ce43d5ef72411376588afa1dd90e881b83c7e8c"
+ ],
+ "version": "==3.1.1"
+ },
+ "markupsafe": {
+ "hashes": [
+ "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473",
+ "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161",
+ "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235",
+ "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5",
+ "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff",
+ "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b",
+ "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1",
+ "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e",
+ "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183",
+ "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66",
+ "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1",
+ "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1",
+ "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e",
+ "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b",
+ "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905",
+ "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735",
+ "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d",
+ "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e",
+ "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d",
+ "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c",
+ "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21",
+ "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2",
+ "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5",
+ "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b",
+ "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6",
+ "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f",
+ "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f",
+ "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"
+ ],
+ "version": "==1.1.1"
+ },
+ "matplotlib": {
+ "hashes": [
+ "sha256:0ba8e3ec1b0feddc6b068fe70dc38dcf2917e301ad8d2b3f848c14ad463a4157",
+ "sha256:10a48e33e64dbd95f0776ba162f379c5cc55301c2d155506e79ce0c26b52f2ce",
+ "sha256:1376535fe731adbba55ab9e48896de226b7e89dbb55390c5fbd8f7161b7ae3be",
+ "sha256:16f0f8ba22df1e2c9f06c87088de45742322fde282a93b5c744c0f969cf7932e",
+ "sha256:1c6c999f2212858021329537f8e0f98f3f29086ec3683511dd1ecec84409f51d",
+ "sha256:2316dc177fc7b3d8848b49365498de0c385b4c9bba511edddd24c34fbe3d37a4",
+ "sha256:3398bfb533482bf21974cecf28224dd23784ad4e4848be582903f7a2436ec12e",
+ "sha256:3477cb1e1061b34210acc43d20050be8444478ff50b8adfac5fe2b45fc97df01",
+ "sha256:3cc06333b8264428d02231804e2e726b902e9161dc16f573183dee6cb7ef621f",
+ "sha256:4259ea7cb2c238355ee13275eddd261d869cefbdeb18a65f35459589d6d17def",
+ "sha256:4addcf93234b6122f530f90f485fd3d00d158911fbc1ed24db3fa66cd49fe565",
+ "sha256:50c0e24bcbce9c54346f4a2f4e97b0ed111f0413ac3fe9954061ae1c8aa7021f",
+ "sha256:62ed7597d9e54db6e133420d779c642503c25eba390e1178d85dfb2ba0d05948",
+ "sha256:69f6d51e41a17f6a5f70c56bb10b8ded9f299609204495a7fa2782a3a755ffc5",
+ "sha256:6d232e49b74e3d2db22c63c25a9a0166d965e87e2b057f795487f1f244b61d9d",
+ "sha256:7355bf757ecacd5f0ac9dd9523c8e1a1103faadf8d33c22664178e17533f8ce5",
+ "sha256:886b1045c5105631f10c1cbc999f910e44d33af3e9c7efd68c2123efc06ab636",
+ "sha256:9e1f353edd7fc7e5e9101abd5bc0201946f77a1b59e0da49095086c03db856ed",
+ "sha256:b3a343dfcbe296dbe0f26c731beee72a792ff948407e6979524298ae7bc3234e",
+ "sha256:d93675af09ca497a25f4f8d62f3313cf0f21e45427a87487049fe84898b99909",
+ "sha256:e2409ef9d37804dfb566f39c962e6ed70f281ff516b8131b3e6b4e6442711ff1",
+ "sha256:f8b653b0f89938ba72e92ab080c2f3aa24c1b72e2f61add22880cd1b9a6e3cdd"
+ ],
+ "index": "pypi",
+ "version": "==2.2.3"
+ },
+ "mccabe": {
+ "hashes": [
+ "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42",
+ "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"
+ ],
+ "version": "==0.6.1"
+ },
+ "meld3": {
+ "hashes": [
+ "sha256:b28a9bfac342aadb4557aa144bea9f8e6208bfb0596190570d10a892d35ff7dc",
+ "sha256:f7b754a0fde7a4429b2ebe49409db240b5699385a572501bb0d5627d299f9558"
+ ],
+ "version": "==1.0.2"
+ },
+ "mistune": {
+ "hashes": [
+ "sha256:59a3429db53c50b5c6bcc8a07f8848cb00d7dc8bdb431a4ab41920d201d4756e",
+ "sha256:88a1051873018da288eee8538d476dffe1262495144b33ecb586c4ab266bb8d4"
+ ],
+ "version": "==0.8.4"
+ },
+ "mock": {
+ "hashes": [
+ "sha256:83657d894c90d5681d62155c82bda9c1187827525880eda8ff5df4ec813437c3",
+ "sha256:d157e52d4e5b938c550f39eb2fd15610db062441a9c2747d3dbfa9298211d0f8"
+ ],
+ "version": "==3.0.5"
+ },
+ "monotonic": {
+ "hashes": [
+ "sha256:23953d55076df038541e648a53676fb24980f7a1be290cdda21300b3bc21dfb0",
+ "sha256:552a91f381532e33cbd07c6a2655a21908088962bb8fa7239ecbcc6ad1140cc7"
+ ],
+ "markers": "python_version == '2.7'",
+ "version": "==1.5"
+ },
+ "mpld3": {
+ "hashes": [
+ "sha256:4d455884a211bf99b37ecc760759435c7bb6a5955de47d8daf4967e301878ab7"
+ ],
+ "index": "pypi",
+ "version": "==0.3"
+ },
+ "msgpack-python": {
+ "hashes": [
+ "sha256:378cc8a6d3545b532dfd149da715abae4fda2a3adb6d74e525d0d5e51f46909b"
+ ],
+ "index": "pypi",
+ "version": "==0.5.6"
+ },
+ "msrest": {
+ "hashes": [
+ "sha256:05538c68251eb0c81bd2010524d8ff36d4266ec0669338fbdcecfd23c733231c",
+ "sha256:8143093308975f815f968b0d2a1ac8e26ba217eb6d03f3f27aac616aa3a25bd0"
+ ],
+ "version": "==0.6.7"
+ },
+ "msrestazure": {
+ "hashes": [
+ "sha256:070220fa9c86b55026360435b655d1d67ff4306fd1412687c400dc549e9647b7",
+ "sha256:e9d525b11d88f1073744e128ae19a4e023e4085893cfcfd02483fdd4cee25091"
+ ],
+ "version": "==0.6.1"
+ },
+ "nbconvert": {
+ "hashes": [
+ "sha256:138381baa41d83584459b5cfecfc38c800ccf1f37d9ddd0bd440783346a4c39c",
+ "sha256:4a978548d8383f6b2cfca4a3b0543afb77bc7cb5a96e8b424337ab58c12da9bc"
+ ],
+ "version": "==5.5.0"
+ },
+ "nbformat": {
+ "hashes": [
+ "sha256:b9a0dbdbd45bb034f4f8893cafd6f652ea08c8c1674ba83f2dc55d3955743b0b",
+ "sha256:f7494ef0df60766b7cabe0a3651556345a963b74dbc16bc7c18479041170d402"
+ ],
+ "version": "==4.4.0"
+ },
+ "nbstripout": {
+ "hashes": [
+ "sha256:814efbe00988445b2c3f3d1944c9f296a556e2b14a060f7b25372881c2e497d4",
+ "sha256:8f085e26e60e9d9c0710748510d1c763c8f63905cb16df7658b35a2936e8ca2b"
+ ],
+ "index": "pypi",
+ "version": "==0.3.5"
+ },
+ "networkx": {
+ "hashes": [
+ "sha256:45e56f7ab6fe81652fb4bc9f44faddb0e9025f469f602df14e3b2551c2ea5c8b"
+ ],
+ "version": "==2.2"
+ },
+ "nose": {
+ "hashes": [
+ "sha256:9ff7c6cc443f8c51994b34a667bbcf45afd6d945be7477b52e97516fd17c53ac",
+ "sha256:dadcddc0aefbf99eea214e0f1232b94f2fa9bd98fa8353711dacb112bfcbbb2a",
+ "sha256:f1bffef9cbc82628f6e7d7b40d7e255aefaa1adb6a1b1d26c69a8b79e6208a98"
+ ],
+ "index": "pypi",
+ "version": "==1.3.7"
+ },
+ "nose-parameterized": {
+ "hashes": [
+ "sha256:8f519b9739ac67e3d95f69c15cc80416eea4d63559530d01a37b9565eb629277",
+ "sha256:d35e677aba2f15135b6b7ea7feb88f792b899492ba5365ec0e269015df5214ce"
+ ],
+ "index": "pypi",
+ "version": "==0.6.0"
+ },
+ "notebook": {
+ "hashes": [
+ "sha256:573e0ae650c5d76b18b6e564ba6d21bf321d00847de1d215b418acb64f056eb8",
+ "sha256:f64fa6624d2323fbef6210a621817d6505a45d0d4a9367f1843b20a38a4666ee"
+ ],
+ "version": "==5.7.8"
+ },
+ "numpy": {
+ "hashes": [
+ "sha256:0778076e764e146d3078b17c24c4d89e0ecd4ac5401beff8e1c87879043a0633",
+ "sha256:141c7102f20abe6cf0d54c4ced8d565b86df4d3077ba2343b61a6db996cefec7",
+ "sha256:14270a1ee8917d11e7753fb54fc7ffd1934f4d529235beec0b275e2ccf00333b",
+ "sha256:27e11c7a8ec9d5838bc59f809bfa86efc8a4fd02e58960fa9c49d998e14332d5",
+ "sha256:2a04dda79606f3d2f760384c38ccd3d5b9bb79d4c8126b67aff5eb09a253763e",
+ "sha256:3c26010c1b51e1224a3ca6b8df807de6e95128b0908c7e34f190e7775455b0ca",
+ "sha256:52c40f1a4262c896420c6ea1c6fda62cf67070e3947e3307f5562bd783a90336",
+ "sha256:6e4f8d9e8aa79321657079b9ac03f3cf3fd067bf31c1cca4f56d49543f4356a5",
+ "sha256:7242be12a58fec245ee9734e625964b97cf7e3f2f7d016603f9e56660ce479c7",
+ "sha256:7dc253b542bfd4b4eb88d9dbae4ca079e7bf2e2afd819ee18891a43db66c60c7",
+ "sha256:94f5bd885f67bbb25c82d80184abbf7ce4f6c3c3a41fbaa4182f034bba803e69",
+ "sha256:a89e188daa119ffa0d03ce5123dee3f8ffd5115c896c2a9d4f0dbb3d8b95bfa3",
+ "sha256:ad3399da9b0ca36e2f24de72f67ab2854a62e623274607e37e0ce5f5d5fa9166",
+ "sha256:b0348be89275fd1d4c44ffa39530c41a21062f52299b1e3ee7d1c61f060044b8",
+ "sha256:b5554368e4ede1856121b0dfa35ce71768102e4aa55e526cb8de7f374ff78722",
+ "sha256:cbddc56b2502d3f87fda4f98d948eb5b11f36ff3902e17cb6cc44727f2200525",
+ "sha256:d79f18f41751725c56eceab2a886f021d70fd70a6188fd386e29a045945ffc10",
+ "sha256:dc2ca26a19ab32dc475dbad9dfe723d3a64c835f4c23f625c2b6566ca32b9f29",
+ "sha256:dd9bcd4f294eb0633bb33d1a74febdd2b9018b8b8ed325f861fffcd2c7660bb8",
+ "sha256:e8baab1bc7c9152715844f1faca6744f2416929de10d7639ed49555a85549f52",
+ "sha256:ec31fe12668af687b99acf1567399632a7c47b0e17cfb9ae47c098644ef36797",
+ "sha256:f12b4f7e2d8f9da3141564e6737d79016fe5336cc92de6814eba579744f65b0a",
+ "sha256:f58ac38d5ca045a377b3b377c84df8175ab992c970a53332fa8ac2373df44ff7"
+ ],
+ "index": "pypi",
+ "version": "==1.16.4"
+ },
+ "oauthlib": {
+ "hashes": [
+ "sha256:0ce32c5d989a1827e3f1148f98b9085ed2370fc939bf524c9c851d8714797298",
+ "sha256:3e1e14f6cde7e5475128d30e97edc3bfb4dc857cb884d8714ec161fdbb3b358e"
+ ],
+ "version": "==3.0.1"
+ },
+ "opencv-python": {
+ "hashes": [
+ "sha256:1703a296a96d3d46615e5053f224867977accb4240bcaa0fcabcb0768bf5ac13",
+ "sha256:1777ce7535ee7a1995cae168a107a1320e9df13648b930e72a1a2c2eccd64cda",
+ "sha256:1e5520482fb18fbd64d079e7f17ac0018f195fd75f6360a53bb82d7903106b50",
+ "sha256:25522dcf2529614750a71112a6659759080b4bdc2323f19d47f4d895960fd796",
+ "sha256:2af5f2842ad44c65ae2647377e0ff198719e1a1cfc9c6a19bc0c525c035d4bd8",
+ "sha256:31ec48d7eca13fc25c287dea7cecab453976e372cad8f50d55c054a247efda21",
+ "sha256:47cf48ff5dbd554e9f58cc9e98cf0b5de3f6a971172612bffa06bc5fb79ce872",
+ "sha256:494f98366bb5d6c2ac7e50e6617139f353704fd97a6d12ec9d392e72817d5cb0",
+ "sha256:4a9845870739e640e3350a8d98d511c92c087fe3d66090e83be7bf94e0ac64f7",
+ "sha256:4ac29cc0847d948a6636899014e84e165c30cc8779d6218394d44363462a01ce",
+ "sha256:5857ace03b7854221abf8072462d306c2c2ce4e366190b21d90ee8ee8aaf5bb4",
+ "sha256:5b4a23d99d5a2874767034466f5a8fd37b9f93ac14955a01b1a208983c76b9ad",
+ "sha256:734d87a5021c037064beb62133e135e66c7128e401a63b8b842b809ae2093749",
+ "sha256:78005c1c5d15ef4e32e0f485557bd15b5b6d87f49c19db7fe3e9246a61ebe7e4",
+ "sha256:81ae2283225c5c52fc3d72debd4241c30ccff2bb922578bf7867f9851cce3acb",
+ "sha256:88dbf900f297fdae0f62b899d6a784d8868ec2135854c5f8a9abbad00a6f0c5b",
+ "sha256:8c98ea7b8d327a31cd6028782a06147d0e0329ae8e829e881fb5d02f7ed8aec9",
+ "sha256:937d4686fef6967921145290f5b50c01c00c5b5d3542a6519e8a85cd88448723",
+ "sha256:a057958c0e362b3c4f03b9af1cbdb6d5af035fd22ecd7fd794eba8fdeb049eb8",
+ "sha256:c41eab31fa2c641226c6187caa391a688d064c99f078d604574f1912296b771f",
+ "sha256:cf4f7e62d1f80d1fa85a1693a3500def5cde54b2b75212b3609e552e4c25acfb",
+ "sha256:d90d60143e18334330c149f293071c9f2f3c79c896f33dc4ec65099e58baaaa7",
+ "sha256:db3106b7ca86999a7bd1f2fcc93e49314e5e6e451356774e421a69428df5020b",
+ "sha256:dbaf264db56f4771dfac6624f438bc4dc670aa94f61a6138848fcab7e9e77380",
+ "sha256:e65206c4cf651dc9cf0829962fae8bec986767c9f123d6a1ad17f9356bf7257e",
+ "sha256:eac94ddc78c58e891cff7180274317dad2938a4ddfc6ced1c04846c7f50e77e9",
+ "sha256:f2e828711f044a965509c862b3a59b3181e9c56c145a950cb53d43fec54e66d2"
+ ],
+ "version": "==4.1.0.25"
+ },
+ "osmium": {
+ "hashes": [
+ "sha256:008f89720d833a28ff875893bc90ca6314ed27f23dedbff6b8e7e0224c058076",
+ "sha256:0811d5453e9828f14dc14f7380570a71b2ac2e9fbfc849fb1485a198e1bc0825",
+ "sha256:08a427a7c3fe3dceb84e19bcef6edada0dde9a675f75189d89dd7f4b0cab3539",
+ "sha256:0a1e4200e678e18db9b291a6498385b4c8f66dc3898be8fc6d0c232fe7600360",
+ "sha256:2183610dfbd7831b819e5990ec47a9c25dec76084dbae1d55bdc092bfba9177c",
+ "sha256:227ab38197d45fced6e18a5000e27b7bc7ef2970f7adcb856370661340a03b8e",
+ "sha256:2928713aaadaeab38fa8d546d274c9545b20440f2019425b3a6bab9444bd935a",
+ "sha256:2a3a42252afcf7fd3558c582e6a38df63df038a027b6d5fe1eaf8dac66969d37",
+ "sha256:4617fc74d13e2373b239597c6a875b90f95f40ec0d0977f68ca4beb3383a6f63",
+ "sha256:4ea02b36332585b66fb52b49468fac7426a257d0ffeaf0e0aa7ef7205f0fc442",
+ "sha256:56f269587578fcdd406af43dc276f3a59c4763821f9e41ce7b777f6f97cdede4",
+ "sha256:62688a1a662bc2ef7f0b05908c9e68ba11926fc79f3d1df13cd62cee74a6ca66",
+ "sha256:72d1d43834610c3d802316b526c204ecf428d5bbd5dab189b0e469bc67858db1",
+ "sha256:8a316b6bba0f33250c232c8a10f550d8578b639857e286159e1e0767d5ac7107",
+ "sha256:8b4802472d974b4f05ee960c40ccd0c14881b73cd68a669f23ce9b35fe313157",
+ "sha256:8c6b5c489d78d398786547480f87a7d51ad51cf0044479f13ecb0c74fb5616c7",
+ "sha256:91baacc2b7ad28574ec8c204ba812c5bdd9b0fae79f8b6787bea450441cba52f",
+ "sha256:b0b2f925c45fdd1af4a79d3051359c3bc70e7e83939c6096ab91f80b3e2e8cf8",
+ "sha256:b96ab16db2537edf7fd36f5b819f4575b7be0dce6ac857a813822b85c790c8c3",
+ "sha256:ce9f170aa8cf03a497e3a42fff785e4ddd6937a0a074e480d03b2ae90b60f80d",
+ "sha256:d5ebe6bf0e2afc943125ab01980cd0762b3cae8bb47c50aa14ee1a934caf0c85"
+ ],
+ "index": "pypi",
+ "version": "==2.15.0"
+ },
+ "pandocfilters": {
+ "hashes": [
+ "sha256:b3dd70e169bb5449e6bc6ff96aea89c5eea8c5f6ab5e207fc2f521a2cf4a0da9"
+ ],
+ "version": "==1.4.2"
+ },
+ "pathlib2": {
+ "hashes": [
+ "sha256:25199318e8cc3c25dcb45cbe084cc061051336d5a9ea2a12448d3d8cb748f742",
+ "sha256:5887121d7f7df3603bca2f710e7219f3eca0eb69e0b7cc6e0a022e155ac931a7"
+ ],
+ "markers": "python_version in '2.6 2.7 3.2 3.3'",
+ "version": "==2.3.3"
+ },
+ "pbr": {
+ "hashes": [
+ "sha256:8257baf496c8522437e8a6cfe0f15e00aedc6c0e0e7c9d55eeeeab31e0853843",
+ "sha256:8c361cc353d988e4f5b998555c88098b9d5964c2e11acf7b0d21925a66bb5824"
+ ],
+ "index": "pypi",
+ "version": "==5.1.3"
+ },
+ "percache": {
+ "hashes": [
+ "sha256:b60043937aece6d154ccd1fd7380fc01ea482335716c2bd41efb85b097bc88df"
+ ],
+ "index": "pypi",
+ "version": "==0.3.0"
+ },
+ "pexpect": {
+ "hashes": [
+ "sha256:2094eefdfcf37a1fdbfb9aa090862c1a4878e5c7e0e7e7088bdb511c558e5cd1",
+ "sha256:9e2c1fd0e6ee3a49b28f95d4b33bc389c89b20af6a1255906e90ff1262ce62eb"
+ ],
+ "markers": "sys_platform != 'win32'",
+ "version": "==4.7.0"
+ },
+ "pickleshare": {
+ "hashes": [
+ "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca",
+ "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"
+ ],
+ "version": "==0.7.5"
+ },
+ "pillow": {
+ "hashes": [
+ "sha256:15c056bfa284c30a7f265a41ac4cbbc93bdbfc0dfe0613b9cb8a8581b51a9e55",
+ "sha256:1a4e06ba4f74494ea0c58c24de2bb752818e9d504474ec95b0aa94f6b0a7e479",
+ "sha256:1c3c707c76be43c9e99cb7e3d5f1bee1c8e5be8b8a2a5eeee665efbf8ddde91a",
+ "sha256:1fd0b290203e3b0882d9605d807b03c0f47e3440f97824586c173eca0aadd99d",
+ "sha256:24114e4a6e1870c5a24b1da8f60d0ba77a0b4027907860188ea82bd3508c80eb",
+ "sha256:258d886a49b6b058cd7abb0ab4b2b85ce78669a857398e83e8b8e28b317b5abb",
+ "sha256:33c79b6dd6bc7f65079ab9ca5bebffb5f5d1141c689c9c6a7855776d1b09b7e8",
+ "sha256:367385fc797b2c31564c427430c7a8630db1a00bd040555dfc1d5c52e39fcd72",
+ "sha256:3c1884ff078fb8bf5f63d7d86921838b82ed4a7d0c027add773c2f38b3168754",
+ "sha256:44e5240e8f4f8861d748f2a58b3f04daadab5e22bfec896bf5434745f788f33f",
+ "sha256:46aa988e15f3ea72dddd81afe3839437b755fffddb5e173886f11460be909dce",
+ "sha256:74d90d499c9c736d52dd6d9b7221af5665b9c04f1767e35f5dd8694324bd4601",
+ "sha256:809c0a2ce9032cbcd7b5313f71af4bdc5c8c771cb86eb7559afd954cab82ebb5",
+ "sha256:85d1ef2cdafd5507c4221d201aaf62fc9276f8b0f71bd3933363e62a33abc734",
+ "sha256:8c3889c7681af77ecfa4431cd42a2885d093ecb811e81fbe5e203abc07e0995b",
+ "sha256:9218d81b9fca98d2c47d35d688a0cea0c42fd473159dfd5612dcb0483c63e40b",
+ "sha256:9aa4f3827992288edd37c9df345783a69ef58bd20cc02e64b36e44bcd157bbf1",
+ "sha256:9d80f44137a70b6f84c750d11019a3419f409c944526a95219bea0ac31f4dd91",
+ "sha256:b7ebd36128a2fe93991293f997e44be9286503c7530ace6a55b938b20be288d8",
+ "sha256:c4c78e2c71c257c136cdd43869fd3d5e34fc2162dc22e4a5406b0ebe86958239",
+ "sha256:c6a842537f887be1fe115d8abb5daa9bc8cc124e455ff995830cc785624a97af",
+ "sha256:cf0a2e040fdf5a6d95f4c286c6ef1df6b36c218b528c8a9158ec2452a804b9b8",
+ "sha256:cfd28aad6fc61f7a5d4ee556a997dc6e5555d9381d1390c00ecaf984d57e4232",
+ "sha256:dca5660e25932771460d4688ccbb515677caaf8595f3f3240ec16c117deff89a",
+ "sha256:de7aedc85918c2f887886442e50f52c1b93545606317956d65f342bd81cb4fc3",
+ "sha256:e6c0bbf8e277b74196e3140c35f9a1ae3eafd818f7f2d3a15819c49135d6c062"
+ ],
+ "version": "==6.0.0"
+ },
+ "pprofile": {
+ "hashes": [
+ "sha256:3469102f462f9fc2d889970afcf73d89c0d89a36c49a4c262c3edc302b4a22da"
+ ],
+ "index": "pypi",
+ "version": "==2.0.2"
+ },
+ "progressbar2": {
+ "hashes": [
+ "sha256:9ecb2d35edaa30ed86eb92fb0135eb19a6ef9b3657be4350cc3d0d3563e6af65",
+ "sha256:c086fc1f718839c0ec95caaeb7bd5a1d0268a8775960b8f9dee06f2a04c84628"
+ ],
+ "version": "==3.42.0"
+ },
+ "prometheus-client": {
+ "hashes": [
+ "sha256:ee0c90350595e4a9f36591f291e6f9933246ea67d7cd7d1d6139a9781b14eaae"
+ ],
+ "version": "==0.7.0"
+ },
+ "prompt-toolkit": {
+ "hashes": [
+ "sha256:1e71341526efa4b11bb44d323e687a5d9cef204aabe2907e3f0dc1534cda0ecc",
+ "sha256:955d81315bb7a049f19cd17d1a73f1a40861483260f7dffd825e98303a8bd6b6",
+ "sha256:c1cedd626e08b8ee830ee65897de754113ff3f3035880030c08b01674d85c5b4"
+ ],
+ "version": "==1.0.16"
+ },
+ "protobuf": {
+ "hashes": [
+ "sha256:03f43eac9d5b651f976e91cf46a25b75e5779d98f0f4114b0abfed83376d75f8",
+ "sha256:0c94b21e6de01362f91a86b372555d22a60b59708599ca9d5032ae9fdf8e3538",
+ "sha256:2d2a9f30f61f4063fadd7fb68a2510a6939b43c0d6ceeec5c4704f22225da28e",
+ "sha256:34a0b05fca061e4abb77dd180209f68d8637115ff319f51e28a6a9382d69853a",
+ "sha256:358710fd0db25372edcf1150fa691f48376a134a6c69ce29f38f185eea7699e6",
+ "sha256:41e47198b94c27ba05a08b4a95160656105745c462af574e4bcb0807164065c0",
+ "sha256:8c61cc8a76e9d381c665aecc5105fa0f1878cf7db8b5cd17202603bcb386d0fc",
+ "sha256:a6eebc4db759e58fdac02efcd3028b811effac881d8a5bad1996e4e8ee6acb47",
+ "sha256:a9c12f7c98093da0a46ba76ec40ace725daa1ac4038c41e4b1466afb5c45bb01",
+ "sha256:cb95068492ba0859b8c9e61fa8ba206a83c64e5d0916fb4543700b2e2b214115",
+ "sha256:cd98476ce7bb4dcd6a7b101f5eecdc073dafea19f311e36eb8fba1a349346277",
+ "sha256:ce64cfbea18c535176bdaa10ba740c0fc4c6d998a3f511c17bedb0ae4b3b167c",
+ "sha256:dcbb59eac73fd454e8f2c5fba9e3d3320fd4707ed6a9d3ea3717924a6f0903ea",
+ "sha256:dd67f34458ae716029e2a71ede998e9092493b62a519236ca52e3c5202096c87",
+ "sha256:e3c96056eb5b7284a20e256cb0bf783c8f36ad82a4ae5434a7b7cd02384144a7",
+ "sha256:f612d584d7a27e2f39e7b17878430a959c1bc09a74ba09db096b468558e5e126",
+ "sha256:f6de8a7d6122297b81566e5bd4df37fd5d62bec14f8f90ebff8ede1c9726cd0a",
+ "sha256:fa529d9261682b24c2aaa683667253175c9acebe0a31105394b221090da75832"
+ ],
+ "version": "==3.8.0"
+ },
+ "psutil": {
+ "hashes": [
+ "sha256:028a1ec3c6197eadd11e7b46e8cc2f0720dc18ac6d7aabdb8e8c0d6c9704f000",
+ "sha256:503e4b20fa9d3342bcf58191bbc20a4a5ef79ca7df8972e6197cc14c5513e73d",
+ "sha256:863a85c1c0a5103a12c05a35e59d336e1d665747e531256e061213e2e90f63f3",
+ "sha256:954f782608bfef9ae9f78e660e065bd8ffcfaea780f9f2c8a133bb7cb9e826d7",
+ "sha256:b6e08f965a305cd84c2d07409bc16fbef4417d67b70c53b299116c5b895e3f45",
+ "sha256:bc96d437dfbb8865fc8828cf363450001cb04056bbdcdd6fc152c436c8a74c61",
+ "sha256:cf49178021075d47c61c03c0229ac0c60d5e2830f8cab19e2d88e579b18cdb76",
+ "sha256:d5350cb66690915d60f8b233180f1e49938756fb2d501c93c44f8fb5b970cc63",
+ "sha256:eba238cf1989dfff7d483c029acb0ac4fcbfc15de295d682901f0e2497e6781a"
+ ],
+ "index": "pypi",
+ "version": "==5.6.3"
+ },
+ "ptyprocess": {
+ "hashes": [
+ "sha256:923f299cc5ad920c68f2bc0bc98b75b9f838b93b599941a6b63ddbc2476394c0",
+ "sha256:d7cc528d76e76342423ca640335bd3633420dc1366f258cb31d05e865ef5ca1f"
+ ],
+ "markers": "os_name != 'nt'",
+ "version": "==0.6.0"
+ },
+ "pycocotools": {
+ "git": "https://github.com/cocodataset/cocoapi.git",
+ "ref": "aca78bcd6b4345d25405a64fdba1120dfa5da1ab",
+ "subdirectory": "PythonAPI"
+ },
+ "pycparser": {
+ "hashes": [
+ "sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3"
+ ],
+ "version": "==2.19"
+ },
+ "pycurl": {
+ "hashes": [
+ "sha256:0f0cdfc7a92d4f2a5c44226162434e34f7d6967d3af416a6f1448649c09a25a4",
+ "sha256:10510a0016c862af467c6e069e051409f15f5831552bed03f5104b395a5d7dd1",
+ "sha256:208dd2c89e80d32a69397ba8a5cdb3bc0dc60f961a4f2a9662e5e1624dc799d1",
+ "sha256:6dc6ee5e7628400083471cba8044010860fe8b22e4dee05e42150a68047d7d9d",
+ "sha256:794bda39ea6fe434b6e1f58ab3bea9f0e6123fb43702fecd760eed6f1547b20a",
+ "sha256:dae7277e7c06da00947f3cd32c095b1e65eae09f07478ada4ea9dfa57020b646",
+ "sha256:eccea049aef47decc380746b3ff242d95636d578c907d0eab3b00918292d6c48"
+ ],
+ "index": "pypi",
+ "version": "==7.43.0.2"
+ },
+ "pygame": {
+ "hashes": [
+ "sha256:0480fe82cd41a43e3eea497fa2c059c72ac54cb5d003d5aa2ed06a04541c384e",
+ "sha256:136a3b5711d9ec369a0407e4e08ffced3ba61aa41059e9280ffffa79c8614f65",
+ "sha256:2622b9dd95f445c887a36a57eade42c672598589f69a8052ccdb8eeeffa4dbb1",
+ "sha256:301c6428c0880ecd4a9e3951b80e539c33863b6ff356a443db1758de4f297957",
+ "sha256:398c42b605ecc514e62f68f1944a2d21e247938309f598de6cb0ad3c207324a8",
+ "sha256:4aaff572a273a32e70ec3593d213e59ab11c183a9916616562247930f17a5447",
+ "sha256:4e1065577f1b29111113be5deb2ea88553551a5e1cf33e0c08fa32768f285809",
+ "sha256:5f052dc2975a399aa1830c1f04c5f72856aa416bf3cd4b31375a058015a5c620",
+ "sha256:68ea43e51150316b9fb08e251209d4e2b4e76a340b5b6fc8cdf1a898c78f7e5b",
+ "sha256:698433a9fcefca0527244dc44dff9503eb26157494730b1cc80e6e4dbb246e92",
+ "sha256:6f714986f7987f10cb94f1be0753318e341a7ea6b12d66f37a4d5d6dd4695023",
+ "sha256:73cd9df328c7e72638dbcc1d18e7155225faed880a53db6bad90d1d7c0a71dfd",
+ "sha256:7876d1f29f66d3d7cac46479503891ee1ef409b0fbce54b0d74f3a6b33a46dba",
+ "sha256:854e87b8b2b76e3ed11d64985fcfdd7af919659503de99fc2b0a717b314c3cf0",
+ "sha256:8da13704ad45b7d5de8a8cca135a7f44c7fc6aa9f691abe7b0392468a34a8013",
+ "sha256:9ce22fb72298ea33dbb3a1c6c60a4a4e19d9698df6f3f5782eba4dada7b7736d",
+ "sha256:a37b6c59e7b8feadc51db5197052b86ceb6443f9fb2a6f7d6527620e707c558c",
+ "sha256:a6e8d2f99dbe1dfe72d0c019693c14d93c410f702d0b04ec9a81b36dacd55a23",
+ "sha256:a9ac862dd7159861f2c6443b0029089e1c0c4ec762a8074022914ec52fe4dfac",
+ "sha256:ae1bc3e78ed28f20878e7ca2c98663a6634e9c00d7746d39413fc18e907dc162",
+ "sha256:be7e70f91bd4eb35ae081062f16bf434619b3292358d9b061f8159ddc570c7f0",
+ "sha256:c895cf9c1b6d1cbba8cb8cc3f5427febcf8aa41a9333697741abeea1c537a350",
+ "sha256:f1f5714d2c23f6a64ef2ac4fcd36a2dd2689da85978d951a99a6ae5dfdf9bdbc",
+ "sha256:fa788f775680fc5d268ab00a2da29c9a22830032cfab732730298a2952cd87f3"
+ ],
+ "index": "pypi",
+ "version": "==1.9.6"
+ },
+ "pygments": {
+ "hashes": [
+ "sha256:71e430bc85c88a430f000ac1d9b331d2407f681d6f6aec95e8bcfbc3df5b0127",
+ "sha256:881c4c157e45f30af185c1ffe8d549d48ac9127433f2c380c24b84572ad66297"
+ ],
+ "index": "pypi",
+ "version": "==2.4.2"
+ },
+ "pyjwt": {
+ "hashes": [
+ "sha256:5c6eca3c2940464d106b99ba83b00c6add741c9becaec087fb7ccdefea71350e",
+ "sha256:8d59a976fb773f3e6a39c85636357c4f0e242707394cadadd9814f5cbaa20e96"
+ ],
+ "index": "pypi",
+ "version": "==1.7.1"
+ },
+ "pylint": {
+ "hashes": [
+ "sha256:02c2b6d268695a8b64ad61847f92e611e6afcff33fd26c3a2125370c4662905d",
+ "sha256:ee1e85575587c5b58ddafa25e1c1b01691ef172e139fc25585e5d3f02451da93"
+ ],
+ "index": "pypi",
+ "version": "==1.9.4"
+ },
+ "pymongo": {
+ "hashes": [
+ "sha256:32421df60d06f479d71b6b539642e410ece3006e8910688e68df962c8eb40a21",
+ "sha256:324b22a8443e11faca44c96b20e7ec8a9e59a1e664457edeeb4f796080b31cde",
+ "sha256:4505ff8b7923dd7a8bed1bf25c9c4d0df5ab0b8b2821f2296533f2149a55f401",
+ "sha256:460b224681ea711e48e3638d15be2249024031b7dcb9622ba19c2e85bd5a26cc",
+ "sha256:47473b70c5f3cd5ddd2c49ab3b9ceafdafbbed5bc963f147df22a9343d7978f5",
+ "sha256:49375839af76834e9c5c3cc78c78386873fd0b2ad9a0860a7dc4ec9fe73af9dd",
+ "sha256:4a65f0f71ece86c860d30a1436b646db8ea32aec518845ef2903ca569faec32e",
+ "sha256:530621906c5dd6d27305b39c4e017701e5f4299aa68b93cde70eb985f94ca26f",
+ "sha256:54f4770b5810e8dc3cbeed675874195f02bb2bc4e95a9d665068edfb3baff4f7",
+ "sha256:5ed9382410e938b0ff76041c34018210504729a83bcf4f6a70c7092c28169f6f",
+ "sha256:61cad83637ae12c1c825130d7f9325cd6c162e3a64e8747a8144866020be3ff4",
+ "sha256:61e8e1c58b4fdf47ab79b7c7db8bb022c1e40b3b5fcbbaeea5fc94dc5c75638d",
+ "sha256:6e04e496af7d156b66cce70460011c621ecbadf5dcdce325c7acbb3cd6ea245d",
+ "sha256:7ef89ec435e89da902451dde6845066fe2770befaf0301fe2a1ac426b51fced3",
+ "sha256:854e8425e5eb775ccfffad04ecd094c99923d60a2c2d49babb5c435e836a91fa",
+ "sha256:9569796d48498e4db4e1d56284b626a8ed15f641ce3a8b2085f06bb03f4c2c88",
+ "sha256:9d50c99c6388863cbfdc5db9bad62e3a7c2e5fc151554a07c7f3c2530334a34f",
+ "sha256:9ea016c2c011df21f77c1f806ce45129a344ba2d414bd50f9e065b13a4a134be",
+ "sha256:a8421f0823174888fb12a5fa675322e756499d71e77ff712b4412d4b8f3c6503",
+ "sha256:aef7d88384ada699976350a285c7a333f96ebc959e98e7d2c98589f47bbf3b7f",
+ "sha256:b4d7ff9957ee770cf03bd7156a68a2f2e838e60712d9608eadc8741c15d01e72",
+ "sha256:c1db85c39e6a60588f855dbc7bd68fb0dab796096148ab5aa4abecaff19e1c6e",
+ "sha256:cee2fc0b94e66e7230da12fc4b3d34793c49957e16ee04f6468a94e264a1e41d",
+ "sha256:cf1dea28379a16b23e47db312883f07b3ba8d9d6abc1c59e51d4c8ae1820ab43",
+ "sha256:d1cd175df7c8b5fc976bade78bf4d9fb5aa7ab465c0f59931e380bbe188ef8fc",
+ "sha256:d48a94edf3cdd34524936a72ea01b352682b337f33a42db10ba29a96c37147d3",
+ "sha256:d9cc103a4e97f78bc77a1d72759ab3722f6cdf0374ad4fb4b0c53bd3238bdf98",
+ "sha256:fcb9ae8aa9158106c5d98a4349ec0d90b68f052d620b2d24622ba03b91e4d81d"
+ ],
+ "index": "pypi",
+ "version": "==3.8.0"
+ },
+ "pymysql": {
+ "hashes": [
+ "sha256:95f057328357e0e13a30e67857a8c694878b0175797a9a203ee7adbfb9b1ec5f",
+ "sha256:9ec760cbb251c158c19d6c88c17ca00a8632bac713890e465b2be01fdc30713f"
+ ],
+ "index": "pypi",
+ "version": "==0.9.2"
+ },
+ "pynacl": {
+ "hashes": [
+ "sha256:05c26f93964373fc0abe332676cb6735f0ecad27711035b9472751faa8521255",
+ "sha256:0c6100edd16fefd1557da078c7a31e7b7d7a52ce39fdca2bec29d4f7b6e7600c",
+ "sha256:0d0a8171a68edf51add1e73d2159c4bc19fc0718e79dec51166e940856c2f28e",
+ "sha256:1c780712b206317a746ace34c209b8c29dbfd841dfbc02aa27f2084dd3db77ae",
+ "sha256:2424c8b9f41aa65bbdbd7a64e73a7450ebb4aa9ddedc6a081e7afcc4c97f7621",
+ "sha256:2d23c04e8d709444220557ae48ed01f3f1086439f12dbf11976e849a4926db56",
+ "sha256:30f36a9c70450c7878053fa1344aca0145fd47d845270b43a7ee9192a051bf39",
+ "sha256:37aa336a317209f1bb099ad177fef0da45be36a2aa664507c5d72015f956c310",
+ "sha256:4943decfc5b905748f0756fdd99d4f9498d7064815c4cf3643820c9028b711d1",
+ "sha256:57ef38a65056e7800859e5ba9e6091053cd06e1038983016effaffe0efcd594a",
+ "sha256:5bd61e9b44c543016ce1f6aef48606280e45f892a928ca7068fba30021e9b786",
+ "sha256:6482d3017a0c0327a49dddc8bd1074cc730d45db2ccb09c3bac1f8f32d1eb61b",
+ "sha256:7d3ce02c0784b7cbcc771a2da6ea51f87e8716004512493a2b69016326301c3b",
+ "sha256:a14e499c0f5955dcc3991f785f3f8e2130ed504fa3a7f44009ff458ad6bdd17f",
+ "sha256:a39f54ccbcd2757d1d63b0ec00a00980c0b382c62865b61a505163943624ab20",
+ "sha256:aabb0c5232910a20eec8563503c153a8e78bbf5459490c49ab31f6adf3f3a415",
+ "sha256:bd4ecb473a96ad0f90c20acba4f0bf0df91a4e03a1f4dd6a4bdc9ca75aa3a715",
+ "sha256:e2da3c13307eac601f3de04887624939aca8ee3c9488a0bb0eca4fb9401fc6b1",
+ "sha256:f67814c38162f4deb31f68d590771a29d5ae3b1bd64b75cf232308e5c74777e0"
+ ],
+ "index": "pypi",
+ "version": "==1.3.0"
+ },
+ "pynmea2": {
+ "hashes": [
+ "sha256:8b83fa7e3e668af5e182ef1c2fd4a535433ecadf60d7b627280172d695a1646b",
+ "sha256:fe786594299588d1bfbd346ece2c2c1e5b24e160dcb740813c34bfa70d0a141d"
+ ],
+ "index": "pypi",
+ "version": "==1.15.0"
+ },
+ "pyparsing": {
+ "hashes": [
+ "sha256:1873c03321fc118f4e9746baf201ff990ceb915f433f23b395f5580d1840cb2a",
+ "sha256:9b6323ef4ab914af344ba97510e966d64ba91055d6b9afa6b30799340e89cc03"
+ ],
+ "version": "==2.4.0"
+ },
+ "pypolyline": {
+ "hashes": [
+ "sha256:09cc2192bc12063c7afa2d2718b739cd4bf3f8ec29eacde0cb728c9f5f7f7858",
+ "sha256:21acee0e31d867bde04583907ccb7afe4b21d33a63c23adc7cf0d82b6f2feab3",
+ "sha256:5e0643454b4471f4f23d38530467ee7093d3b375898d5e1b054876e5a50a6b89",
+ "sha256:6b0a1b573fe84c9ed0aa3a4eb9903d44864f37e405cdcc7396b61e6d00a937d6",
+ "sha256:6bdbc9210f29d4fd44c3e4d510ffcc1276e46a50d63365831e2e422dc0b3cb43",
+ "sha256:8efb93097c92c5894dcaf9e784b888f9426d170ae51d62164341bbb2b832c09a",
+ "sha256:9c843a35b2d02b04c1226db851834b55f0de30eef47ba057fd6f8623cdef6f2d",
+ "sha256:ad01fedf427536f391776b329c95e5f80f2b1a5d25c54ea7713c8cdb56947106",
+ "sha256:e4e4c857790f6a3067dab3ae661edda99d5cee55d107b3b4d0186159431165ef",
+ "sha256:f8c84f0d2aa6bd9ed14bdb671fab80f79b4ba93b4347b530ae4d3b56a3fb269a"
+ ],
+ "index": "pypi",
+ "version": "==0.1.17"
+ },
+ "pyrsistent": {
+ "hashes": [
+ "sha256:16692ee739d42cf5e39cef8d27649a8c1fdb7aa99887098f1460057c5eb75c3a"
+ ],
+ "version": "==0.15.2"
+ },
+ "pysdl2": {
+ "hashes": [
+ "sha256:b52acab5493a77b08c2afee1f385769fc2005f17cfeaf1886eff22dc78da2123"
+ ],
+ "index": "pypi",
+ "version": "==0.9.6"
+ },
+ "pysendfile": {
+ "hashes": [
+ "sha256:510a414b270986fba3c79cb76d90a4c910c701bfb43ff983a5d4e92846050e17"
+ ],
+ "index": "pypi",
+ "version": "==2.0.1"
+ },
+ "python-dateutil": {
+ "hashes": [
+ "sha256:7e6584c74aeed623791615e26efd690f29817a27c73085b78e4bad02493df2fb",
+ "sha256:c89805f6f4d64db21ed966fda138f8a5ed7a4fdbc1a8ee329ce1b74e3c74da9e"
+ ],
+ "index": "pypi",
+ "version": "==2.8.0"
+ },
+ "python-engineio": {
+ "hashes": [
+ "sha256:9e4e7109d05d80ce5414f13b16f66725c2b5d574099fd43d37b024e7ea1c4354",
+ "sha256:d3315d3f972bd9bd32e0738d45801a912f522177ff75094762f31a8c341d1f41"
+ ],
+ "version": "==3.8.1"
+ },
+ "python-logstash": {
+ "hashes": [
+ "sha256:10943e5df83f592b4d61b63ad1afff855ccc8c9467f78718f0a59809ba1fe68c"
+ ],
+ "index": "pypi",
+ "version": "==0.4.6"
+ },
+ "python-socketio": {
+ "hashes": [
+ "sha256:89a48591a8850c1f30d735f8e5a0294846da245a9b8940c39e1106e460c7a14e",
+ "sha256:c7ffeac3d81f2d8d63b3ec7ed1e2d4478cc84aa1da666c1934c19432f4b8c0f8"
+ ],
+ "version": "==4.1.0"
+ },
+ "python-utils": {
+ "hashes": [
+ "sha256:34aaf26b39b0b86628008f2ae0ac001b30e7986a8d303b61e1357dfcdad4f6d3",
+ "sha256:e25f840564554eaded56eaa395bca507b0b9e9f0ae5ecb13a8cb785305c56d25"
+ ],
+ "version": "==2.3.0"
+ },
+ "pytz": {
+ "hashes": [
+ "sha256:303879e36b721603cc54604edcac9d20401bdbe31e1e4fdee5b9f98d5d31dfda",
+ "sha256:d747dd3d23d77ef44c6a3526e274af6efeb0a6f1afd5a69ba4d5be4098c8e141"
+ ],
+ "version": "==2019.1"
+ },
+ "pyvcd": {
+ "hashes": [
+ "sha256:791fd7608fb8113c9658f699cb6292d66d7fb90bcab9ebc00b05adc40da7a5ce",
+ "sha256:bdcb848b79cea2196ebf317178eff2c9c7d6354b85f9eb4991e9175f98e26937"
+ ],
+ "index": "pypi",
+ "version": "==0.1.4"
+ },
+ "pywavelets": {
+ "hashes": [
+ "sha256:18b193b67937e805a8e79c036bd2aa4ea3a357737256efeefdabd19c95083c3b",
+ "sha256:1d7ba03baa81938b17d4819db36f018e680d929af329062af4d4b6d6236d02ba",
+ "sha256:21f39d86cc35e003576fc1400b15534e2999570418fcdb17ea62d1ff8773b076",
+ "sha256:250412f482d5cb358b7ec323b2a783d91e5cfc337fdf8fde3c59bf2c35d6366f",
+ "sha256:25c0c592bf43eaffb4d3c6b6444b14c7407db750b6f2d344d809d4af934319d9",
+ "sha256:2f2cdd96e4882b0c18e75cc90c4710de429ac226ce53b58a90c7420e3e307631",
+ "sha256:3abed8dcd3e94ead72ee8010b494df5a9bdbdd5e39129d52fbf8066efa323a51",
+ "sha256:3e99ab8feeb47755738fb8deb8154c9604c4a7996b1b7db6b090475105ca7c92",
+ "sha256:64926c4c78dd690ec0d61be20f7c27cfbde6de9fa66ab8205eb079d9db6927fc",
+ "sha256:687ec8877c10e3a03595ad167d1ea2662bc1ab13ef43d63a6e207a53b2ee4c26",
+ "sha256:6af0077c7a4c9935aa64301f6942468b494656b8812e801d4a635cf42088f96c",
+ "sha256:7215856a5d2e1a2dccca1f71d912ee6a7387086f3b3adcb55d7c41314c6abb0c",
+ "sha256:9e47b241533add77961093b1e40cfff031597d429e91ad7c675838be0f7cc0df",
+ "sha256:9e782f49dca57bc0fd2a40c0917949d77be2ecc999ccd44fff57fb10aa214135",
+ "sha256:a12c7a6258c0015d2c75d88b87393ee015494551f049009e8b63eafed2d78efc",
+ "sha256:a5027d47484498e70391b311a2688c4f74294de629b982ed17be57be4c77ade7",
+ "sha256:ab02363467ee3cb222c5b425bc53453270ddae72bce313e72fd14616692d725a",
+ "sha256:adc79308c65a2007bdbd5846fda70088e7ead0ef0a5a6f44d08829e9478a907f",
+ "sha256:afaaee392450785a346d9e5e5f6e5307b13958d8b0633818632cb38972a7752a",
+ "sha256:b26b836c7f71df7b2779e62d1338367cfe37b98324e9b0d54b428ac030e3d1f0",
+ "sha256:b9adbc27d70a2626c235a18b41315de2832c384651d03383db7a58c2a2bccc6f",
+ "sha256:bd6e62efb7839fd6bf894b7b9aec6d58be0c44a38ea0c9f3c5bea834d84d05eb",
+ "sha256:de083a3a71576a9c3d8ba73b6f0425e4690d6ac6e480562f30bec5cb20667324",
+ "sha256:e89551257233a3da717a9e6e2e303243df75faffe0b6781d21c15eb9d682ec6d",
+ "sha256:eafb7d609c41a04028144f4b6697792f448554960ef353244aaf0a5883263543",
+ "sha256:fb3ee9f65d25ee5c89104e533d5f341c253cdb9543ef6fcd6dfa599b12e84f1c"
+ ],
+ "version": "==1.0.3"
+ },
+ "pyyaml": {
+ "hashes": [
+ "sha256:57acc1d8533cbe51f6662a55434f0dbecfa2b9eaf115bede8f6fd00115a0c0d3",
+ "sha256:588c94b3d16b76cfed8e0be54932e5729cc185caffaa5a451e7ad2f7ed8b4043",
+ "sha256:68c8dd247f29f9a0d09375c9c6b8fdc64b60810ebf07ba4cdd64ceee3a58c7b7",
+ "sha256:70d9818f1c9cd5c48bb87804f2efc8692f1023dac7f1a1a5c61d454043c1d265",
+ "sha256:86a93cccd50f8c125286e637328ff4eef108400dd7089b46a7be3445eecfa391",
+ "sha256:a0f329125a926876f647c9fa0ef32801587a12328b4a3c741270464e3e4fa778",
+ "sha256:a3c252ab0fa1bb0d5a3f6449a4826732f3eb6c0270925548cac342bc9b22c225",
+ "sha256:b4bb4d3f5e232425e25dda21c070ce05168a786ac9eda43768ab7f3ac2770955",
+ "sha256:cd0618c5ba5bda5f4039b9398bb7fb6a317bb8298218c3de25c47c4740e4b95e",
+ "sha256:ceacb9e5f8474dcf45b940578591c7f3d960e82f926c707788a570b51ba59190",
+ "sha256:fe6a88094b64132c4bb3b631412e90032e8cfe9745a58370462240b8cb7553cd"
+ ],
+ "index": "pypi",
+ "version": "==5.1.1"
+ },
+ "pyzmq": {
+ "hashes": [
+ "sha256:1651e52ed91f0736afd6d94ef9f3259b5534ce8beddb054f3d5ca989c4ef7c4f",
+ "sha256:5ccb9b3d4cd20c000a9b75689d5add8cd3bce67fcbd0f8ae1b59345247d803af",
+ "sha256:5e120c4cd3872e332fb35d255ad5998ebcee32ace4387b1b337416b6b90436c7",
+ "sha256:5e2a3707c69a7281a9957f83718815fd74698cba31f6d69f9ed359921f662221",
+ "sha256:63d51add9af8d0442dc90f916baf98fdc04e3b0a32afec4bfc83f8d85e72959f",
+ "sha256:65c5a0bdc49e20f7d6b03a661f71e2fda7a99c51270cafe71598146d09810d0d",
+ "sha256:66828fabe911aa545d919028441a585edb7c9c77969a5fea6722ef6e6ece38ab",
+ "sha256:7d79427e82d9dad6e9b47c0b3e7ae5f9d489b1601e3a36ea629bb49501a4daf3",
+ "sha256:824ee5d3078c4eae737ffc500fbf32f2b14e6ec89b26b435b7834febd70120cf",
+ "sha256:89dc0a83cccec19ff3c62c091e43e66e0183d1e6b4658c16ee4e659518131494",
+ "sha256:8b319805f6f7c907b101c864c3ca6cefc9db8ce0791356f180b1b644c7347e4c",
+ "sha256:90facfb379ab47f94b19519c1ecc8ec8d10813b69d9c163117944948bdec5d15",
+ "sha256:a0a178c7420021fc0730180a914a4b4b3092ce9696ceb8e72d0f60f8ce1655dd",
+ "sha256:a7a89591ae315baccb8072f216614b3e59aed7385aef4393a6c741783d6ee9cf",
+ "sha256:ba2578f0ae582452c02ed9fac2dc477b08e80ce05d2c0885becf5fff6651ccb0",
+ "sha256:c69b0055c55702f5b0b6b354133e8325b9a56dbc80e1be2d240bead253fb9825",
+ "sha256:ca434e1858fe222380221ddeb81e86f45522773344c9da63c311d17161df5e06",
+ "sha256:d4b8ecfc3d92f114f04d5c40f60a65e5196198b827503341521dda12d8b14939",
+ "sha256:d706025c47b09a54f005953ebe206f6d07a22516776faa4f509aaff681cc5468",
+ "sha256:d8f27e958f8a2c0c8ffd4d8855c3ce8ac3fa1e105f0491ce31729aa2b3229740",
+ "sha256:dbd264298f76b9060ce537008eb989317ca787c857e23cbd1b3ddf89f190a9b1",
+ "sha256:e926d66f0df8fdbf03ba20583af0f215e475c667fb033d45fd031c66c63e34c9",
+ "sha256:efc3bd48237f973a749f7312f68062f1b4ca5c2032a0673ca3ea8e46aa77187b",
+ "sha256:f59bc782228777cbfe04555707a9c56d269c787ed25d6d28ed9d0fbb41cb1ad2",
+ "sha256:f8da5322f4ff5f667a0d5a27e871b560c6637153c81e318b35cb012b2a98835c"
+ ],
+ "index": "pypi",
+ "version": "==18.0.1"
+ },
+ "qtconsole": {
+ "hashes": [
+ "sha256:4af84facdd6f00a6b9b2927255f717bb23ae4b7a20ba1d9ef0a5a5a8dbe01ae2",
+ "sha256:60d61d93f7d67ba2b265c6d599d413ffec21202fec999a952f658ff3a73d252b"
+ ],
+ "version": "==4.5.1"
+ },
+ "redis": {
+ "hashes": [
+ "sha256:6946b5dca72e86103edc8033019cc3814c031232d339d5f4533b02ea85685175",
+ "sha256:8ca418d2ddca1b1a850afa1680a7d2fd1f3322739271de4b704e0d4668449273"
+ ],
+ "index": "pypi",
+ "version": "==3.2.1"
+ },
+ "redlock": {
+ "hashes": [
+ "sha256:b718646239d300745475a76e81d350ec523e7146cf84d696b3c4a7dfdd5dd4d4",
+ "sha256:ce7e6ab404882b64a9c5017c7a78b1a3714f2c712635bcb22cbb74d20719bbd1"
+ ],
+ "index": "pypi",
+ "version": "==1.2.0"
+ },
+ "requests": {
+ "hashes": [
+ "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4",
+ "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31"
+ ],
+ "index": "pypi",
+ "version": "==2.22.0"
+ },
+ "requests-oauthlib": {
+ "hashes": [
+ "sha256:bd6533330e8748e94bf0b214775fed487d309b8b8fe823dc45641ebcd9a32f57",
+ "sha256:d3ed0c8f2e3bbc6b344fa63d6f933745ab394469da38db16bdddb461c7e25140"
+ ],
+ "version": "==1.2.0"
+ },
+ "reverse-geocoder": {
+ "hashes": [
+ "sha256:2a2e781b5f69376d922b78fe8978f1350c84fce0ddb07e02c834ecf98b57c75c"
+ ],
+ "index": "pypi",
+ "version": "==1.5.1"
+ },
+ "s2sphere": {
+ "hashes": [
+ "sha256:c2478c1ff7c601a59a7151a57b605435897514578fa6bdb8730721c182adbbaf",
+ "sha256:d2340c9cf458ddc9a89afd1d8048a4195ce6fa6b0095ab900d4be5271e537401"
+ ],
+ "index": "pypi",
+ "version": "==0.2.5"
+ },
+ "s3transfer": {
+ "hashes": [
+ "sha256:6efc926738a3cd576c2a79725fed9afde92378aa5c6a957e3af010cb019fac9d",
+ "sha256:b780f2411b824cb541dbcd2c713d0cb61c7d1bcadae204cdddda2b35cef493ba"
+ ],
+ "version": "==0.2.1"
+ },
+ "scandir": {
+ "hashes": [
+ "sha256:2586c94e907d99617887daed6c1d102b5ca28f1085f90446554abf1faf73123e",
+ "sha256:2ae41f43797ca0c11591c0c35f2f5875fa99f8797cb1a1fd440497ec0ae4b022",
+ "sha256:2b8e3888b11abb2217a32af0766bc06b65cc4a928d8727828ee68af5a967fa6f",
+ "sha256:2c712840c2e2ee8dfaf36034080108d30060d759c7b73a01a52251cc8989f11f",
+ "sha256:4d4631f6062e658e9007ab3149a9b914f3548cb38bfb021c64f39a025ce578ae",
+ "sha256:67f15b6f83e6507fdc6fca22fedf6ef8b334b399ca27c6b568cbfaa82a364173",
+ "sha256:7d2d7a06a252764061a020407b997dd036f7bd6a175a5ba2b345f0a357f0b3f4",
+ "sha256:8c5922863e44ffc00c5c693190648daa6d15e7c1207ed02d6f46a8dcc2869d32",
+ "sha256:92c85ac42f41ffdc35b6da57ed991575bdbe69db895507af88b9f499b701c188",
+ "sha256:b24086f2375c4a094a6b51e78b4cf7ca16c721dcee2eddd7aa6494b42d6d519d",
+ "sha256:cb925555f43060a1745d0a321cca94bcea927c50114b623d73179189a4e100ac"
+ ],
+ "markers": "python_version < '3.5'",
+ "version": "==1.10.0"
+ },
+ "scikit-image": {
+ "hashes": [
+ "sha256:056632aa964528c484758829d295f11c86a405aa0294f2578eac4acd945d4300",
+ "sha256:1600628c96b76f265dede2393115f77d93a427c617202622dfd6ba27e075efcc",
+ "sha256:1e85573ed37e0205ea918475c1fbd12e6c118c6f1e166dd159af04bcd9d4fa30",
+ "sha256:1fc4a596d6b7295bd05dce3df1105d1c7c7abe9c65f5d3ced2eace1cd746c15e",
+ "sha256:24ebe2a9cf40f2196393bc575345bc514bc845366545361785696a76e3aeb89b",
+ "sha256:331ee6db27e434e467831e21c8489bec23038ede790c53e0b6040e1e638fff45",
+ "sha256:4c17f2919029bd68907e2bf80dfecfb8b601bee4f392ef01f835ba4aa8c616e9",
+ "sha256:4e59c25be3e9760ba181832b9b33e27ff3cea9c362842260ac06644ae08b23c8",
+ "sha256:4f12cdf72155f77b736902e87c6b4544e311241070e9548c03ac0fcf9aa0bbed",
+ "sha256:62718e67f1f058501055c7e6b7206eea96f792039ea4c87af8e6b706a22ae11e",
+ "sha256:6b88c64f8351f1755ccc7feec26a7e55359acba2375498409fa1380bd3789b6f",
+ "sha256:755ee87e4b0332fd1645c67fd1e5780908937f35d28a6bd3377af304fd54a8d9",
+ "sha256:8508b9a2fccaa52a30785316ae4b29aaf339ef8fc3dab1bb35d36468397e0b0d",
+ "sha256:8541cefddad87b08105583e946132e822b196fff437f407afa92742e1e763387",
+ "sha256:8d76474ad59e5339584a9c4317868e51c0fbf2c2d11a936e836279fc281633d6",
+ "sha256:b26462abeee13ee249c814723a3038ccd74af2144349422d1b344e1378f9f702",
+ "sha256:b7b5605c7737073c1bdffbfea1f6a257dd6e96ab109fc37f43a7bd3d1d581e2a",
+ "sha256:c7afc4231e9bb9d0d2b44958e6e403117e6823bb16bca61ab95540e737f2941f",
+ "sha256:cc97cfc239f1f7ee8cc5129e3cb29fe553237fa62380b62d6f7c0909974d1400",
+ "sha256:ce114f536941348998665360ea6fbbf1577a3c49a5c2b4d416c71d3edde05ab7",
+ "sha256:db9f4fb00db5ce5855737c22abbdc22d9663d44643cbdad674e2c9fc32ba9c16",
+ "sha256:e312e914d6f97e525460268cd0d215cd9c9c4fe131457316bd32c6c760171660",
+ "sha256:e50d053133c292efe0e70eefc6a6481002b32d7b4b72ef38bd7caae6b24fb7d6",
+ "sha256:ef3fb33404fbf1717e3d268e1cc0983264fc3154036b29950fbc9c3fbed98ee3",
+ "sha256:f05eab2df885fb6fde3df0e4d24c9c620d6474ea0eb949fd45f6f634925dd514",
+ "sha256:fb1de3dabbc7a429b38a016d01502920226b59d277578291fb18a28888ed5792"
+ ],
+ "index": "pypi",
+ "version": "==0.14.3"
+ },
+ "scipy": {
+ "hashes": [
+ "sha256:0bcababa06ff83138a7f30a68f334dee034ce1cc7604f9278b96f62265fe7fd7",
+ "sha256:162b803984ebb76927990d7233cab825d146be8e2a3f6a0efb1b3a61ebacae73",
+ "sha256:271c6e56c8f9a3d6c3f0bc857d7a6e7cf7a8415c879a3915701cd011e82a83a3",
+ "sha256:2eb255b30dac7516c6f3c5237f2e0ad1f1213b5364de409d932249c9a8c5bffb",
+ "sha256:447c40d33ec5e0020750fadbb8599220b9eb9fd8798030efe9b308247800f364",
+ "sha256:4686d699f76068757a81269f1a111c0db689bf048a56b131a339803121534fa8",
+ "sha256:47d4623efa71948dc4a92f978fbf6b9fb69dac5b0f0fae4c1a1f3d955ac8aea9",
+ "sha256:49dcebc6f57bce0bd23cb55dbc6144f4990e5cbce9aab3128af03d6b1b4eab6a",
+ "sha256:5fa84b467b5f77c243c5701628ed7a4238e53bc4120db87be7dafa416e842fb9",
+ "sha256:67d2210c7f6f585e1055bee3dc9f15610b5ebb04e80bfaa757868937ee744fec",
+ "sha256:682b210ff7a65f6f5245fdf73d26a348b57e42d2059bc5fcf7ed25d063f35c45",
+ "sha256:7f58faa422aa493d7b70dd56d6e8783223e84dd6e7f4b4161bd776b39ecbac92",
+ "sha256:7fb4efff9895116428ad65564d2232fb1cac4b9d84398512a858b09dd4a7fd59",
+ "sha256:922e2370674c82dd1367fc13a08c8765f4e5281a584d871e7cb454828d84600f",
+ "sha256:97f26b4b5d4456f44849fd35cad8801f7cae4e64b75fc4e522d26a54aef17391",
+ "sha256:9a21d64d002cb3a9239a55c0aa100b48d58b5e38382c0fdfcdfc68cf417d8142",
+ "sha256:a4331e0b8dab1ff75d2c67b5158a8bb9a83c799d7140094dda936d876c7cfbb1",
+ "sha256:a9fc1fcaa560edf771d4545d7e6dd865a213fc5b485bb127de5dfd32f40094e1",
+ "sha256:b074a83299a82eae617dc46a830cfa7aaa588d07523990507848ee1ded3c52ce",
+ "sha256:bcd0d4b2de5cb3fab69007214a39737e917267f56f887ce9c7732ba3278fc33d",
+ "sha256:c390f1721757ec983616149f00e1bd0432aa32d2c1d9398930d7e7cc9542c922",
+ "sha256:c5b9db9e3f6537bf7b308de12c185b27f22fb9a66fd12efc7aefbcfa0adb4d82",
+ "sha256:d0d41a9ee3264f95820138170b447f5d3e453e5ebd10b411bca37c99237aac69",
+ "sha256:d18d1575d4a54f128c0f34422bd73ce0f177e462d6124f074388e211d8dc2616",
+ "sha256:e99cd49daffe7384fd35046c3b14bee98ce87d97c95865469227001905534e13",
+ "sha256:f4e355afa8fdda11010de308c2376edda29e064cec699974097364115f71e16f",
+ "sha256:f64e29a8b32d672fb6078f456bfff3cae8f36b6c8b64c337ad0942f29404b03f",
+ "sha256:fbdff021643c2dfa35efd29218e0318c4b4987f48ea432be7e8c02bdb1b0c314"
+ ],
+ "index": "pypi",
+ "version": "==1.2.2"
+ },
+ "send2trash": {
+ "hashes": [
+ "sha256:60001cc07d707fe247c94f74ca6ac0d3255aabcb930529690897ca2a39db28b2",
+ "sha256:f1691922577b6fa12821234aeb57599d887c4900b9ca537948d2dac34aea888b"
+ ],
+ "version": "==1.5.0"
+ },
+ "shapely": {
+ "hashes": [
+ "sha256:0378964902f89b8dbc332e5bdfa08e0bc2f7ab39fecaeb17fbb2a7699a44fe71",
+ "sha256:34e7c6f41fb27906ccdf2514ee44a5774b90b39a256b6511a6a57d11ffe64999",
+ "sha256:3ca69d4b12e2b05b549465822744b6a3a1095d8488cc27b2728a06d3c07d0eee",
+ "sha256:3e9388f29bd81fcd4fa5c35125e1fbd4975ee36971a87a90c093f032d0e9de24",
+ "sha256:3ef28e3f20a1c37f5b99ea8cf8dcb58e2f1a8762d65ed2d21fd92bf1d4811182",
+ "sha256:523c94403047eb6cacd7fc1863ebef06e26c04d8a4e7f8f182d49cd206fe787e",
+ "sha256:5d22a1a705c2f70f61ccadc696e33d922c1a92e00df8e1d58a6ade14dd7e3b4f",
+ "sha256:714b6680215554731389a1bbdae4cec61741aa4726921fa2b2b96a6f578a2534",
+ "sha256:7dfe1528650c3f0dc82f41a74cf4f72018288db9bfb75dcd08f6f04233ec7e78",
+ "sha256:ba58b21b9cf3c33725f7f530febff9ed6a6846f9d0bf8a120fc74683ff919f89",
+ "sha256:c4b87bb61fc3de59fc1f85e71a79b0c709dc68364d9584473697aad4aa13240f",
+ "sha256:ebb4d2bee7fac3f6c891fcdafaa17f72ab9c6480f6d00de0b2dc9a5137dfe342"
+ ],
+ "index": "pypi",
+ "version": "==1.6.4.post2"
+ },
+ "simplegeneric": {
+ "hashes": [
+ "sha256:dc972e06094b9af5b855b3df4a646395e43d1c9d0d39ed345b7393560d0b9173"
+ ],
+ "version": "==0.8.1"
+ },
+ "simplejson": {
+ "hashes": [
+ "sha256:067a7177ddfa32e1483ba5169ebea1bc2ea27f224853211ca669325648ca5642",
+ "sha256:2fc546e6af49fb45b93bbe878dea4c48edc34083729c0abd09981fe55bdf7f91",
+ "sha256:354fa32b02885e6dae925f1b5bbf842c333c1e11ea5453ddd67309dc31fdb40a",
+ "sha256:37e685986cf6f8144607f90340cff72d36acf654f3653a6c47b84c5c38d00df7",
+ "sha256:3af610ee72efbe644e19d5eaad575c73fb83026192114e5f6719f4901097fce2",
+ "sha256:3b919fc9cf508f13b929a9b274c40786036b31ad28657819b3b9ba44ba651f50",
+ "sha256:3dd289368bbd064974d9a5961101f080e939cbe051e6689a193c99fb6e9ac89b",
+ "sha256:6c3258ffff58712818a233b9737fe4be943d306c40cf63d14ddc82ba563f483a",
+ "sha256:75e3f0b12c28945c08f54350d91e624f8dd580ab74fd4f1bbea54bc6b0165610",
+ "sha256:b1f329139ba647a9548aa05fb95d046b4a677643070dc2afc05fa2e975d09ca5",
+ "sha256:ee9625fc8ee164902dfbb0ff932b26df112da9f871c32f0f9c1bcf20c350fe2a",
+ "sha256:fb2530b53c28f0d4d84990e945c2ebb470edb469d63e389bf02ff409012fe7c5"
+ ],
+ "index": "pypi",
+ "version": "==3.16.0"
+ },
+ "singledispatch": {
+ "hashes": [
+ "sha256:5b06af87df13818d14f08a028e42f566640aef80805c3b50c5056b086e3c2b9c",
+ "sha256:833b46966687b3de7f438c761ac475213e53b306740f1abfaa86e1d1aae56aa8"
+ ],
+ "markers": "python_version < '3.4'",
+ "version": "==3.4.0.3"
+ },
+ "six": {
+ "hashes": [
+ "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c",
+ "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"
+ ],
+ "index": "pypi",
+ "version": "==1.12.0"
+ },
+ "sortedcontainers": {
+ "hashes": [
+ "sha256:974e9a32f56b17c1bac2aebd9dcf197f3eb9cd30553c5852a3187ad162e1a03a",
+ "sha256:d9e96492dd51fae31e60837736b38fe42a187b5404c16606ff7ee7cd582d4c60"
+ ],
+ "version": "==2.1.0"
+ },
+ "sqlalchemy": {
+ "hashes": [
+ "sha256:d6cda03b0187d6ed796ff70e87c9a7dce2c2c9650a7bc3c022cd331416853c31"
+ ],
+ "index": "pypi",
+ "version": "==1.2.7"
+ },
+ "subprocess32": {
+ "hashes": [
+ "sha256:88e37c1aac5388df41cc8a8456bb49ebffd321a3ad4d70358e3518176de3a56b",
+ "sha256:eb2937c80497978d181efa1b839ec2d9622cf9600a039a79d0e108d1f9aec79d"
+ ],
+ "index": "pypi",
+ "version": "==3.5.4"
+ },
+ "supervisor": {
+ "hashes": [
+ "sha256:a3289b9124e59aee1621d43b55cd1634468cb3212d09c5b0114a3183cc080cca",
+ "sha256:f768abc073e8702892718938b8a0ab98ebcb91c2afcb39bf2cb570d3eb51149e"
+ ],
+ "index": "pypi",
+ "version": "==4.0.3"
+ },
+ "tenacity": {
+ "hashes": [
+ "sha256:a0c3c5f7ae0c33f5556c775ca059c12d6fd8ab7121613a713e8b7d649908571b",
+ "sha256:b87c1934daa0b2ccc7db153c37b8bf91d12f165936ade8628e7b962b92dc7705"
+ ],
+ "index": "pypi",
+ "version": "==5.0.4"
+ },
+ "tensorboard": {
+ "hashes": [
+ "sha256:6f194519f41762bfdf5eb410ccf33226d1c252caf5ad8893288648bfbcf4d135",
+ "sha256:81170f66bf8f95c2e9f6b3fefe0ddc5472655a9e3793e73b5b5d4ec0ba395e76"
+ ],
+ "version": "==1.12.2"
+ },
+ "tensorflow-estimator": {
+ "hashes": [
+ "sha256:7cfdaa3e83e3532f31713713feb98be7ea9f3065722be4267e49b6c301271419"
+ ],
+ "version": "==1.13.0"
+ },
+ "tensorflow-gpu": {
+ "hashes": [
+ "sha256:0c2fa74a53009f72eb73da46ef8e78ffc09514349ba3de179c6b419b69a4bf09",
+ "sha256:17460b5f3525ddbbb1fb9f639955d3a999f9656cc7bf1be65bc78dea1a0cedea",
+ "sha256:2f85fdfee4eb93432bf8ef11428f2b5e17fb3e1b733599612329e165bb74a3fd",
+ "sha256:38be54cb1e757f95f24b2e03e71d7bcab359429267ff36c9e32de2ed17943a42",
+ "sha256:42c13cf5538125d93177b7901f23a1f6759b64f9f3f2d8680099b1fbfec37b83",
+ "sha256:b771297d3b93f93a20af1d2d7dc049bb9617e2c2ab25c36156b011bf1a49bd7c",
+ "sha256:ca68f7eb91e6101300ffc59a59c3b5600359a0ab6f2e1e8cde4a8a65ec21bb92"
+ ],
+ "index": "pypi",
+ "version": "==1.13.0rc0"
+ },
+ "termcolor": {
+ "hashes": [
+ "sha256:1d6d69ce66211143803fbc56652b41d73b4a400a2891d7bf7a1cdf4c02de613b"
+ ],
+ "version": "==1.1.0"
+ },
+ "terminado": {
+ "hashes": [
+ "sha256:d9d012de63acb8223ac969c17c3043337c2fcfd28f3aea1ee429b345d01ef460",
+ "sha256:de08e141f83c3a0798b050ecb097ab6259c3f0331b2f7b7750c9075ced2c20c2"
+ ],
+ "version": "==0.8.2"
+ },
+ "testpath": {
+ "hashes": [
+ "sha256:46c89ebb683f473ffe2aab0ed9f12581d4d078308a3cb3765d79c6b2317b0109",
+ "sha256:b694b3d9288dbd81685c5d2e7140b81365d46c29f5db4bc659de5aa6b98780f8"
+ ],
+ "version": "==0.4.2"
+ },
+ "theano": {
+ "hashes": [
+ "sha256:35c9bbef56b61ffa299265a42a4e8f8cb5a07b2997dabaef0f8830b397086913"
+ ],
+ "index": "pypi",
+ "version": "==1.0.4"
+ },
+ "torchfile": {
+ "hashes": [
+ "sha256:a53dfe134b737845a9f2cb24fe0585317874f965932cebdb0439d13c8da4136e"
+ ],
+ "version": "==0.1.0"
+ },
+ "tornado": {
+ "hashes": [
+ "sha256:0662d28b1ca9f67108c7e3b77afabfb9c7e87bde174fbda78186ecedc2499a9d",
+ "sha256:4e5158d97583502a7e2739951553cbd88a72076f152b4b11b64b9a10c4c49409",
+ "sha256:732e836008c708de2e89a31cb2fa6c0e5a70cb60492bee6f1ea1047500feaf7f",
+ "sha256:8154ec22c450df4e06b35f131adc4f2f3a12ec85981a203301d310abf580500f",
+ "sha256:8e9d728c4579682e837c92fdd98036bd5cdefa1da2aaf6acf26947e6dd0c01c5",
+ "sha256:d4b3e5329f572f055b587efc57d29bd051589fb5a43ec8898c77a47ec2fa2bbb",
+ "sha256:e5f2585afccbff22390cddac29849df463b252b711aa2ce7c5f3f342a5b3b444"
+ ],
+ "version": "==5.1.1"
+ },
+ "traitlets": {
+ "hashes": [
+ "sha256:9c4bd2d267b7153df9152698efb1050a5d84982d3384a37b2c1f7723ba3e7835",
+ "sha256:c6cb5e6f57c5a9bdaa40fa71ce7b4af30298fbab9ece9815b5d995ab6217c7d9"
+ ],
+ "version": "==4.3.2"
+ },
+ "transforms3d": {
+ "hashes": [
+ "sha256:404c7797c78aa461cb8043081901fc5517cef342d5ff56becd74a7967ba88d78"
+ ],
+ "index": "pypi",
+ "version": "==0.3.1"
+ },
+ "typing": {
+ "hashes": [
+ "sha256:4027c5f6127a6267a435201981ba156de91ad0d1d98e9ddc2aa173453453492d",
+ "sha256:57dcf675a99b74d64dacf6fba08fb17cf7e3d5fdff53d4a30ea2a5e7e52543d4",
+ "sha256:a4c8473ce11a65999c8f59cb093e70686b6c84c98df58c1dae9b3b196089858a"
+ ],
+ "markers": "python_version < '3.5'",
+ "version": "==3.6.6"
+ },
+ "urllib3": {
+ "hashes": [
+ "sha256:b246607a25ac80bedac05c6f282e3cdaf3afb65420fd024ac94435cabe6e18d1",
+ "sha256:dbe59173209418ae49d485b87d1681aefa36252ee85884c31346debd19463232"
+ ],
+ "index": "pypi",
+ "version": "==1.25.3"
+ },
+ "utm": {
+ "hashes": [
+ "sha256:a6608a67df84418fd959a79b228b90ab55b2ae877827f9c210947104c5a75d0e"
+ ],
+ "index": "pypi",
+ "version": "==0.4.2"
+ },
+ "uwsgi": {
+ "hashes": [
+ "sha256:4972ac538800fb2d421027f49b4a1869b66048839507ccf0aa2fda792d99f583"
+ ],
+ "index": "pypi",
+ "version": "==2.0.18"
+ },
+ "v4l2": {
+ "hashes": [
+ "sha256:0d8f31f9d554ded4d0b50a31a7be5590b861df9e1ba256ee757e1c09175dd4a2"
+ ],
+ "index": "pypi",
+ "version": "==0.2"
+ },
+ "vine": {
+ "hashes": [
+ "sha256:133ee6d7a9016f177ddeaf191c1f58421a1dcc6ee9a42c58b34bed40e1d2cd87",
+ "sha256:ea4947cc56d1fd6f2095c8d543ee25dad966f78692528e68b4fada11ba3f98af"
+ ],
+ "version": "==1.3.0"
+ },
+ "visdom": {
+ "hashes": [
+ "sha256:77edd6811471282740846672a996348e963b5fa4220780f126c71481ad21d5a5"
+ ],
+ "index": "pypi",
+ "version": "==0.1.8.8"
+ },
+ "wcwidth": {
+ "hashes": [
+ "sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e",
+ "sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c"
+ ],
+ "version": "==0.1.7"
+ },
+ "websocket-client": {
+ "hashes": [
+ "sha256:1151d5fb3a62dc129164292e1227655e4bbc5dd5340a5165dfae61128ec50aa9",
+ "sha256:1fd5520878b68b84b5748bb30e592b10d0a91529d5383f74f4964e72b297fd3a"
+ ],
+ "index": "pypi",
+ "version": "==0.56.0"
+ },
+ "werkzeug": {
+ "hashes": [
+ "sha256:865856ebb55c4dcd0630cdd8f3331a1847a819dda7e8c750d3db6f2aa6c0209c",
+ "sha256:a0b915f0815982fb2a09161cb8f31708052d0951c3ba433ccc5e1aa276507ca6"
+ ],
+ "version": "==0.15.4"
+ },
+ "wheel": {
+ "hashes": [
+ "sha256:5e79117472686ac0c4aef5bad5172ea73a1c2d1646b808c35926bd26bdfb0c08",
+ "sha256:62fcfa03d45b5b722539ccbc07b190e4bfff4bb9e3a4d470dd9f6a0981002565"
+ ],
+ "markers": "python_version < '3'",
+ "version": "==0.33.4"
+ },
+ "widgetsnbextension": {
+ "hashes": [
+ "sha256:14b2c65f9940c9a7d3b70adbe713dbd38b5ec69724eebaba034d1036cf3d4740",
+ "sha256:fa618be8435447a017fd1bf2c7ae922d0428056cfc7449f7a8641edf76b48265"
+ ],
+ "version": "==3.4.2"
+ },
+ "wrapt": {
+ "hashes": [
+ "sha256:4aea003270831cceb8a90ff27c4031da6ead7ec1886023b80ce0dfe0adf61533"
+ ],
+ "version": "==1.11.1"
+ }
+ }
+}
diff --git a/README.md b/README.md
index e76b2fcc0..7a4825846 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-[](#)
+[](#)
Welcome to openpilot
======
@@ -77,8 +77,8 @@ Supported Cars
| Honda | Civic Hatchback 2017-19 | Honda Sensing | Yes | Stock | 0mph | 12mph | Bosch |
| Honda | CR-V 2015-16 | Touring | Yes | Yes | 25mph1| 12mph | Nidec |
| Honda | CR-V 2017-19 | Honda Sensing | Yes | Stock | 0mph | 12mph | Bosch |
-| Honda | CR-V Hybrid 2019 | All | Yes | Stock | 0mph | 12mph | Bosch |
-| Honda | Odyssey 2017-19 | Honda Sensing | Yes | Yes | 25mph1| 0mph | Inverted Nidec |
+| Honda | CR-V Hybrid 2017-2019 | Honda Sensing | Yes | Stock | 0mph | 12mph | Bosch |
+| Honda | Odyssey 2018-19 | Honda Sensing | Yes | Yes | 25mph1| 0mph | Inverted Nidec |
| Honda | Passport 2019 | All | Yes | Yes | 25mph1| 12mph | Inverted Nidec |
| Honda | Pilot 2016-18 | Honda Sensing | Yes | Yes | 25mph1| 12mph | Nidec |
| Honda | Pilot 2019 | All | Yes | Yes | 25mph1| 12mph | Inverted Nidec |
@@ -91,13 +91,15 @@ Supported Cars
| Kia | Optima 2019 | SCC + LKAS | Yes | Stock | 0mph | 0mph | Custom6|
| Kia | Sorento 2018 | All | Yes | Stock | 0mph | 0mph | Custom6|
| Kia | Stinger 2018 | SCC + LKAS | Yes | Stock | 0mph | 0mph | Custom6|
+| Lexus | ES Hybrid 2019 | All | Yes | Yes | 0mph | 0mph | Toyota |
| Lexus | RX Hybrid 2016-19 | All | Yes | Yes2| 0mph | 0mph | Toyota |
| Subaru | Crosstrek 2018 | EyeSight | Yes | Stock | 0mph | 0mph | Custom4|
| Subaru | Impreza 2019 | EyeSight | Yes | Stock | 0mph | 0mph | Custom4|
| Toyota | Avalon 2016 | TSS-P | Yes | Yes2| 20mph1| 0mph | Toyota |
| Toyota | Camry 2018 | All | Yes | Stock | 0mph5 | 0mph | Toyota |
| Toyota | C-HR 2017-18 | All | Yes | Stock | 0mph | 0mph | Toyota |
-| Toyota | Corolla 2017-18 | All | Yes | Yes2| 20mph1| 0mph | Toyota |
+| Toyota | Corolla 2017-19 | All | Yes | Yes2| 20mph1| 0mph | Toyota |
+| Toyota | Corolla 2020 | All | Yes | Yes | 0mph | 0mph | Toyota |
| Toyota | Corolla Hatchback 2019 | All | Yes | Yes | 0mph | 0mph | Toyota |
| Toyota | Highlander 2017-18 | All | Yes | Yes2| 0mph | 0mph | Toyota |
| Toyota | Highlander Hybrid 2018 | All | Yes | Yes2| 0mph | 0mph | Toyota |
diff --git a/RELEASES.md b/RELEASES.md
index 50e71874b..f73b8daf8 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,16 @@
+Version 0.6 (2019-07-01)
+========================
+ * New model, with double the pixels and ten times the temporal context!
+ * Car should not take exits when in the right lane
+ * openpilot uses only ~65% of the CPU (down from 75%)
+ * Routes visible in connect/explorer after only 0.2% is uploaded (qlogs)
+ * loggerd and sensord are open source, every line of openpilot is now open
+ * Panda safety code is MISRA compliant and ships with a signed version on release2
+ * New NEOS is 500MB smaller and has a reproducible usr/pipenv
+ * Lexus ES Hybrid support thanks to wocsor!
+ * Improve tuning for supported Toyota with TSS2
+ * Various other stability improvements
+
Version 0.5.13 (2019-05-31)
==========================
* Reduce panda power consumption by 70%, down to 80mW, when car is off (not for GM)
diff --git a/cereal/.gitignore b/cereal/.gitignore
index 57b5883f3..3f6de09fb 100644
--- a/cereal/.gitignore
+++ b/cereal/.gitignore
@@ -1,3 +1,6 @@
gen
node_modules
package-lock.json
+*.pyc
+__pycache__
+
diff --git a/cereal/car.capnp b/cereal/car.capnp
index b33ab97c8..f30b20f97 100644
--- a/cereal/car.capnp
+++ b/cereal/car.capnp
@@ -22,7 +22,7 @@ struct CarEvent @0x9b1657f34caf3ad3 {
enum EventName @0xbaa8c5d505f727de {
# TODO: copy from error list
- commIssue @0;
+ canError @0;
steerUnavailable @1;
brakeUnavailable @2;
gasUnavailable @3;
@@ -37,7 +37,7 @@ struct CarEvent @0x9b1657f34caf3ad3 {
buttonEnable @12;
pedalPressed @13;
cruiseDisabled @14;
- radarCommIssue @15;
+ radarCanError @15;
dataNeeded @16;
speedTooLow @17;
outOfSpace @18;
@@ -49,7 +49,7 @@ struct CarEvent @0x9b1657f34caf3ad3 {
pcmDisable @24;
noTarget @25;
radarFault @26;
- modelCommIssue @27;
+ modelCommIssueDEPRECATED @27;
brakeHold @28;
parkBrake @29;
manualRestart @30;
@@ -75,6 +75,7 @@ struct CarEvent @0x9b1657f34caf3ad3 {
vehicleModelInvalid @50;
controlsFailed @51;
sensorDataInvalid @52;
+ commIssue @53;
}
}
@@ -123,6 +124,7 @@ struct CarState {
# lock info
doorOpen @24 :Bool;
seatbeltUnlatched @25 :Bool;
+ canValid @26 :Bool;
# which packets this state came from
canMonoTimes @12: List(UInt64);
@@ -184,7 +186,7 @@ struct RadarData @0x888ad6581cf0aacb {
canMonoTimes @2 :List(UInt64);
enum Error {
- commIssue @0;
+ canError @0;
fault @1;
wrongConfig @2;
}
@@ -293,7 +295,7 @@ struct CarParams {
minEnableSpeed @7 :Float32;
minSteerSpeed @8 :Float32;
- safetyModel @9 :Int16;
+ safetyModel @9 :SafetyModel;
safetyParam @10 :Int16;
steerMaxBP @11 :List(Float32);
@@ -362,7 +364,7 @@ struct CarParams {
}
- enum SafetyModels {
+ enum SafetyModel {
# does NOT match board setting
noOutput @0;
honda @1;
diff --git a/cereal/generate_javascript.sh b/cereal/generate_javascript.sh
new file mode 100755
index 000000000..d6525a64d
--- /dev/null
+++ b/cereal/generate_javascript.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+rm -r gen/ts
+rm -r gen/js
+
+mkdir gen/ts
+mkdir gen/js
+
+echo "Installing needed npm modules"
+npm i capnpc-ts capnp-ts
+
+capnpc -o node_modules/.bin/capnpc-ts:gen/ts log.capnp car.capnp
+capnpc -o node_modules/.bin/capnpc-ts:gen/ts car.capnp
+
+cat log.capnp | egrep '\([a-zA-Z]*\.[^\s]+\.[^s]+\)' | sed 's/^.*([a-zA-Z]*\.\([a-zA-Z.]*\)).*/\1/' | while read line
+do
+ TOKEN=`echo $line | sed 's/\./_/g'`
+ ROOT=`echo $line | sed 's/\..*$//g'`
+ cat gen/ts/log.capnp.ts | grep '^import.*'${TOKEN}
+ if [[ "$?" == "1" ]]
+ then
+ sed -i 's/^\(import {.*\)'${ROOT}'\(,*\) \(.*\)$/\1'${ROOT}', '${TOKEN}'\2 \3/' ./gen/ts/log.capnp.ts
+ fi
+done
+
+tsc ./gen/ts/* --lib es2015 --outDir ./gen/js
diff --git a/cereal/install_capnp.sh b/cereal/install_capnp.sh
new file mode 100755
index 000000000..b83e1ffda
--- /dev/null
+++ b/cereal/install_capnp.sh
@@ -0,0 +1,39 @@
+set -e
+echo "Installing capnp"
+
+cd /tmp
+VERSION=0.6.1
+wget https://capnproto.org/capnproto-c++-${VERSION}.tar.gz
+tar xvf capnproto-c++-${VERSION}.tar.gz
+cd capnproto-c++-${VERSION}
+CXXFLAGS="-fPIC" ./configure
+
+make -j4
+
+# manually build binaries statically
+g++ -std=gnu++11 -I./src -I./src -DKJ_HEADER_WARNINGS -DCAPNP_HEADER_WARNINGS -DCAPNP_INCLUDE_DIR=\"/usr/local/include\" -pthread -O2 -DNDEBUG -pthread -pthread -o .libs/capnp src/capnp/compiler/module-loader.o src/capnp/compiler/capnp.o ./.libs/libcapnpc.a ./.libs/libcapnp.a ./.libs/libkj.a -lpthread -pthread
+
+g++ -std=gnu++11 -I./src -I./src -DKJ_HEADER_WARNINGS -DCAPNP_HEADER_WARNINGS -DCAPNP_INCLUDE_DIR=\"/usr/local/include\" -pthread -O2 -DNDEBUG -pthread -pthread -o .libs/capnpc-c++ src/capnp/compiler/capnpc-c++.o ./.libs/libcapnp.a ./.libs/libkj.a -lpthread -pthread
+
+g++ -std=gnu++11 -I./src -I./src -DKJ_HEADER_WARNINGS -DCAPNP_HEADER_WARNINGS -DCAPNP_INCLUDE_DIR=\"/usr/local/include\" -pthread -O2 -DNDEBUG -pthread -pthread -o .libs/capnpc-capnp src/capnp/compiler/capnpc-capnp.o ./.libs/libcapnp.a ./.libs/libkj.a -lpthread -pthread
+
+cp .libs/capnp /usr/local/bin/
+ln -s /usr/local/bin/capnp /usr/local/bin/capnpc
+cp .libs/capnpc-c++ /usr/local/bin/
+cp .libs/capnpc-capnp /usr/local/bin/
+cp .libs/*.a /usr/local/lib
+
+cd /tmp
+echo "Installing c-capnp"
+git clone https://github.com/commaai/c-capnproto.git
+cd c-capnproto
+git submodule update --init --recursive
+autoreconf -f -i -s
+CXXFLAGS="-fPIC" ./configure
+make -j4
+
+# manually build binaries statically
+gcc -fPIC -o .libs/capnpc-c compiler/capnpc-c.o compiler/schema.capnp.o compiler/str.o ./.libs/libcapnp_c.a
+
+cp .libs/capnpc-c /usr/local/bin/
+cp .libs/*.a /usr/local/lib
diff --git a/cereal/log.capnp b/cereal/log.capnp
index 7276e20b5..adf76c488 100644
--- a/cereal/log.capnp
+++ b/cereal/log.capnp
@@ -150,6 +150,12 @@ struct FrameData {
}
}
+struct Thumbnail {
+ frameId @0 :UInt32;
+ timestampEof @1 :UInt64;
+ thumbnail @2 :Data;
+}
+
struct GPSNMEAData {
timestamp @0 :Int64;
localWallTime @1 :UInt64;
@@ -508,12 +514,15 @@ struct ModelData {
prob @1 :Float32;
std @2 :Float32;
stds @3 :List(Float32);
+ poly @4 :List(Float32);
}
struct LeadData {
dist @0 :Float32;
prob @1 :Float32;
std @2 :Float32;
+ relVel @3 :Float32;
+ relVelStd @4 :Float32;
}
struct ModelSettings {
@@ -576,6 +585,8 @@ struct LogRotate {
struct Plan {
mdMonoTime @9 :UInt64;
radarStateMonoTime @10 :UInt64;
+ commIssue @31 :Bool;
+
eventsDEPRECATED @13 :List(Car.CarEvent);
# lateral, 3rd order polynomial
@@ -614,7 +625,7 @@ struct Plan {
decelForTurn @22 :Bool;
mapValid @25 :Bool;
radarValid @28 :Bool;
- radarCommIssue @30 :Bool;
+ radarCanError @30 :Bool;
processingDelay @29 :Float32;
@@ -645,11 +656,12 @@ struct PathPlan {
angleSteers @8 :Float32; # deg
rateSteers @13 :Float32; # deg/s
- valid @9 :Bool;
+ mpcSolutionValid @9 :Bool;
paramsValid @10 :Bool;
- modelValid @12 :Bool;
+ modelValidDEPRECATED @12 :Bool;
angleOffset @11 :Float32;
sensorValid @14 :Bool;
+ commIssue @15 :Bool;
}
struct LiveLocationData {
@@ -1646,6 +1658,7 @@ struct LiveParametersData {
stiffnessFactor @4 :Float32;
steerRatio @5 :Float32;
sensorValid @6 :Bool;
+ yawRate @7 :Float32;
}
struct LiveMapData {
@@ -1685,6 +1698,7 @@ struct KalmanOdometry {
struct Event {
# in nanoseconds?
logMonoTime @0 :UInt64;
+ valid @67 :Bool = true;
union {
initData @1 :InitData;
@@ -1752,5 +1766,8 @@ struct Event {
cameraOdometry @63 :CameraOdometry;
pathPlan @64 :PathPlan;
kalmanOdometry @65 :KalmanOdometry;
+ thumbnail @66: Thumbnail;
+ carEvents @68: List(Car.CarEvent);
+ carParams @69: Car.CarParams;
}
}
diff --git a/cereal/maptile.capnp b/cereal/maptile.capnp
new file mode 100644
index 000000000..336901392
--- /dev/null
+++ b/cereal/maptile.capnp
@@ -0,0 +1,53 @@
+using Cxx = import "./include/c++.capnp";
+$Cxx.namespace("cereal");
+
+using Java = import "./include/java.capnp";
+$Java.package("ai.comma.openpilot.cereal");
+$Java.outerClassname("Map");
+
+@0xa086df597ef5d7a0;
+
+# Geometry
+struct Point {
+ x @0: Float64;
+ y @1: Float64;
+ z @2: Float64;
+}
+
+struct PolyLine {
+ points @0: List(Point);
+}
+
+# Map features
+struct Lane {
+ id @0 :Text;
+
+ leftBoundary @1 :LaneBoundary;
+ rightBoundary @2 :LaneBoundary;
+
+ leftAdjacentId @3 :Text;
+ rightAdjacentId @4 :Text;
+
+ inboundIds @5 :List(Text);
+ outboundIds @6 :List(Text);
+
+ struct LaneBoundary {
+ polyLine @0 :PolyLine;
+ startHeading @1 :Float32; # WRT north
+ }
+}
+
+# Map tiles
+struct TileSummary {
+ version @0 :Text;
+ updatedAt @1 :UInt64; # Millis since epoch
+
+ level @2 :UInt8;
+ x @3 :UInt16;
+ y @4 :UInt16;
+}
+
+struct MapTile {
+ summary @0 :TileSummary;
+ lanes @1 :List(Lane);
+}
diff --git a/common/fingerprints.py b/common/fingerprints.py
index 5a29c9555..ddc3bceb6 100644
--- a/common/fingerprints.py
+++ b/common/fingerprints.py
@@ -4,7 +4,7 @@ from common.basedir import BASEDIR
def get_fingerprint_list():
# read all the folders in selfdrive/car and return a dict where:
# - keys are all the car models for which we have a fingerprint
- # - values are lists dicts of messages that constitute the unique
+ # - values are lists dicts of messages that constitute the unique
# CAN fingerprint of each car model and all its variants
fingerprints = {}
for car_folder in [x[0] for x in os.walk(BASEDIR + '/selfdrive/car')]:
diff --git a/common/kalman/Makefile b/common/kalman/Makefile
index cb8f09265..88b032af1 100644
--- a/common/kalman/Makefile
+++ b/common/kalman/Makefile
@@ -1,7 +1,7 @@
all: simple_kalman_impl.so
simple_kalman_impl.so: simple_kalman_impl.pyx simple_kalman_impl.pxd simple_kalman_setup.py
- python simple_kalman_setup.py build_ext --inplace
+ python2 simple_kalman_setup.py build_ext --inplace
rm -rf build
rm simple_kalman_impl.c
diff --git a/common/params.py b/common/params.py
index cde03156f..c374d5233 100755
--- a/common/params.py
+++ b/common/params.py
@@ -65,6 +65,7 @@ keys = {
"IsGeofenceEnabled": [TxType.PERSISTENT],
"IsMetric": [TxType.PERSISTENT],
"IsUpdateAvailable": [TxType.PERSISTENT],
+ "IsUploadRawEnabled": [TxType.PERSISTENT],
"IsUploadVideoOverCellularEnabled": [TxType.PERSISTENT],
"LimitSetSpeed": [TxType.PERSISTENT],
"LiveParameters": [TxType.PERSISTENT],
diff --git a/common/realtime.py b/common/realtime.py
index 21204db0d..8bcd06966 100644
--- a/common/realtime.py
+++ b/common/realtime.py
@@ -15,6 +15,13 @@ assert monotonic_time
assert sec_since_boot
+# time step for each process
+DT_CTRL = 0.01 # controlsd
+DT_PLAN = 0.05 # mpc
+DT_MDL = 0.05 # model
+DT_DMON = 0.1 # driver monitoring
+
+
ffi = FFI()
ffi.cdef("long syscall(long number, ...);")
libc = ffi.dlopen(None)
diff --git a/common/transformations/camera.py b/common/transformations/camera.py
index 1ac9bc5b2..2e04c5ac2 100644
--- a/common/transformations/camera.py
+++ b/common/transformations/camera.py
@@ -1,6 +1,5 @@
import numpy as np
import common.transformations.orientation as orient
-import cv2
import math
FULL_FRAME_SIZE = (1164, 874)
@@ -126,6 +125,8 @@ def img_from_device(pt_device):
#TODO please use generic img transform below
def rotate_img(img, eulers, crop=None, intrinsics=eon_intrinsics):
+ import cv2
+
size = img.shape[:2]
rot = orient.rot_from_euler(eulers)
quadrangle = np.array([[0, 0],
@@ -162,6 +163,8 @@ def transform_img(base_img,
output_size=None,
pretransform=None,
top_hacks=True):
+ import cv2
+
size = base_img.shape[:2]
if not output_size:
output_size = size[::-1]
@@ -204,10 +207,10 @@ def transform_img(base_img,
def yuv_crop(frame, output_size, center=None):
# output_size in camera coordinates so u,v
# center in array coordinates so row, column
+ import cv2
rgb = cv2.cvtColor(frame, cv2.COLOR_YUV2RGB_I420)
if not center:
center = (rgb.shape[0]/2, rgb.shape[1]/2)
rgb_crop = rgb[center[0] - output_size[1]/2: center[0] + output_size[1]/2,
center[1] - output_size[0]/2: center[1] + output_size[0]/2]
return cv2.cvtColor(rgb_crop, cv2.COLOR_RGB2YUV_I420)
-
diff --git a/installer/updater/Makefile b/installer/updater/Makefile
new file mode 100644
index 000000000..d9444e6c5
--- /dev/null
+++ b/installer/updater/Makefile
@@ -0,0 +1,88 @@
+CC = clang
+CXX = clang++
+
+PHONELIBS = ../../phonelibs
+
+WARN_FLAGS = -Werror=implicit-function-declaration \
+ -Werror=incompatible-pointer-types \
+ -Werror=int-conversion \
+ -Werror=return-type \
+ -Werror=format-extra-args
+
+CFLAGS = -std=gnu11 -g -fPIC -O2 $(WARN_FLAGS)
+CXXFLAGS = -std=c++11 -g -fPIC -O2 $(WARN_FLAGS)
+
+CURL_FLAGS = -I$(PHONELIBS)/curl/include
+CURL_LIBS = $(PHONELIBS)/curl/lib/libcurl.a \
+ $(PHONELIBS)/zlib/lib/libz.a
+
+BORINGSSL_FLAGS = -I$(PHONELIBS)/boringssl/include
+BORINGSSL_LIBS = $(PHONELIBS)/boringssl/lib/libssl_static.a \
+ $(PHONELIBS)/boringssl/lib/libcrypto_static.a \
+
+NANOVG_FLAGS = -I$(PHONELIBS)/nanovg
+
+JSON11_FLAGS = -I$(PHONELIBS)/json11
+
+OPENGL_LIBS = -lGLESv3
+
+FRAMEBUFFER_LIBS = -lutils -lgui -lEGL
+
+.PHONY: all
+all: updater
+
+OBJS = courbd.ttf.o \
+ ../../selfdrive/common/touch.o \
+ ../../selfdrive/common/framebuffer.o \
+ $(PHONELIBS)/json11/json11.o \
+ $(PHONELIBS)/nanovg/nanovg.o
+
+DEPS := $(OBJS:.o=.d)
+
+updater: updater.o $(OBJS)
+ @echo "[ LINK ] $@"
+ $(CXX) $(CPPFLAGS) -fPIC -o 'updater' $^ \
+ $(FRAMEBUFFER_LIBS) \
+ $(CURL_LIBS) \
+ $(BORINGSSL_LIBS) \
+ -L/system/vendor/lib64 \
+ $(OPENGL_LIBS) \
+ -lcutils -lm -llog
+ strip updater
+
+courbd.ttf.o: ../../selfdrive/assets/courbd.ttf
+ @echo "[ bin2o ] $@"
+ cd '$(dir $<)' && ld -r -b binary '$(notdir $<)' -o '$(abspath $@)'
+
+%.o: %.c
+ mkdir -p $(@D)
+ @echo "[ CC ] $@"
+ $(CC) $(CPPFLAGS) $(CFLAGS) \
+ -I../.. \
+ -I$(PHONELIBS)/android_frameworks_native/include \
+ -I$(PHONELIBS)/android_system_core/include \
+ -I$(PHONELIBS)/android_hardware_libhardware/include \
+ $(NANOVG_FLAGS) \
+ -c -o '$@' '$<'
+
+%.o: %.cc
+ mkdir -p $(@D)
+ @echo "[ CXX ] $@"
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) \
+ -I../../selfdrive \
+ -I../../ \
+ -I$(PHONELIBS)/android_frameworks_native/include \
+ -I$(PHONELIBS)/android_system_core/include \
+ -I$(PHONELIBS)/android_hardware_libhardware/include \
+ $(NANOVG_FLAGS) \
+ $(JSON11_FLAGS) \
+ $(CURL_FLAGS) \
+ $(BORINGSSL_FLAGS) \
+ -c -o '$@' '$<'
+
+
+.PHONY: clean
+clean:
+ rm -f $(OBJS) $(DEPS)
+
+-include $(DEPS)
diff --git a/installer/updater/update.json b/installer/updater/update.json
new file mode 100644
index 000000000..827a44b10
--- /dev/null
+++ b/installer/updater/update.json
@@ -0,0 +1,7 @@
+{
+ "ota_url": "https://commadist.azureedge.net/neosupdate/ota-signed-c992abb59cbaf6588f51055db52db619061107851773fc8480acb8bb5d77a28f.zip",
+ "ota_hash": "c992abb59cbaf6588f51055db52db619061107851773fc8480acb8bb5d77a28f",
+ "recovery_url": "https://commadist.azureedge.net/neosupdate/recovery-af099a84cfd7b91266090779238ac358278948dcde2dcfa0fbca6e8397366f0a.img",
+ "recovery_len": 15136044,
+ "recovery_hash": "af099a84cfd7b91266090779238ac358278948dcde2dcfa0fbca6e8397366f0a"
+}
diff --git a/installer/updater/updater b/installer/updater/updater
index 84a8614d5..857a78e6f 100755
Binary files a/installer/updater/updater and b/installer/updater/updater differ
diff --git a/installer/updater/updater.cc b/installer/updater/updater.cc
new file mode 100644
index 000000000..58fab3241
--- /dev/null
+++ b/installer/updater/updater.cc
@@ -0,0 +1,675 @@
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+
+#include "nanovg.h"
+#define NANOVG_GLES3_IMPLEMENTATION
+#include "nanovg_gl.h"
+#include "nanovg_gl_utils.h"
+
+#include "json11.hpp"
+
+#include "common/framebuffer.h"
+#include "common/touch.h"
+#include "common/utilpp.h"
+
+#define USER_AGENT "NEOSUpdater-0.2"
+
+#define MANIFEST_URL_EON_STAGING "https://github.com/commaai/eon-neos/raw/master/update.staging.json"
+#define MANIFEST_URL_EON_LOCAL "http://192.168.5.1:8000/neosupdate/update.local.json"
+#define MANIFEST_URL_EON "https://github.com/commaai/eon-neos/raw/master/update.json"
+const char *manifest_url = MANIFEST_URL_EON;
+
+#define RECOVERY_DEV "/dev/block/bootdevice/by-name/recovery"
+#define RECOVERY_COMMAND "/cache/recovery/command"
+
+#define UPDATE_DIR "/data/neoupdate"
+
+extern const uint8_t bin_courbd[] asm("_binary_courbd_ttf_start");
+extern const uint8_t bin_courbd_end[] asm("_binary_courbd_ttf_end");
+
+namespace {
+
+std::string sha256_file(std::string fn, size_t limit=0) {
+ SHA256_CTX ctx;
+ SHA256_Init(&ctx);
+
+ FILE *file = fopen(fn.c_str(), "rb");
+ if (!file) return "";
+
+ const size_t buf_size = 8192;
+ std::unique_ptr buffer( new char[ buf_size ] );
+
+ bool read_limit = (limit != 0);
+ while (true) {
+ size_t read_size = buf_size;
+ if (read_limit) read_size = std::min(read_size, limit);
+ size_t bytes_read = fread(buffer.get(), 1, read_size, file);
+ if (!bytes_read) break;
+
+ SHA256_Update(&ctx, buffer.get(), bytes_read);
+
+ if (read_limit) {
+ limit -= bytes_read;
+ if (limit == 0) break;
+ }
+ }
+
+ uint8_t hash[SHA256_DIGEST_LENGTH];
+ SHA256_Final(hash, &ctx);
+
+ fclose(file);
+
+ return util::tohex(hash, sizeof(hash));
+}
+
+size_t download_string_write(void *ptr, size_t size, size_t nmeb, void *up) {
+ size_t sz = size * nmeb;
+ ((std::string*)up)->append((char*)ptr, sz);
+ return sz;
+}
+
+std::string download_string(CURL *curl, std::string url) {
+ std::string os;
+
+ curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
+ curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
+ curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
+ curl_easy_setopt(curl, CURLOPT_USERAGENT, USER_AGENT);
+ curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt(curl, CURLOPT_RESUME_FROM, 0);
+
+ curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
+
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, download_string_write);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &os);
+ CURLcode res = curl_easy_perform(curl);
+ if (res != CURLE_OK) {
+ return "";
+ }
+
+ return os;
+}
+
+size_t download_file_write(void *ptr, size_t size, size_t nmeb, void *up) {
+ return fwrite(ptr, size, nmeb, (FILE*)up);
+}
+
+bool check_battery() {
+ std::string bat_cap_s = util::read_file("/sys/class/power_supply/battery/capacity");
+ int bat_cap = atoi(bat_cap_s.c_str());
+ std::string current_now_s = util::read_file("/sys/class/power_supply/battery/current_now");
+ int current_now = atoi(current_now_s.c_str());
+ return bat_cap > 35 || (current_now < 0 && bat_cap > 10);
+}
+
+bool check_space() {
+ struct statvfs stat;
+ if (statvfs("/data/", &stat) != 0) {
+ return false;
+ }
+ size_t space = stat.f_bsize * stat.f_bavail;
+ return space > 2000000000ULL; // 2GB
+}
+
+static void start_settings_activity(const char* name) {
+ char launch_cmd[1024];
+ snprintf(launch_cmd, sizeof(launch_cmd),
+ "am start -W --ez :settings:show_fragment_as_subsetting true -n 'com.android.settings/.%s'", name);
+ system(launch_cmd);
+}
+
+struct Updater {
+ bool do_exit = false;
+
+ TouchState touch;
+
+ int fb_w, fb_h;
+ EGLDisplay display;
+ EGLSurface surface;
+
+ FramebufferState *fb = NULL;
+ NVGcontext *vg = NULL;
+ int font;
+
+ std::thread update_thread_handle;
+
+ std::mutex lock;
+
+ // i hate state machines give me coroutines already
+ enum UpdateState {
+ CONFIRMATION,
+ RUNNING,
+ ERROR,
+ };
+ UpdateState state;
+
+ std::string progress_text;
+ float progress_frac;
+
+ std::string error_text;
+
+ // button
+ int b_x, b_w, b_y, b_h;
+ int balt_x;
+
+ CURL *curl = NULL;
+
+ Updater() {
+ touch_init(&touch);
+
+ fb = framebuffer_init("updater", 0x00001000, false,
+ &display, &surface, &fb_w, &fb_h);
+ assert(fb);
+
+ vg = nvgCreateGLES3(NVG_ANTIALIAS | NVG_STENCIL_STROKES | NVG_DEBUG);
+ assert(vg);
+ font = nvgCreateFontMem(vg, "courbd", (unsigned char*)bin_courbd, (bin_courbd_end - bin_courbd), 0);
+ assert(font >= 0);
+
+ b_w = 600;
+ balt_x = 200;
+ b_x = fb_w-b_w-200;
+ b_y = 700;
+ b_h = 250;
+
+ state = CONFIRMATION;
+
+ }
+
+ int download_file_xferinfo(curl_off_t dltotal, curl_off_t dlno,
+ curl_off_t ultotal, curl_off_t ulnow) {
+ {
+ std::lock_guard guard(lock);
+ if (dltotal != 0) {
+ progress_frac = (float) dlno / dltotal;
+ }
+ }
+ // printf("info: %ld %ld %f\n", dltotal, dlno, progress_frac);
+ return 0;
+ }
+
+ bool download_file(std::string url, std::string out_fn) {
+ FILE *of = fopen(out_fn.c_str(), "ab");
+ assert(of);
+
+ CURLcode res;
+ long last_resume_from = 0;
+
+ fseek(of, 0, SEEK_END);
+
+ int tries = 4;
+
+ bool ret = false;
+
+ while (true) {
+ long resume_from = ftell(of);
+
+ curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
+ curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
+ curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
+ curl_easy_setopt(curl, CURLOPT_USERAGENT, USER_AGENT);
+ curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
+ curl_easy_setopt(curl, CURLOPT_RESUME_FROM, resume_from);
+
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, download_file_write);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, of);
+
+ curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
+
+ curl_easy_setopt(curl, CURLOPT_XFERINFODATA, this);
+ curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, &Updater::download_file_xferinfo);
+
+ CURLcode res = curl_easy_perform(curl);
+
+ long response_code = 0;
+ curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
+
+ // double content_length = 0.0;
+ // curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &content_length);
+
+ printf("download %s res %d, code %ld, resume from %ld\n", url.c_str(), res, response_code, resume_from);
+ if (res == CURLE_OK) {
+ ret = true;
+ break;
+ } else if (res == CURLE_HTTP_RETURNED_ERROR && response_code == 416) {
+ // failed because the file is already complete?
+ ret = true;
+ break;
+ } else if (resume_from == last_resume_from) {
+ // failed and dind't make make forward progress. only retry a couple times
+ tries--;
+ if (tries <= 0) {
+ break;
+ }
+ }
+ last_resume_from = resume_from;
+ }
+ // printf("res %d\n", res);
+
+ // printf("- %ld %f\n", response_code, content_length);
+
+ fclose(of);
+
+ return ret;
+ }
+
+ void set_progress(std::string text) {
+ std::lock_guard guard(lock);
+ progress_text = text;
+ }
+
+ void set_error(std::string text) {
+ std::lock_guard guard(lock);
+ error_text = text;
+ state = ERROR;
+ }
+
+ std::string stage_download(std::string url, std::string hash, std::string name) {
+ std::string out_fn = UPDATE_DIR "/" + util::base_name(url);
+
+ set_progress("downloading " + name + "...");
+ bool r = download_file(url, out_fn);
+ if (!r) {
+ set_error("failed to download " + name);
+ return "";
+ }
+
+ set_progress("verifying " + name + "...");
+ std::string fn_hash = sha256_file(out_fn);
+ printf("got %s hash: %s\n", name.c_str(), hash.c_str());
+ if (fn_hash != hash) {
+ set_error(name + " was corrupt");
+ unlink(out_fn.c_str());
+ return "";
+ }
+
+ return out_fn;
+ }
+
+ void run_stages() {
+ curl = curl_easy_init();
+ assert(curl);
+
+ if (!check_battery()) {
+ set_error("Please plug power in to your EON and wait for charge");
+ return;
+ }
+
+ if (!check_space()) {
+ set_error("2GB of free space required to update");
+ return;
+ }
+
+ mkdir(UPDATE_DIR, 0777);
+
+ const int EON = (access("/EON", F_OK) != -1);
+
+ set_progress("finding latest version...");
+ std::string manifest_s;
+ if (EON) {
+ manifest_s = download_string(curl, manifest_url);
+ } else {
+ // don't update NEO
+ exit(0);
+ }
+
+ printf("manifest: %s\n", manifest_s.c_str());
+
+ std::string err;
+ auto manifest = json11::Json::parse(manifest_s, err);
+ if (manifest.is_null() || !err.empty()) {
+ set_error("failed to load update manifest");
+ return;
+ }
+
+ std::string ota_url = manifest["ota_url"].string_value();
+ std::string ota_hash = manifest["ota_hash"].string_value();
+
+ std::string recovery_url = manifest["recovery_url"].string_value();
+ std::string recovery_hash = manifest["recovery_hash"].string_value();
+ int recovery_len = manifest["recovery_len"].int_value();
+
+ // std::string installer_url = manifest["installer_url"].string_value();
+ // std::string installer_hash = manifest["installer_hash"].string_value();
+
+ if (ota_url.empty() || ota_hash.empty()) {
+ set_error("invalid update manifest");
+ return;
+ }
+
+ // std::string installer_fn = stage_download(installer_url, installer_hash, "installer");
+ // if (installer_fn.empty()) {
+ // //error'd
+ // return;
+ // }
+
+ std::string recovery_fn;
+ if (recovery_url.empty() || recovery_hash.empty() || recovery_len == 0) {
+ set_progress("skipping recovery flash...");
+ } else {
+ // only download the recovery if it differs from what's flashed
+ set_progress("checking recovery...");
+ std::string existing_recovery_hash = sha256_file(RECOVERY_DEV, recovery_len);
+ printf("existing recovery hash: %s\n", existing_recovery_hash.c_str());
+
+ if (existing_recovery_hash != recovery_hash) {
+ recovery_fn = stage_download(recovery_url, recovery_hash, "recovery");
+ if (recovery_fn.empty()) {
+ // error'd
+ return;
+ }
+ }
+ }
+
+ std::string ota_fn = stage_download(ota_url, ota_hash, "update");
+ if (ota_fn.empty()) {
+ //error'd
+ return;
+ }
+
+ if (!check_battery()) {
+ set_error("must have at least 35% battery to update");
+ return;
+ }
+
+ if (!recovery_fn.empty()) {
+ // flash recovery
+ set_progress("flashing recovery...");
+
+ FILE *flash_file = fopen(recovery_fn.c_str(), "rb");
+ if (!flash_file) {
+ set_error("failed to flash recovery");
+ return;
+ }
+
+ FILE *recovery_dev = fopen(RECOVERY_DEV, "w+b");
+ if (!recovery_dev) {
+ fclose(flash_file);
+ set_error("failed to flash recovery");
+ return;
+ }
+
+ const size_t buf_size = 4096;
+ std::unique_ptr buffer( new char[ buf_size ] );
+
+ while (true) {
+ size_t bytes_read = fread(buffer.get(), 1, buf_size, flash_file);
+ if (!bytes_read) break;
+
+ size_t bytes_written = fwrite(buffer.get(), 1, bytes_read, recovery_dev);
+ if (bytes_read != bytes_written) {
+ fclose(recovery_dev);
+ fclose(flash_file);
+ set_error("failed to flash recovery: write failed");
+ return;
+ }
+ }
+
+ fclose(recovery_dev);
+ fclose(flash_file);
+
+ set_progress("verifying flash...");
+ std::string new_recovery_hash = sha256_file(RECOVERY_DEV, recovery_len);
+ printf("new recovery hash: %s\n", new_recovery_hash.c_str());
+
+ if (new_recovery_hash != recovery_hash) {
+ set_error("recovery flash corrupted");
+ return;
+ }
+
+ }
+
+ // write arguments to recovery
+ FILE *cmd_file = fopen(RECOVERY_COMMAND, "wb");
+ if (!cmd_file) {
+ set_error("failed to reboot into recovery");
+ return;
+ }
+ fprintf(cmd_file, "--update_package=%s\n", ota_fn.c_str());
+ fclose(cmd_file);
+
+ set_progress("rebooting");
+
+ // remove the continue.sh so we come back into the setup.
+ // maybe we should go directly into the installer, but what if we don't come back with internet? :/
+ //unlink("/data/data/com.termux/files/continue.sh");
+
+ // TODO: this should be generic between android versions
+ // IPowerManager.reboot(confirm=false, reason="recovery", wait=true)
+ system("service call power 16 i32 0 s16 recovery i32 1");
+ while(1) pause();
+
+ // execl("/system/bin/reboot", "recovery");
+ // set_error("failed to reboot into recovery");
+ }
+
+ void draw_ack_screen(const char *message, const char *button, const char *altbutton) {
+ nvgFontSize(vg, 96.0f);
+ nvgFillColor(vg, nvgRGBA(255,255,255,255));
+ nvgTextAlign(vg, NVG_ALIGN_LEFT | NVG_ALIGN_BASELINE);
+ nvgTextBox(vg, 50, 100, fb_w-100, message, NULL);
+
+ // draw button
+ if (button) {
+ nvgBeginPath(vg);
+ nvgFillColor(vg, nvgRGBA(0, 0, 0, 255));
+ nvgRoundedRect(vg, b_x, b_y, b_w, b_h, 20);
+ nvgFill(vg);
+
+ nvgFillColor(vg, nvgRGBA(255, 255, 255, 255));
+ nvgTextAlign(vg, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE);
+ nvgText(vg, b_x+b_w/2, b_y+b_h/2, button, NULL);
+
+ nvgBeginPath(vg);
+ nvgStrokeColor(vg, nvgRGBA(255, 255, 255, 255));
+ nvgStrokeWidth(vg, 5);
+ nvgRoundedRect(vg, b_x, b_y, b_w, b_h, 20);
+ nvgStroke(vg);
+ }
+
+ // draw button
+ if (altbutton) {
+ nvgBeginPath(vg);
+ nvgFillColor(vg, nvgRGBA(0, 0, 0, 255));
+ nvgRoundedRect(vg, balt_x, b_y, b_w, b_h, 20);
+ nvgFill(vg);
+
+ nvgFillColor(vg, nvgRGBA(255, 255, 255, 255));
+ nvgTextAlign(vg, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE);
+ nvgText(vg, balt_x+b_w/2, b_y+b_h/2, altbutton, NULL);
+
+ nvgBeginPath(vg);
+ nvgStrokeColor(vg, nvgRGBA(255, 255, 255, 255));
+ nvgStrokeWidth(vg, 5);
+ nvgRoundedRect(vg, balt_x, b_y, b_w, b_h, 20);
+ nvgStroke(vg);
+ }
+ }
+
+ void draw_progress_screen() {
+ // draw progress message
+ nvgFontSize(vg, 64.0f);
+ nvgFillColor(vg, nvgRGBA(255,255,255,255));
+ nvgTextAlign(vg, NVG_ALIGN_CENTER | NVG_ALIGN_BASELINE);
+ nvgTextBox(vg, 0, 700, fb_w, progress_text.c_str(), NULL);
+
+ // draw progress bar
+ {
+ int progress_width = 800;
+ int progress_x = fb_w/2-progress_width/2;
+ int progress_y = 768;
+ int progress_height = 15;
+
+ int powerprompt_y = 512;
+ nvgText(vg, fb_w/2, powerprompt_y, "Ensure EON is connected to power", NULL);
+
+ NVGpaint paint = nvgBoxGradient(
+ vg, progress_x + 1, progress_y + 1,
+ progress_width - 2, progress_height, 3, 4, nvgRGB(0, 32, 0), nvgRGB(0, 92, 0));
+ nvgBeginPath(vg);
+ nvgRoundedRect(vg, progress_x, progress_y, progress_width, progress_height, 3);
+ nvgFillPaint(vg, paint);
+ nvgFill(vg);
+
+ float value = std::min(std::max(0.0f, progress_frac), 1.0f);
+ int bar_pos = ((progress_width - 2) * value);
+
+ paint = nvgBoxGradient(
+ vg, progress_x, progress_y,
+ bar_pos+1.5f, progress_height-1, 3, 4,
+ nvgRGB(220, 100, 0), nvgRGB(128, 100, 0));
+
+ nvgBeginPath(vg);
+ nvgRoundedRect(
+ vg, progress_x+1, progress_y+1,
+ bar_pos, progress_height-2, 3);
+ nvgFillPaint(vg, paint);
+ nvgFill(vg);
+ }
+ }
+
+ void ui_draw() {
+ std::lock_guard guard(lock);
+
+ nvgBeginFrame(vg, fb_w, fb_h, 1.0f);
+
+ switch (state) {
+ case CONFIRMATION:
+ draw_ack_screen("An upgrade to NEOS is required.\n\n"
+ "Your device will now be reset and upgraded. You may want to connect to wifi as download is around 1 GB\nData on device shouldn't be lost.",
+ "continue",
+ "wifi");
+ break;
+ case RUNNING:
+ draw_progress_screen();
+ break;
+ case ERROR:
+ draw_ack_screen(("ERROR: " + error_text + "\n\nYou will need to retry").c_str(), NULL, "exit");
+ break;
+ }
+
+ nvgEndFrame(vg);
+ }
+
+ void ui_update() {
+ std::lock_guard guard(lock);
+
+ switch (state) {
+ case ERROR:
+ case CONFIRMATION: {
+ int touch_x = -1, touch_y = -1;
+ int res = touch_poll(&touch, &touch_x, &touch_y, 0);
+ if (res == 1 && !is_settings_active()) {
+ if (touch_x >= b_x && touch_x < b_x+b_w && touch_y >= b_y && touch_y < b_y+b_h) {
+ if (state == CONFIRMATION) {
+ state = RUNNING;
+ update_thread_handle = std::thread(&Updater::run_stages, this);
+ }
+ }
+ if (touch_x >= balt_x && touch_x < balt_x+b_w && touch_y >= b_y && touch_y < b_y+b_h) {
+ if (state == CONFIRMATION) {
+ start_settings_activity("Settings$WifiSettingsActivity");
+ } else if (state == ERROR) {
+ do_exit = 1;
+ }
+ }
+ }
+ }
+ default:
+ break;
+ }
+ }
+
+
+ void go() {
+ while (!do_exit) {
+ ui_update();
+
+ glClearColor(0.19, 0.09, 0.2, 1.0);
+ glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ ui_draw();
+
+ glDisable(GL_BLEND);
+
+ eglSwapBuffers(display, surface);
+ assert(glGetError() == GL_NO_ERROR);
+
+ // no simple way to do 30fps vsync with surfaceflinger...
+ usleep(30000);
+ }
+
+ if (update_thread_handle.joinable()) {
+ update_thread_handle.join();
+ }
+
+ system("service call power 16 i32 0 i32 0 i32 1");
+ }
+
+ bool is_settings_active() {
+ FILE *fp;
+ char sys_output[4096];
+
+ fp = popen("/bin/dumpsys window windows", "r");
+ if (fp == NULL) {
+ return false;
+ }
+
+ bool active = false;
+ while (fgets(sys_output, sizeof(sys_output), fp) != NULL) {
+ if (strstr(sys_output, "mCurrentFocus=null") != NULL) {
+ break;
+ }
+
+ if (strstr(sys_output, "mCurrentFocus=Window") != NULL) {
+ active = true;
+ break;
+ }
+ }
+
+ pclose(fp);
+
+ return active;
+ }
+
+};
+
+}
+int main(int argc, char *argv[]) {
+ if (argc > 1) {
+ if (strcmp(argv[1], "local") == 0) {
+ manifest_url = MANIFEST_URL_EON_LOCAL;
+ } else if (strcmp(argv[1], "staging") == 0) {
+ manifest_url = MANIFEST_URL_EON_STAGING;
+ } else {
+ manifest_url = argv[1];
+ }
+ }
+ printf("updating from %s\n", manifest_url);
+ Updater updater;
+ updater.go();
+
+ return 0;
+}
diff --git a/launch_chffrplus.sh b/launch_chffrplus.sh
index 4b7c4c036..287c72a78 100755
--- a/launch_chffrplus.sh
+++ b/launch_chffrplus.sh
@@ -1,5 +1,11 @@
#!/usr/bin/bash
+export OMP_NUM_THREADS=1
+export MKL_NUM_THREADS=1
+export NUMEXPR_NUM_THREADS=1
+export OPENBLAS_NUM_THREADS=1
+export VECLIB_MAXIMUM_THREADS=1
+
if [ -z "$PASSIVE" ]; then
export PASSIVE="1"
fi
@@ -7,9 +13,16 @@ fi
function launch {
# apply update
if [ "$(git rev-parse HEAD)" != "$(git rev-parse @{u})" ]; then
- git reset --hard @{u} &&
- git clean -xdf &&
- exec "${BASH_SOURCE[0]}"
+ git reset --hard @{u} &&
+ git clean -xdf &&
+
+ # Touch all files on release2 after checkout to prevent rebuild
+ BRANCH=$(git rev-parse --abbrev-ref HEAD)
+ if [[ "$BRANCH" == "release2" ]]; then
+ touch **
+ fi
+
+ exec "${BASH_SOURCE[0]}"
fi
# no cpu rationing for now
diff --git a/models/driving_model.dlc b/models/driving_model.dlc
index a33c1feb0..3cceccf11 100644
Binary files a/models/driving_model.dlc and b/models/driving_model.dlc differ
diff --git a/opendbc/generator/toyota/toyota_camry_hybrid_2018_pt.dbc b/opendbc/generator/toyota/toyota_camry_hybrid_2018_pt.dbc
index efde86ba9..1d41d1e20 100644
--- a/opendbc/generator/toyota/toyota_camry_hybrid_2018_pt.dbc
+++ b/opendbc/generator/toyota/toyota_camry_hybrid_2018_pt.dbc
@@ -16,7 +16,7 @@ BO_ 581 GAS_PEDAL: 8 XXX
SG_ GAS_PEDAL : 23|8@0+ (0.005,0) [0|1] "" XXX
BO_ 608 STEER_TORQUE_SENSOR: 8 XXX
- SG_ STEER_TORQUE_EPS : 47|16@0- (0.66,0) [-20000|20000] "" XXX
+ SG_ STEER_TORQUE_EPS : 47|16@0- (0.73,0) [-20000|20000] "" XXX
SG_ STEER_TORQUE_DRIVER : 15|16@0- (1,0) [-32768|32767] "" XXX
SG_ STEER_OVERRIDE : 0|1@0+ (1,0) [0|1] "" XXX
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
diff --git a/opendbc/generator/toyota/toyota_chr_hybrid_2018_pt.dbc b/opendbc/generator/toyota/toyota_nodsu_hybrid_pt.dbc
similarity index 96%
rename from opendbc/generator/toyota/toyota_chr_hybrid_2018_pt.dbc
rename to opendbc/generator/toyota/toyota_nodsu_hybrid_pt.dbc
index c86fcaaf6..4f6415751 100644
--- a/opendbc/generator/toyota/toyota_chr_hybrid_2018_pt.dbc
+++ b/opendbc/generator/toyota/toyota_nodsu_hybrid_pt.dbc
@@ -20,6 +20,7 @@ BO_ 608 STEER_TORQUE_SENSOR: 8 XXX
SG_ STEER_TORQUE_DRIVER : 15|16@0- (1,0) [-32768|32767] "" XXX
SG_ STEER_OVERRIDE : 0|1@0+ (1,0) [0|1] "" XXX
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
+ SG_ STEER_ANGLE : 31|16@0- (0.056,0) [-500|500] "" XXX
BO_ 610 EPS_STATUS: 8 EPS
SG_ IPAS_STATE : 3|4@0+ (1,0) [0|15] "" XXX
diff --git a/opendbc/generator/toyota/toyota_chr_2018_pt.dbc b/opendbc/generator/toyota/toyota_nodsu_pt.dbc
similarity index 74%
rename from opendbc/generator/toyota/toyota_chr_2018_pt.dbc
rename to opendbc/generator/toyota/toyota_nodsu_pt.dbc
index 7306ed2c0..026abdd88 100644
--- a/opendbc/generator/toyota/toyota_chr_2018_pt.dbc
+++ b/opendbc/generator/toyota/toyota_nodsu_pt.dbc
@@ -1,6 +1,17 @@
CM_ "IMPORT _toyota_2017.dbc"
CM_ "IMPORT _comma.dbc"
+BO_ 401 STEERING_LTA: 8 XXX
+ SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX
+ SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
+ SG_ SETME_X3 : 29|2@0+ (1,0) [0|3] "" XXX
+ SG_ PERCENTAGE : 39|8@0+ (1,0) [0|255] "" XXX
+ SG_ SETME_X64 : 47|8@0+ (1,0) [0|255] "" XXX
+ SG_ ANGLE : 55|8@0- (0.5,0) [0|255] "" XXX
+ SG_ STEER_ANGLE_CMD : 15|16@0- (0.056,0) [-540|540] "" XXX
+ SG_ STEER_REQUEST : 25|1@0+ (1,0) [0|1] "" XXX
+ SG_ BIT : 30|1@0+ (1,0) [0|1] "" XXX
+
BO_ 550 BRAKE_MODULE: 8 XXX
SG_ BRAKE_PRESSURE : 0|9@0+ (1,0) [0|511] "" XXX
SG_ BRAKE_POSITION : 16|9@0+ (1,0) [0|511] "" XXX
@@ -15,6 +26,7 @@ BO_ 608 STEER_TORQUE_SENSOR: 8 XXX
SG_ STEER_TORQUE_DRIVER : 15|16@0- (1,0) [-32768|32767] "" XXX
SG_ STEER_OVERRIDE : 0|1@0+ (1,0) [0|1] "" XXX
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
+ SG_ STEER_ANGLE : 31|16@0- (0.056,0) [-500|500] "" XXX
BO_ 610 EPS_STATUS: 8 EPS
SG_ IPAS_STATE : 3|4@0+ (1,0) [0|15] "" XXX
diff --git a/opendbc/honda_odyssey_extreme_edition_2018_china_can.dbc b/opendbc/honda_odyssey_extreme_edition_2018_china_can.dbc
index 5126bb16a..6bdcaab04 100644
--- a/opendbc/honda_odyssey_extreme_edition_2018_china_can.dbc
+++ b/opendbc/honda_odyssey_extreme_edition_2018_china_can.dbc
@@ -150,14 +150,15 @@ BO_ 780 ACC_HUD: 8 ADAS
SG_ FCM_PROBLEM : 34|1@0+ (1,0) [0|1] "" BDY
SG_ RADAR_OBSTRUCTED : 33|1@0+ (1,0) [0|1] "" BDY
SG_ ENABLE_MINI_CAR : 32|1@0+ (1,0) [0|1] "" BDY
- SG_ SET_ME_X03 : 47|2@0+ (1,0) [0|3] "" BDY
+ SG_ HUD_DISTANCE : 47|2@0+ (1,0) [0|3] "" BDY
SG_ HUD_LEAD : 45|2@0+ (1,0) [0|3] "" BDY
SG_ BOH_3 : 43|1@0+ (1,0) [0|3] "" BDY
SG_ BOH_4 : 42|1@0+ (1,0) [0|3] "" BDY
SG_ BOH_5 : 41|1@0+ (1,0) [0|3] "" BDY
SG_ CRUISE_CONTROL_LABEL : 40|1@0+ (1,0) [0|3] "" BDY
SG_ HUD_DISTANCE_3 : 52|1@0+ (1,0) [0|1] "" BDY
- SG_ SET_ME_X03_2 : 55|2@0+ (1,0) [0|3] "" BDY
+ SG_ IMPERIAL_UNIT : 54|1@0+ (1,0) [0|1] "" BDY
+ SG_ SET_ME_X01_2 : 55|1@0+ (1,0) [0|1] "" BDY
SG_ SET_ME_X01 : 48|1@0+ (1,0) [0|1] "" BDY
SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" BDY
SG_ CHECKSUM : 59|4@0+ (1,0) [0|3] "" BDY
diff --git a/opendbc/toyota_prius_2017_adas.dbc b/opendbc/toyota_adas.dbc
similarity index 100%
rename from opendbc/toyota_prius_2017_adas.dbc
rename to opendbc/toyota_adas.dbc
diff --git a/opendbc/toyota_camry_hybrid_2018_pt_generated.dbc b/opendbc/toyota_camry_hybrid_2018_pt_generated.dbc
index 35b4d97e2..5578b7063 100644
--- a/opendbc/toyota_camry_hybrid_2018_pt_generated.dbc
+++ b/opendbc/toyota_camry_hybrid_2018_pt_generated.dbc
@@ -314,7 +314,7 @@ BO_ 581 GAS_PEDAL: 8 XXX
SG_ GAS_PEDAL : 23|8@0+ (0.005,0) [0|1] "" XXX
BO_ 608 STEER_TORQUE_SENSOR: 8 XXX
- SG_ STEER_TORQUE_EPS : 47|16@0- (0.66,0) [-20000|20000] "" XXX
+ SG_ STEER_TORQUE_EPS : 47|16@0- (0.73,0) [-20000|20000] "" XXX
SG_ STEER_TORQUE_DRIVER : 15|16@0- (1,0) [-32768|32767] "" XXX
SG_ STEER_OVERRIDE : 0|1@0+ (1,0) [0|1] "" XXX
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
diff --git a/opendbc/toyota_chr_hybrid_2018_pt_generated.dbc b/opendbc/toyota_nodsu_hybrid_pt_generated.dbc
similarity index 99%
rename from opendbc/toyota_chr_hybrid_2018_pt_generated.dbc
rename to opendbc/toyota_nodsu_hybrid_pt_generated.dbc
index 5e53e1297..0e2bbb314 100644
--- a/opendbc/toyota_chr_hybrid_2018_pt_generated.dbc
+++ b/opendbc/toyota_nodsu_hybrid_pt_generated.dbc
@@ -295,7 +295,7 @@ VAL_ 1162 SPLSGN3 15 "conditional blank" 4 "wet road" 5 "rain" 0 "none";
CM_ "CHFFR_METRIC 37 STEER_ANGLE STEER_ANGLE 0.36 180";
-CM_ "toyota_chr_hybrid_2018_pt.dbc starts here"
+CM_ "toyota_nodsu_hybrid_pt.dbc starts here"
@@ -318,6 +318,7 @@ BO_ 608 STEER_TORQUE_SENSOR: 8 XXX
SG_ STEER_TORQUE_DRIVER : 15|16@0- (1,0) [-32768|32767] "" XXX
SG_ STEER_OVERRIDE : 0|1@0+ (1,0) [0|1] "" XXX
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
+ SG_ STEER_ANGLE : 31|16@0- (0.056,0) [-500|500] "" XXX
BO_ 610 EPS_STATUS: 8 EPS
SG_ IPAS_STATE : 3|4@0+ (1,0) [0|15] "" XXX
diff --git a/opendbc/toyota_chr_2018_pt_generated.dbc b/opendbc/toyota_nodsu_pt_generated.dbc
similarity index 96%
rename from opendbc/toyota_chr_2018_pt_generated.dbc
rename to opendbc/toyota_nodsu_pt_generated.dbc
index 69ba26969..d9e343f6a 100644
--- a/opendbc/toyota_chr_2018_pt_generated.dbc
+++ b/opendbc/toyota_nodsu_pt_generated.dbc
@@ -295,10 +295,21 @@ VAL_ 1162 SPLSGN3 15 "conditional blank" 4 "wet road" 5 "rain" 0 "none";
CM_ "CHFFR_METRIC 37 STEER_ANGLE STEER_ANGLE 0.36 180";
-CM_ "toyota_chr_2018_pt.dbc starts here"
+CM_ "toyota_nodsu_pt.dbc starts here"
+BO_ 401 STEERING_LTA: 8 XXX
+ SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX
+ SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
+ SG_ SETME_X3 : 29|2@0+ (1,0) [0|3] "" XXX
+ SG_ PERCENTAGE : 39|8@0+ (1,0) [0|255] "" XXX
+ SG_ SETME_X64 : 47|8@0+ (1,0) [0|255] "" XXX
+ SG_ ANGLE : 55|8@0- (0.5,0) [0|255] "" XXX
+ SG_ STEER_ANGLE_CMD : 15|16@0- (0.056,0) [-540|540] "" XXX
+ SG_ STEER_REQUEST : 25|1@0+ (1,0) [0|1] "" XXX
+ SG_ BIT : 30|1@0+ (1,0) [0|1] "" XXX
+
BO_ 550 BRAKE_MODULE: 8 XXX
SG_ BRAKE_PRESSURE : 0|9@0+ (1,0) [0|511] "" XXX
SG_ BRAKE_POSITION : 16|9@0+ (1,0) [0|511] "" XXX
@@ -313,6 +324,7 @@ BO_ 608 STEER_TORQUE_SENSOR: 8 XXX
SG_ STEER_TORQUE_DRIVER : 15|16@0- (1,0) [-32768|32767] "" XXX
SG_ STEER_OVERRIDE : 0|1@0+ (1,0) [0|1] "" XXX
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
+ SG_ STEER_ANGLE : 31|16@0- (0.056,0) [-500|500] "" XXX
BO_ 610 EPS_STATUS: 8 EPS
SG_ IPAS_STATE : 3|4@0+ (1,0) [0|15] "" XXX
diff --git a/opendbc/toyota_rav4_2019_adas.dbc b/opendbc/toyota_tss2_adas.dbc
similarity index 100%
rename from opendbc/toyota_rav4_2019_adas.dbc
rename to opendbc/toyota_tss2_adas.dbc
diff --git a/panda/.circleci/config.yml b/panda/.circleci/config.yml
index 06dae5735..e36aaa142 100644
--- a/panda/.circleci/config.yml
+++ b/panda/.circleci/config.yml
@@ -26,9 +26,19 @@ jobs:
command: |
mkdir /tmp/misra
docker run -v /tmp/misra:/tmp/misra panda_misra /bin/bash -c "cd /panda/tests/misra; ./test_misra.sh"
+ - store_artifacts:
+ name: Store cppcheck test output
+ path: /tmp/misra/cppcheck_output.txt
- store_artifacts:
name: Store misra test output
- path: /tmp/misra/output.txt
+ path: /tmp/misra/misra_output.txt
+ - store_artifacts:
+ name: Store cppcheck safety test output
+ path: /tmp/misra/cppcheck_safety_output.txt
+ - store_artifacts:
+ name: Store misra safety test output
+ path: /tmp/misra/misra_safety_output.txt
+
strict-compiler:
machine:
@@ -41,7 +51,7 @@ jobs:
- run:
name: Build Panda with strict compiler rules
command: |
- docker run panda_strict_compiler /bin/bash -c "cd /panda/board; make -f Makefile.strict clean; make -f Makefile.strict bin"
+ docker run panda_strict_compiler /bin/bash -c "cd /panda/tests/build_strict; ./test_build_strict.sh"
build:
machine:
@@ -76,6 +86,19 @@ jobs:
command: |
docker run panda_build /bin/bash -c "cd /panda/boardesp; make user1.bin"
+ safety_replay:
+ machine:
+ docker_layer_caching: true
+ steps:
+ - checkout
+ - run:
+ name: Build image
+ command: "docker build -t panda_safety_replay -f tests/safety_replay/Dockerfile ."
+ - run:
+ name: Replay drives
+ command: |
+ docker run panda_safety_replay /bin/bash -c "cd /openpilot/panda/tests/safety_replay; PYTHONPATH=/openpilot ./test_safety_replay.py"
+
workflows:
version: 2
main:
@@ -84,3 +107,4 @@ workflows:
- misra-c2012
- strict-compiler
- build
+ - safety_replay
diff --git a/panda/VERSION b/panda/VERSION
index bb8edae97..ec7b96782 100644
--- a/panda/VERSION
+++ b/panda/VERSION
@@ -1 +1 @@
-v1.3.2
\ No newline at end of file
+v1.4.0
\ No newline at end of file
diff --git a/panda/board/Makefile.strict b/panda/board/Makefile.strict
index b2ff83d30..b6c72b58b 100644
--- a/panda/board/Makefile.strict
+++ b/panda/board/Makefile.strict
@@ -1,5 +1,5 @@
PROJ_NAME = panda
-CFLAGS = -g -Wall -Wextra -pedantic -Wstrict-prototypes
+CFLAGS = -g -Wall -Wextra -Wstrict-prototypes
CFLAGS += -mlittle-endian -mthumb -mcpu=cortex-m4
CFLAGS += -mhard-float -DSTM32F4 -DSTM32F413xx -mfpu=fpv4-sp-d16 -fsingle-precision-constant
diff --git a/panda/board/bootstub.c b/panda/board/bootstub.c
index 6fcb386de..691d0d02e 100644
--- a/panda/board/bootstub.c
+++ b/panda/board/bootstub.c
@@ -13,7 +13,7 @@
#endif
// default since there's no serial
-int puts(const char *a) { return 0; }
+void puts(const char *a) {}
void puth(unsigned int i) {}
#include "libc.h"
diff --git a/panda/board/build.mk b/panda/board/build.mk
index bde461d21..af2bffeb0 100644
--- a/panda/board/build.mk
+++ b/panda/board/build.mk
@@ -2,12 +2,15 @@ CFLAGS += -I inc -I ../ -nostdlib -fno-builtin -std=gnu11 -Os
CFLAGS += -Tstm32_flash.ld
+DFU_UTIL = "dfu-util"
+
# Compile fast charge (DCP) only not on EON
ifeq (,$(wildcard /EON))
BUILDER = DEV
else
CFLAGS += "-DEON"
BUILDER = EON
+ DFU_UTIL = "tools/dfu-util-aarch64"
endif
CC = arm-none-eabi-gcc
@@ -22,7 +25,6 @@ else
CFLAGS += "-DALLOW_DEBUG"
endif
-DFU_UTIL = "dfu-util"
DEPDIR = generated_dependencies
$(shell mkdir -p -m 777 $(DEPDIR) >/dev/null)
diff --git a/panda/board/config.h b/panda/board/config.h
index e83429980..219ce64c2 100644
--- a/panda/board/config.h
+++ b/panda/board/config.h
@@ -22,17 +22,17 @@
#include
#define NULL ((void*)0)
-#define COMPILE_TIME_ASSERT(pred) switch(0){case 0:case pred:;}
+#define COMPILE_TIME_ASSERT(pred) ((void)sizeof(char[1 - (2 * (!(pred)))]))
-#define min(a,b) \
+#define MIN(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
- _a < _b ? _a : _b; })
+ (_a < _b) ? _a : _b; })
-#define max(a,b) \
+#define MAX(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
- _a > _b ? _a : _b; })
+ (_a > _b) ? _a : _b; })
#define MAX_RESP_LEN 0x40
diff --git a/panda/board/drivers/adc.h b/panda/board/drivers/adc.h
index cb2aeede0..3e5f1b32a 100644
--- a/panda/board/drivers/adc.h
+++ b/panda/board/drivers/adc.h
@@ -8,7 +8,7 @@
#define ADCCHAN_VOLTAGE 12
#define ADCCHAN_CURRENT 13
-void adc_init() {
+void adc_init(void) {
// global setup
ADC->CCR = ADC_CCR_TSVREFE | ADC_CCR_VBATE;
//ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_EOCS | ADC_CR2_DDS;
diff --git a/panda/board/drivers/can.h b/panda/board/drivers/can.h
index 43e4d41de..7d0e63058 100644
--- a/panda/board/drivers/can.h
+++ b/panda/board/drivers/can.h
@@ -3,8 +3,8 @@
// CAN3_TX, CAN3_RX0, CAN3_SCE
typedef struct {
- uint32_t w_ptr;
- uint32_t r_ptr;
+ volatile uint32_t w_ptr;
+ volatile uint32_t r_ptr;
uint32_t fifo_size;
CAN_FIFOMailBox_TypeDef *elems;
} can_ring;
@@ -18,14 +18,14 @@ extern int can_live, pending_can_live;
// must reinit after changing these
extern int can_loopback, can_silent;
-extern uint32_t can_speed[];
+extern uint32_t can_speed[4];
void can_set_forwarding(int from, int to);
void can_init(uint8_t can_number);
-void can_init_all();
+void can_init_all(void);
void can_send(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number);
-int can_pop(can_ring *q, CAN_FIFOMailBox_TypeDef *elem);
+bool can_pop(can_ring *q, CAN_FIFOMailBox_TypeDef *elem);
// end API
@@ -48,10 +48,17 @@ can_buffer(tx3_q, 0x100)
can_buffer(txgmlan_q, 0x100)
can_ring *can_queues[] = {&can_tx1_q, &can_tx2_q, &can_tx3_q, &can_txgmlan_q};
+// global CAN stats
+int can_rx_cnt = 0;
+int can_tx_cnt = 0;
+int can_txd_cnt = 0;
+int can_err_cnt = 0;
+int can_overflow_cnt = 0;
+
// ********************* interrupt safe queue *********************
-int can_pop(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) {
- int ret = 0;
+bool can_pop(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) {
+ bool ret = 0;
enter_critical_section();
if (q->w_ptr != q->r_ptr) {
@@ -78,7 +85,12 @@ int can_push(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) {
ret = 1;
}
exit_critical_section();
- if (ret == 0) puts("can_push failed!\n");
+ if (ret == 0) {
+ can_overflow_cnt++;
+ #ifdef DEBUG
+ puts("can_push failed!\n");
+ #endif
+ }
return ret;
}
@@ -98,11 +110,6 @@ void can_clear(can_ring *q) {
// can_num_lookup: Translates from 'bus number' to 'can number'.
// can_forwarding: Given a bus num, lookup bus num to forward to. -1 means no forward.
-int can_rx_cnt = 0;
-int can_tx_cnt = 0;
-int can_txd_cnt = 0;
-int can_err_cnt = 0;
-
// Panda: Bus 0=CAN1 Bus 1=CAN2 Bus 2=CAN3
CAN_TypeDef *cans[] = {CAN1, CAN2, CAN3};
uint8_t bus_lookup[] = {0,1,2};
@@ -112,8 +119,8 @@ uint32_t can_speed[] = {5000, 5000, 5000, 333};
#define CAN_MAX 3
#define CANIF_FROM_CAN_NUM(num) (cans[num])
-#define CAN_NUM_FROM_CANIF(CAN) (CAN==CAN1 ? 0 : (CAN==CAN2 ? 1 : 2))
-#define CAN_NAME_FROM_CANIF(CAN) (CAN==CAN1 ? "CAN1" : (CAN==CAN2 ? "CAN2" : "CAN3"))
+#define CAN_NUM_FROM_CANIF(CAN) ((CAN)==CAN1 ? 0 : ((CAN) == CAN2 ? 1 : 2))
+#define CAN_NAME_FROM_CANIF(CAN) ((CAN)==CAN1 ? "CAN1" : ((CAN) == CAN2 ? "CAN2" : "CAN3"))
#define BUS_NUM_FROM_CAN_NUM(num) (bus_lookup[num])
#define CAN_NUM_FROM_BUS_NUM(num) (can_num_lookup[num])
@@ -123,39 +130,34 @@ void can_set_speed(uint8_t can_number) {
CAN_TypeDef *CAN = CANIF_FROM_CAN_NUM(can_number);
uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number);
- while (true) {
- if (llcan_set_speed(CAN, can_speed[bus_number], can_loopback, can_silent & (1 << can_number))) {
- return;
- }
-
+ if (!llcan_set_speed(CAN, can_speed[bus_number], can_loopback, can_silent & (1 << can_number))) {
puts("CAN init FAILED!!!!!\n");
puth(can_number); puts(" ");
puth(BUS_NUM_FROM_CAN_NUM(can_number)); puts("\n");
- return;
}
}
void can_init(uint8_t can_number) {
- if (can_number == 0xff) return;
+ if (can_number != 0xff) {
+ CAN_TypeDef *CAN = CANIF_FROM_CAN_NUM(can_number);
+ set_can_enable(CAN, 1);
+ can_set_speed(can_number);
- CAN_TypeDef *CAN = CANIF_FROM_CAN_NUM(can_number);
- set_can_enable(CAN, 1);
- can_set_speed(can_number);
+ llcan_init(CAN);
- llcan_init(CAN);
-
- // in case there are queued up messages
- process_can(can_number);
+ // in case there are queued up messages
+ process_can(can_number);
+ }
}
-void can_init_all() {
+void can_init_all(void) {
for (int i=0; i < CAN_MAX; i++) {
can_init(i);
}
}
void can_set_gmlan(int bus) {
- if (bus == -1 || bus != can_num_lookup[3]) {
+ if ((bus == -1) || (bus != can_num_lookup[3])) {
// GMLAN OFF
switch (can_num_lookup[3]) {
case 1:
@@ -174,6 +176,9 @@ void can_set_gmlan(int bus) {
can_num_lookup[3] = -1;
can_init(2);
break;
+ default:
+ puts("GMLAN bus value invalid\n");
+ break;
}
}
@@ -227,67 +232,58 @@ void can_sce(CAN_TypeDef *CAN) {
// ***************************** CAN *****************************
void process_can(uint8_t can_number) {
- if (can_number == 0xff) return;
+ if (can_number != 0xff) {
- enter_critical_section();
+ enter_critical_section();
- CAN_TypeDef *CAN = CANIF_FROM_CAN_NUM(can_number);
- uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number);
- #ifdef DEBUG
- puts("process CAN TX\n");
- #endif
+ CAN_TypeDef *CAN = CANIF_FROM_CAN_NUM(can_number);
+ uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number);
- // check for empty mailbox
- CAN_FIFOMailBox_TypeDef to_send;
- if ((CAN->TSR & CAN_TSR_TME0) == CAN_TSR_TME0) {
- // add successfully transmitted message to my fifo
- if ((CAN->TSR & CAN_TSR_RQCP0) == CAN_TSR_RQCP0) {
- can_txd_cnt += 1;
+ // check for empty mailbox
+ CAN_FIFOMailBox_TypeDef to_send;
+ if ((CAN->TSR & CAN_TSR_TME0) == CAN_TSR_TME0) {
+ // add successfully transmitted message to my fifo
+ if ((CAN->TSR & CAN_TSR_RQCP0) == CAN_TSR_RQCP0) {
+ can_txd_cnt += 1;
- if ((CAN->TSR & CAN_TSR_TXOK0) == CAN_TSR_TXOK0) {
- CAN_FIFOMailBox_TypeDef to_push;
- to_push.RIR = CAN->sTxMailBox[0].TIR;
- to_push.RDTR = (CAN->sTxMailBox[0].TDTR & 0xFFFF000F) | ((CAN_BUS_RET_FLAG | bus_number) << 4);
- to_push.RDLR = CAN->sTxMailBox[0].TDLR;
- to_push.RDHR = CAN->sTxMailBox[0].TDHR;
- can_push(&can_rx_q, &to_push);
+ if ((CAN->TSR & CAN_TSR_TXOK0) == CAN_TSR_TXOK0) {
+ CAN_FIFOMailBox_TypeDef to_push;
+ to_push.RIR = CAN->sTxMailBox[0].TIR;
+ to_push.RDTR = (CAN->sTxMailBox[0].TDTR & 0xFFFF000F) | ((CAN_BUS_RET_FLAG | bus_number) << 4);
+ to_push.RDLR = CAN->sTxMailBox[0].TDLR;
+ to_push.RDHR = CAN->sTxMailBox[0].TDHR;
+ can_push(&can_rx_q, &to_push);
+ }
+
+ if ((CAN->TSR & CAN_TSR_TERR0) == CAN_TSR_TERR0) {
+ #ifdef DEBUG
+ puts("CAN TX ERROR!\n");
+ #endif
+ }
+
+ if ((CAN->TSR & CAN_TSR_ALST0) == CAN_TSR_ALST0) {
+ #ifdef DEBUG
+ puts("CAN TX ARBITRATION LOST!\n");
+ #endif
+ }
+
+ // clear interrupt
+ // careful, this can also be cleared by requesting a transmission
+ CAN->TSR |= CAN_TSR_RQCP0;
}
- if ((CAN->TSR & CAN_TSR_TERR0) == CAN_TSR_TERR0) {
- #ifdef DEBUG
- puts("CAN TX ERROR!\n");
- #endif
+ if (can_pop(can_queues[bus_number], &to_send)) {
+ can_tx_cnt += 1;
+ // only send if we have received a packet
+ CAN->sTxMailBox[0].TDLR = to_send.RDLR;
+ CAN->sTxMailBox[0].TDHR = to_send.RDHR;
+ CAN->sTxMailBox[0].TDTR = to_send.RDTR;
+ CAN->sTxMailBox[0].TIR = to_send.RIR;
}
-
- if ((CAN->TSR & CAN_TSR_ALST0) == CAN_TSR_ALST0) {
- #ifdef DEBUG
- puts("CAN TX ARBITRATION LOST!\n");
- #endif
- }
-
- // clear interrupt
- // careful, this can also be cleared by requesting a transmission
- CAN->TSR |= CAN_TSR_RQCP0;
}
- if (can_pop(can_queues[bus_number], &to_send)) {
- if (CAN->MCR & CAN_MCR_SLEEP) {
- set_can_enable(CAN, 1);
- CAN->MCR &= ~(CAN_MCR_SLEEP);
- CAN->MCR |= CAN_MCR_INRQ;
- while((CAN->MSR & CAN_MSR_INAK) != CAN_MSR_INAK);
- CAN->MCR &= ~(CAN_MCR_INRQ);
- }
- can_tx_cnt += 1;
- // only send if we have received a packet
- CAN->sTxMailBox[0].TDLR = to_send.RDLR;
- CAN->sTxMailBox[0].TDHR = to_send.RDHR;
- CAN->sTxMailBox[0].TDTR = to_send.RDTR;
- CAN->sTxMailBox[0].TIR = to_send.RIR;
- }
+ exit_critical_section();
}
-
- exit_critical_section();
}
// CAN receive handlers
@@ -295,7 +291,7 @@ void process_can(uint8_t can_number) {
void can_rx(uint8_t can_number) {
CAN_TypeDef *CAN = CANIF_FROM_CAN_NUM(can_number);
uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number);
- while (CAN->RF0R & CAN_RF0R_FMP0) {
+ while ((CAN->RF0R & CAN_RF0R_FMP0) != 0) {
can_rx_cnt += 1;
// can is live
@@ -312,7 +308,7 @@ void can_rx(uint8_t can_number) {
to_push.RDTR = (to_push.RDTR & 0xFFFF000F) | (bus_number << 4);
// forwarding (panda only)
- int bus_fwd_num = can_forwarding[bus_number] != -1 ? can_forwarding[bus_number] : safety_fwd_hook(bus_number, &to_push);
+ int bus_fwd_num = (can_forwarding[bus_number] != -1) ? can_forwarding[bus_number] : safety_fwd_hook(bus_number, &to_push);
if (bus_fwd_num != -1) {
CAN_FIFOMailBox_TypeDef to_send;
to_send.RIR = to_push.RIR | 1; // TXRQ
@@ -332,25 +328,25 @@ void can_rx(uint8_t can_number) {
}
}
-void CAN1_TX_IRQHandler() { process_can(0); }
-void CAN1_RX0_IRQHandler() { can_rx(0); }
-void CAN1_SCE_IRQHandler() { can_sce(CAN1); }
+void CAN1_TX_IRQHandler(void) { process_can(0); }
+void CAN1_RX0_IRQHandler(void) { can_rx(0); }
+void CAN1_SCE_IRQHandler(void) { can_sce(CAN1); }
-void CAN2_TX_IRQHandler() { process_can(1); }
-void CAN2_RX0_IRQHandler() { can_rx(1); }
-void CAN2_SCE_IRQHandler() { can_sce(CAN2); }
+void CAN2_TX_IRQHandler(void) { process_can(1); }
+void CAN2_RX0_IRQHandler(void) { can_rx(1); }
+void CAN2_SCE_IRQHandler(void) { can_sce(CAN2); }
-void CAN3_TX_IRQHandler() { process_can(2); }
-void CAN3_RX0_IRQHandler() { can_rx(2); }
-void CAN3_SCE_IRQHandler() { can_sce(CAN3); }
+void CAN3_TX_IRQHandler(void) { process_can(2); }
+void CAN3_RX0_IRQHandler(void) { can_rx(2); }
+void CAN3_SCE_IRQHandler(void) { can_sce(CAN3); }
void can_send(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number) {
- if (safety_tx_hook(to_push)) {
+ if (safety_tx_hook(to_push) != 0) {
if (bus_number < BUS_MAX) {
// add CAN packet to send queue
// bus number isn't passed through
to_push->RDTR &= 0xF;
- if (bus_number == 3 && can_num_lookup[3] == 0xFF) {
+ if ((bus_number == 3) && (can_num_lookup[3] == 0xFF)) {
// TODO: why uint8 bro? only int8?
bitbang_gmlan(to_push);
} else {
diff --git a/panda/board/drivers/clock.h b/panda/board/drivers/clock.h
index c999c3f59..a9f2dea73 100644
--- a/panda/board/drivers/clock.h
+++ b/panda/board/drivers/clock.h
@@ -1,4 +1,4 @@
-void clock_init() {
+void clock_init(void) {
// enable external oscillator
RCC->CR |= RCC_CR_HSEON;
while ((RCC->CR & RCC_CR_HSERDY) == 0);
@@ -25,7 +25,7 @@ void clock_init() {
// *** running on PLL ***
}
-void watchdog_init() {
+void watchdog_init(void) {
// setup watchdog
IWDG->KR = 0x5555;
IWDG->PR = 0; // divider /4
@@ -34,7 +34,7 @@ void watchdog_init() {
IWDG->KR = 0xCCCC;
}
-void watchdog_feed() {
+void watchdog_feed(void) {
IWDG->KR = 0xAAAA;
}
diff --git a/panda/board/drivers/gmlan_alt.h b/panda/board/drivers/gmlan_alt.h
index d24833a8f..357cffcd9 100644
--- a/panda/board/drivers/gmlan_alt.h
+++ b/panda/board/drivers/gmlan_alt.h
@@ -9,7 +9,7 @@
#define MAX_BITS_CAN_PACKET (200)
-int gmlan_alt_mode = DISABLED;
+int gmlan_alt_mode = DISABLED;
// returns out_len
int do_bitstuff(char *out, char *in, int in_len) {
@@ -18,7 +18,8 @@ int do_bitstuff(char *out, char *in, int in_len) {
int j = 0;
for (int i = 0; i < in_len; i++) {
char bit = in[i];
- out[j++] = bit;
+ out[j] = bit;
+ j++;
// do the stuffing
if (bit == last_bit) {
@@ -26,7 +27,8 @@ int do_bitstuff(char *out, char *in, int in_len) {
if (bit_cnt == 5) {
// 5 in a row the same, do stuff
last_bit = !bit;
- out[j++] = last_bit;
+ out[j] = last_bit;
+ j++;
bit_cnt = 1;
}
} else {
@@ -42,27 +44,30 @@ int append_crc(char *in, int in_len) {
int crc = 0;
for (int i = 0; i < in_len; i++) {
crc <<= 1;
- if (in[i] ^ ((crc>>15)&1)) {
+ if ((in[i] ^ ((crc >> 15) & 1)) != 0) {
crc = crc ^ 0x4599;
}
crc &= 0x7fff;
}
for (int i = 14; i >= 0; i--) {
- in[in_len++] = (crc>>i)&1;
+ in[in_len] = (crc>>i)&1;
+ in_len++;
}
return in_len;
}
int append_bits(char *in, int in_len, char *app, int app_len) {
for (int i = 0; i < app_len; i++) {
- in[in_len++] = app[i];
+ in[in_len] = app[i];
+ in_len++;
}
return in_len;
}
int append_int(char *in, int in_len, int val, int val_len) {
for (int i = val_len-1; i >= 0; i--) {
- in[in_len++] = (val&(1<RDTR & 0xF;
len = append_int(pkt, len, 0, 1); // Start-of-frame
-
- if (to_bang->RIR & 4) {
+
+ if ((to_bang->RIR & 4) != 0) {
// extended identifier
len = append_int(pkt, len, to_bang->RIR >> 21, 11); // Identifier
len = append_int(pkt, len, 3, 2); // SRR+IDE
@@ -114,7 +119,7 @@ int get_bit_message(char *out, CAN_FIFOMailBox_TypeDef *to_bang) {
return len;
}
-void setup_timer4() {
+void setup_timer4(void) {
// setup
TIM4->PSC = 48-1; // tick on 1 us
TIM4->CR1 = TIM_CR1_CEN; // enable
@@ -131,7 +136,7 @@ void setup_timer4() {
int gmlan_timeout_counter = GMLAN_TICKS_PER_TIMEOUT_TICKLE; //GMLAN transceiver times out every 17ms held high; tickle every 15ms
int can_timeout_counter = GMLAN_TICKS_PER_SECOND; //1 second
-int inverted_bit_to_send = GMLAN_HIGH;
+int inverted_bit_to_send = GMLAN_HIGH;
int gmlan_switch_below_timeout = -1;
int gmlan_switch_timeout_enable = 0;
@@ -140,9 +145,9 @@ void gmlan_switch_init(int timeout_enable) {
gmlan_alt_mode = GPIO_SWITCH;
gmlan_switch_below_timeout = 1;
set_gpio_mode(GPIOB, 13, MODE_OUTPUT);
-
+
setup_timer4();
-
+
inverted_bit_to_send = GMLAN_LOW; //We got initialized, set the output low
}
@@ -162,7 +167,7 @@ void reset_gmlan_switch_timeout(void) {
}
void set_bitbanged_gmlan(int val) {
- if (val) {
+ if (val != 0) {
GPIOB->ODR |= (1 << 13);
} else {
GPIOB->ODR &= ~(1 << 13);
@@ -180,7 +185,7 @@ int gmlan_fail_count = 0;
void TIM4_IRQHandler(void) {
if (gmlan_alt_mode == BITBANG) {
- if (TIM4->SR & TIM_SR_UIF && gmlan_sendmax != -1) {
+ if ((TIM4->SR & TIM_SR_UIF) && (gmlan_sendmax != -1)) {
int read = get_gpio_input(GPIOB, 12);
if (gmlan_silent_count < REQUIRED_SILENT_TIME) {
if (read == 0) {
@@ -189,16 +194,16 @@ void TIM4_IRQHandler(void) {
gmlan_silent_count++;
}
} else if (gmlan_silent_count == REQUIRED_SILENT_TIME) {
- int retry = 0;
+ bool retry = 0;
// in send loop
- if (gmlan_sending > 0 && // not first bit
- (read == 0 && pkt_stuffed[gmlan_sending-1] == 1) && // bus wrongly dominant
- gmlan_sending != (gmlan_sendmax-11)) { //not ack bit
+ if ((gmlan_sending > 0) && // not first bit
+ ((read == 0) && (pkt_stuffed[gmlan_sending-1] == 1)) && // bus wrongly dominant
+ (gmlan_sending != (gmlan_sendmax - 11))) { //not ack bit
puts("GMLAN ERR: bus driven at ");
puth(gmlan_sending);
puts("\n");
retry = 1;
- } else if (read == 1 && gmlan_sending == (gmlan_sendmax-11)) { // recessive during ACK
+ } else if ((read == 1) && (gmlan_sending == (gmlan_sendmax - 11))) { // recessive during ACK
puts("GMLAN ERR: didn't recv ACK\n");
retry = 1;
}
@@ -216,7 +221,7 @@ void TIM4_IRQHandler(void) {
gmlan_sending++;
}
}
- if (gmlan_sending == gmlan_sendmax || gmlan_fail_count == MAX_FAIL_COUNT) {
+ if ((gmlan_sending == gmlan_sendmax) || (gmlan_fail_count == MAX_FAIL_COUNT)) {
set_bitbanged_gmlan(1); // recessive
set_gpio_mode(GPIOB, 13, MODE_INPUT);
TIM4->DIER = 0; // no update interrupt
@@ -228,8 +233,8 @@ void TIM4_IRQHandler(void) {
} //bit bang mode
else if (gmlan_alt_mode == GPIO_SWITCH) {
- if (TIM4->SR & TIM_SR_UIF && gmlan_switch_below_timeout != -1) {
- if (can_timeout_counter == 0 && gmlan_switch_timeout_enable) {
+ if ((TIM4->SR & TIM_SR_UIF) && (gmlan_switch_below_timeout != -1)) {
+ if ((can_timeout_counter == 0) && gmlan_switch_timeout_enable) {
//it has been more than 1 second since timeout was reset; disable timer and restore the GMLAN output
set_gpio_output(GPIOB, 13, GMLAN_LOW);
gmlan_switch_below_timeout = -1;
@@ -256,18 +261,19 @@ void TIM4_IRQHandler(void) {
void bitbang_gmlan(CAN_FIFOMailBox_TypeDef *to_bang) {
gmlan_alt_mode = BITBANG;
// TODO: make failure less silent
- if (gmlan_sendmax != -1) return;
+ if (gmlan_sendmax == -1) {
- int len = get_bit_message(pkt_stuffed, to_bang);
- gmlan_fail_count = 0;
- gmlan_silent_count = 0;
- gmlan_sending = 0;
- gmlan_sendmax = len;
+ int len = get_bit_message(pkt_stuffed, to_bang);
+ gmlan_fail_count = 0;
+ gmlan_silent_count = 0;
+ gmlan_sending = 0;
+ gmlan_sendmax = len;
- // setup for bitbang loop
- set_bitbanged_gmlan(1); // recessive
- set_gpio_mode(GPIOB, 13, MODE_OUTPUT);
+ // setup for bitbang loop
+ set_bitbanged_gmlan(1); // recessive
+ set_gpio_mode(GPIOB, 13, MODE_OUTPUT);
- setup_timer4();
+ setup_timer4();
+ }
}
diff --git a/panda/board/drivers/llcan.h b/panda/board/drivers/llcan.h
index 5c771f76f..5d0b88845 100644
--- a/panda/board/drivers/llcan.h
+++ b/panda/board/drivers/llcan.h
@@ -31,12 +31,13 @@ bool llcan_set_speed(CAN_TypeDef *CAN, uint32_t speed, bool loopback, bool silen
#define CAN_TIMEOUT 1000000
int tmp = 0;
- while((CAN->MSR & CAN_MSR_INAK) == CAN_MSR_INAK && tmp < CAN_TIMEOUT) tmp++;
+ bool ret = false;
+ while(((CAN->MSR & CAN_MSR_INAK) == CAN_MSR_INAK) && (tmp < CAN_TIMEOUT)) tmp++;
if (tmp < CAN_TIMEOUT) {
- return true;
+ ret = true;
}
- return false;
+ return ret;
}
void llcan_init(CAN_TypeDef *CAN) {
@@ -48,7 +49,7 @@ void llcan_init(CAN_TypeDef *CAN) {
CAN->sFilterRegister[0].FR2 = 0;
CAN->sFilterRegister[14].FR1 = 0;
CAN->sFilterRegister[14].FR2 = 0;
- CAN->FA1R |= 1 | (1 << 14);
+ CAN->FA1R |= 1 | (1U << 14);
CAN->FMR &= ~(CAN_FMR_FINIT);
diff --git a/panda/board/drivers/llgpio.h b/panda/board/drivers/llgpio.h
index 984127631..172776eb3 100644
--- a/panda/board/drivers/llgpio.h
+++ b/panda/board/drivers/llgpio.h
@@ -14,8 +14,8 @@ void set_gpio_mode(GPIO_TypeDef *GPIO, int pin, int mode) {
GPIO->MODER = tmp;
}
-void set_gpio_output(GPIO_TypeDef *GPIO, int pin, int val) {
- if (val) {
+void set_gpio_output(GPIO_TypeDef *GPIO, int pin, bool enabled) {
+ if (enabled) {
GPIO->ODR |= (1 << pin);
} else {
GPIO->ODR &= ~(1 << pin);
@@ -39,6 +39,6 @@ void set_gpio_pullup(GPIO_TypeDef *GPIO, int pin, int mode) {
}
int get_gpio_input(GPIO_TypeDef *GPIO, int pin) {
- return (GPIO->IDR & (1 << pin)) == (1 << pin);
+ return (GPIO->IDR & (1U << pin)) == (1U << pin);
}
diff --git a/panda/board/drivers/spi.h b/panda/board/drivers/spi.h
index f31f20590..b61cd719a 100644
--- a/panda/board/drivers/spi.h
+++ b/panda/board/drivers/spi.h
@@ -1,6 +1,6 @@
// IRQs: DMA2_Stream2, DMA2_Stream3, EXTI4
-void spi_init();
+void spi_init(void);
int spi_cb_rx(uint8_t *data, int len, uint8_t *data_out);
// end API
@@ -10,7 +10,7 @@ uint8_t spi_buf[SPI_BUF_SIZE];
int spi_buf_count = 0;
int spi_total_count = 0;
-void spi_init() {
+void spi_init(void) {
//puts("SPI init\n");
SPI1->CR1 = SPI_CR1_SPE;
@@ -118,7 +118,7 @@ void EXTI4_IRQHandler(void) {
puts("exti4\n");
#endif
// SPI CS falling
- if (pr & (1 << 4)) {
+ if ((pr & (1 << 4)) != 0) {
spi_total_count = 0;
spi_rx_dma(spi_buf, 0x14);
}
diff --git a/panda/board/drivers/uart.h b/panda/board/drivers/uart.h
index baba42e34..f86c5f159 100644
--- a/panda/board/drivers/uart.h
+++ b/panda/board/drivers/uart.h
@@ -2,11 +2,11 @@
#define FIFO_SIZE 0x400
typedef struct uart_ring {
- uint16_t w_ptr_tx;
- uint16_t r_ptr_tx;
+ volatile uint16_t w_ptr_tx;
+ volatile uint16_t r_ptr_tx;
uint8_t elems_tx[FIFO_SIZE];
- uint16_t w_ptr_rx;
- uint16_t r_ptr_rx;
+ volatile uint16_t w_ptr_rx;
+ volatile uint16_t r_ptr_rx;
uint8_t elems_rx[FIFO_SIZE];
USART_TypeDef *uart;
void (*callback)(struct uart_ring*);
@@ -14,10 +14,10 @@ typedef struct uart_ring {
void uart_init(USART_TypeDef *u, int baud);
-int getc(uart_ring *q, char *elem);
-int putc(uart_ring *q, char elem);
+bool getc(uart_ring *q, char *elem);
+bool putc(uart_ring *q, char elem);
-int puts(const char *a);
+void puts(const char *a);
void puth(unsigned int i);
void hexdump(const void *a, int l);
@@ -50,18 +50,25 @@ uart_ring debug_ring = { .w_ptr_tx = 0, .r_ptr_tx = 0,
uart_ring *get_ring_by_number(int a) {
+ uart_ring *ring = NULL;
switch(a) {
case 0:
- return &debug_ring;
+ ring = &debug_ring;
+ break;
case 1:
- return &esp_ring;
+ ring = &esp_ring;
+ break;
case 2:
- return &lin1_ring;
+ ring = &lin1_ring;
+ break;
case 3:
- return &lin2_ring;
+ ring = &lin2_ring;
+ break;
default:
- return NULL;
+ ring = NULL;
+ break;
}
+ return ring;
}
// ***************************** serial port *****************************
@@ -72,31 +79,32 @@ void uart_ring_process(uart_ring *q) {
int sr = q->uart->SR;
if (q->w_ptr_tx != q->r_ptr_tx) {
- if (sr & USART_SR_TXE) {
+ if ((sr & USART_SR_TXE) != 0) {
q->uart->DR = q->elems_tx[q->r_ptr_tx];
q->r_ptr_tx = (q->r_ptr_tx + 1) % FIFO_SIZE;
- } else {
- // push on interrupt later
- q->uart->CR1 |= USART_CR1_TXEIE;
}
+ // there could be more to send
+ q->uart->CR1 |= USART_CR1_TXEIE;
} else {
// nothing to send
q->uart->CR1 &= ~USART_CR1_TXEIE;
}
- if (sr & USART_SR_RXNE || sr & USART_SR_ORE) {
+ if ((sr & USART_SR_RXNE) || (sr & USART_SR_ORE)) {
uint8_t c = q->uart->DR; // TODO: can drop packets
if (q != &esp_ring) {
uint16_t next_w_ptr = (q->w_ptr_rx + 1) % FIFO_SIZE;
if (next_w_ptr != q->r_ptr_rx) {
q->elems_rx[q->w_ptr_rx] = c;
q->w_ptr_rx = next_w_ptr;
- if (q->callback) q->callback(q);
+ if (q->callback != NULL) {
+ q->callback(q);
+ }
}
}
}
- if (sr & USART_SR_ORE) {
+ if ((sr & USART_SR_ORE) != 0) {
// set dropped packet flag?
}
@@ -110,22 +118,22 @@ void USART2_IRQHandler(void) { uart_ring_process(&debug_ring); }
void USART3_IRQHandler(void) { uart_ring_process(&lin2_ring); }
void UART5_IRQHandler(void) { uart_ring_process(&lin1_ring); }
-int getc(uart_ring *q, char *elem) {
- int ret = 0;
+bool getc(uart_ring *q, char *elem) {
+ bool ret = false;
enter_critical_section();
if (q->w_ptr_rx != q->r_ptr_rx) {
- *elem = q->elems_rx[q->r_ptr_rx];
+ if (elem != NULL) *elem = q->elems_rx[q->r_ptr_rx];
q->r_ptr_rx = (q->r_ptr_rx + 1) % FIFO_SIZE;
- ret = 1;
+ ret = true;
}
exit_critical_section();
return ret;
}
-int injectc(uart_ring *q, char elem) {
- int ret = 0;
+bool injectc(uart_ring *q, char elem) {
+ int ret = false;
uint16_t next_w_ptr;
enter_critical_section();
@@ -133,15 +141,15 @@ int injectc(uart_ring *q, char elem) {
if (next_w_ptr != q->r_ptr_rx) {
q->elems_rx[q->w_ptr_rx] = elem;
q->w_ptr_rx = next_w_ptr;
- ret = 1;
+ ret = true;
}
exit_critical_section();
return ret;
}
-int putc(uart_ring *q, char elem) {
- int ret = 0;
+bool putc(uart_ring *q, char elem) {
+ bool ret = false;
uint16_t next_w_ptr;
enter_critical_section();
@@ -149,7 +157,7 @@ int putc(uart_ring *q, char elem) {
if (next_w_ptr != q->r_ptr_tx) {
q->elems_tx[q->w_ptr_tx] = elem;
q->w_ptr_tx = next_w_ptr;
- ret = 1;
+ ret = true;
}
exit_critical_section();
@@ -158,6 +166,24 @@ int putc(uart_ring *q, char elem) {
return ret;
}
+void uart_flush(uart_ring *q) {
+ while (q->w_ptr_tx != q->r_ptr_tx) {
+ __WFI();
+ }
+}
+
+void uart_flush_sync(uart_ring *q) {
+ // empty the TX buffer
+ while (q->w_ptr_tx != q->r_ptr_tx) {
+ uart_ring_process(q);
+ }
+}
+
+void uart_send_break(uart_ring *u) {
+ while ((u->uart->CR1 & USART_CR1_SBK) != 0);
+ u->uart->CR1 |= USART_CR1_SBK;
+}
+
void clear_uart_buff(uart_ring *q) {
enter_critical_section();
q->w_ptr_tx = 0;
@@ -169,10 +195,10 @@ void clear_uart_buff(uart_ring *q) {
// ***************************** start UART code *****************************
-#define __DIV(_PCLK_, _BAUD_) (((_PCLK_)*25)/(4*(_BAUD_)))
-#define __DIVMANT(_PCLK_, _BAUD_) (__DIV((_PCLK_), (_BAUD_))/100)
-#define __DIVFRAQ(_PCLK_, _BAUD_) (((__DIV((_PCLK_), (_BAUD_)) - (__DIVMANT((_PCLK_), (_BAUD_)) * 100)) * 16 + 50) / 100)
-#define __USART_BRR(_PCLK_, _BAUD_) ((__DIVMANT((_PCLK_), (_BAUD_)) << 4)|(__DIVFRAQ((_PCLK_), (_BAUD_)) & 0x0F))
+#define __DIV(_PCLK_, _BAUD_) (((_PCLK_) * 25) / (4 * (_BAUD_)))
+#define __DIVMANT(_PCLK_, _BAUD_) (__DIV((_PCLK_), (_BAUD_)) / 100)
+#define __DIVFRAQ(_PCLK_, _BAUD_) ((((__DIV((_PCLK_), (_BAUD_)) - (__DIVMANT((_PCLK_), (_BAUD_)) * 100)) * 16) + 50) / 100)
+#define __USART_BRR(_PCLK_, _BAUD_) ((__DIVMANT((_PCLK_), (_BAUD_)) << 4) | (__DIVFRAQ((_PCLK_), (_BAUD_)) & 0x0F))
void uart_set_baud(USART_TypeDef *u, int baud) {
if (u == USART1) {
@@ -186,19 +212,19 @@ void uart_set_baud(USART_TypeDef *u, int baud) {
#define USART1_DMA_LEN 0x20
char usart1_dma[USART1_DMA_LEN];
-void uart_dma_drain() {
+void uart_dma_drain(void) {
uart_ring *q = &esp_ring;
enter_critical_section();
- if (DMA2->HISR & DMA_HISR_TCIF5 || DMA2->HISR & DMA_HISR_HTIF5 || DMA2_Stream5->NDTR != USART1_DMA_LEN) {
+ if ((DMA2->HISR & DMA_HISR_TCIF5) || (DMA2->HISR & DMA_HISR_HTIF5) || (DMA2_Stream5->NDTR != USART1_DMA_LEN)) {
// disable DMA
q->uart->CR3 &= ~USART_CR3_DMAR;
DMA2_Stream5->CR &= ~DMA_SxCR_EN;
- while (DMA2_Stream5->CR & DMA_SxCR_EN);
+ while ((DMA2_Stream5->CR & DMA_SxCR_EN) != 0);
- int i;
- for (i = 0; i < USART1_DMA_LEN - DMA2_Stream5->NDTR; i++) {
+ unsigned int i;
+ for (i = 0; i < (USART1_DMA_LEN - DMA2_Stream5->NDTR); i++) {
char c = usart1_dma[i];
uint16_t next_w_ptr = (q->w_ptr_rx + 1) % FIFO_SIZE;
if (next_w_ptr != q->r_ptr_rx) {
@@ -280,22 +306,23 @@ void putch(const char a) {
}
}
-int puts(const char *a) {
+void puts(const char *a) {
for (;*a;a++) {
if (*a == '\n') putch('\r');
putch(*a);
}
- return 0;
}
void putui(uint32_t i) {
char str[11];
uint8_t idx = 10;
- str[idx--] = '\0';
+ str[idx] = '\0';
+ idx--;
do {
- str[idx--] = (i % 10) + 0x30;
+ str[idx] = (i % 10) + 0x30;
+ idx--;
i /= 10;
- } while (i);
+ } while (i != 0);
puts(str + idx + 1);
}
@@ -318,7 +345,7 @@ void puth2(unsigned int i) {
void hexdump(const void *a, int l) {
int i;
for (i=0;i>8)&0xFF)
+ ((num) & 0xFF), (((num) >> 8) & 0xFF)
// take in string length and return the first 2 bytes of a string descriptor
#define STRING_DESCRIPTOR_HEADER(size)\
- (((size * 2 + 2)&0xFF) | 0x0300)
+ (((((size) * 2) + 2) & 0xFF) | 0x0300)
uint8_t device_desc[] = {
DSCR_DEVICE_LEN, USB_DESC_TYPE_DEVICE, //Length, Type
@@ -397,9 +397,10 @@ void *USB_ReadPacket(void *dest, uint16_t len) {
uint32_t i=0;
uint32_t count32b = (len + 3) / 4;
- for ( i = 0; i < count32b; i++, dest += 4 ) {
+ for ( i = 0; i < count32b; i++) {
// packed?
*(__attribute__((__packed__)) uint32_t *)dest = USBx_DFIFO(0);
+ dest += 4;
}
return ((void *)dest);
}
@@ -420,8 +421,9 @@ void USB_WritePacket(const uint8_t *src, uint16_t len, uint32_t ep) {
USBx_INEP(ep)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
// load the FIFO
- for (i = 0; i < count32b; i++, src += 4) {
+ for (i = 0; i < count32b; i++) {
USBx_DFIFO(ep) = *((__attribute__((__packed__)) uint32_t *)src);
+ src += 4;
}
}
@@ -433,7 +435,7 @@ void USB_WritePacket_EP0(uint8_t *src, uint16_t len) {
hexdump(src, len);
#endif
- uint16_t wplen = min(len, 0x40);
+ uint16_t wplen = MIN(len, 0x40);
USB_WritePacket(src, wplen, 0);
if (wplen < len) {
@@ -445,7 +447,7 @@ void USB_WritePacket_EP0(uint8_t *src, uint16_t len) {
}
}
-void usb_reset() {
+void usb_reset(void) {
// unmask endpoint interrupts, so many sets
USBx_DEVICE->DAINT = 0xFFFFFFFF;
USBx_DEVICE->DAINTMSK = 0xFFFFFFFF;
@@ -489,14 +491,16 @@ void usb_reset() {
}
char to_hex_char(int a) {
+ char ret;
if (a < 10) {
- return '0' + a;
+ ret = '0' + a;
} else {
- return 'a' + (a-10);
+ ret = 'a' + (a - 10);
}
+ return ret;
}
-void usb_setup() {
+void usb_setup(void) {
int resp_len;
// setup packet is ready
switch (setup.b.bRequest) {
@@ -545,29 +549,29 @@ void usb_setup() {
//puts(" writing device descriptor\n");
// setup transfer
- USB_WritePacket(device_desc, min(sizeof(device_desc), setup.b.wLength.w), 0);
+ USB_WritePacket(device_desc, MIN(sizeof(device_desc), setup.b.wLength.w), 0);
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
//puts("D");
break;
case USB_DESC_TYPE_CONFIGURATION:
- USB_WritePacket(configuration_desc, min(sizeof(configuration_desc), setup.b.wLength.w), 0);
+ USB_WritePacket(configuration_desc, MIN(sizeof(configuration_desc), setup.b.wLength.w), 0);
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
break;
case USB_DESC_TYPE_DEVICE_QUALIFIER:
- USB_WritePacket(device_qualifier, min(sizeof(device_qualifier), setup.b.wLength.w), 0);
+ USB_WritePacket(device_qualifier, MIN(sizeof(device_qualifier), setup.b.wLength.w), 0);
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
break;
case USB_DESC_TYPE_STRING:
switch (setup.b.wValue.bw.msb) {
case STRING_OFFSET_LANGID:
- USB_WritePacket((uint8_t*)string_language_desc, min(sizeof(string_language_desc), setup.b.wLength.w), 0);
+ USB_WritePacket((uint8_t*)string_language_desc, MIN(sizeof(string_language_desc), setup.b.wLength.w), 0);
break;
case STRING_OFFSET_IMANUFACTURER:
- USB_WritePacket((uint8_t*)string_manufacturer_desc, min(sizeof(string_manufacturer_desc), setup.b.wLength.w), 0);
+ USB_WritePacket((uint8_t*)string_manufacturer_desc, MIN(sizeof(string_manufacturer_desc), setup.b.wLength.w), 0);
break;
case STRING_OFFSET_IPRODUCT:
- USB_WritePacket((uint8_t*)string_product_desc, min(sizeof(string_product_desc), setup.b.wLength.w), 0);
+ USB_WritePacket((uint8_t*)string_product_desc, MIN(sizeof(string_product_desc), setup.b.wLength.w), 0);
break;
case STRING_OFFSET_ISERIAL:
#ifdef UID_BASE
@@ -583,16 +587,16 @@ void usb_setup() {
resp[2 + i*4 + 3] = '\0';
}
- USB_WritePacket(resp, min(resp[0], setup.b.wLength.w), 0);
+ USB_WritePacket(resp, MIN(resp[0], setup.b.wLength.w), 0);
#else
- USB_WritePacket((const uint8_t *)string_serial_desc, min(sizeof(string_serial_desc), setup.b.wLength.w), 0);
+ USB_WritePacket((const uint8_t *)string_serial_desc, MIN(sizeof(string_serial_desc), setup.b.wLength.w), 0);
#endif
break;
case STRING_OFFSET_ICONFIGURATION:
- USB_WritePacket((uint8_t*)string_configuration_desc, min(sizeof(string_configuration_desc), setup.b.wLength.w), 0);
+ USB_WritePacket((uint8_t*)string_configuration_desc, MIN(sizeof(string_configuration_desc), setup.b.wLength.w), 0);
break;
case 238:
- USB_WritePacket((uint8_t*)string_238_desc, min(sizeof(string_238_desc), setup.b.wLength.w), 0);
+ USB_WritePacket((uint8_t*)string_238_desc, MIN(sizeof(string_238_desc), setup.b.wLength.w), 0);
break;
default:
// nothing
@@ -602,7 +606,7 @@ void usb_setup() {
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
break;
case USB_DESC_TYPE_BINARY_OBJECT_STORE:
- USB_WritePacket(binary_object_store_desc, min(sizeof(binary_object_store_desc), setup.b.wLength.w), 0);
+ USB_WritePacket(binary_object_store_desc, MIN(sizeof(binary_object_store_desc), setup.b.wLength.w), 0);
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
break;
default:
@@ -628,7 +632,7 @@ void usb_setup() {
case WEBUSB_VENDOR_CODE:
switch (setup.b.wIndex.w) {
case WEBUSB_REQ_GET_URL:
- USB_WritePacket(webusb_url_descriptor, min(sizeof(webusb_url_descriptor), setup.b.wLength.w), 0);
+ USB_WritePacket(webusb_url_descriptor, MIN(sizeof(webusb_url_descriptor), setup.b.wLength.w), 0);
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
break;
default:
@@ -642,15 +646,15 @@ void usb_setup() {
switch (setup.b.wIndex.w) {
// winusb 2.0 descriptor from BOS
case WINUSB_REQ_GET_DESCRIPTOR:
- USB_WritePacket_EP0((uint8_t*)winusb_20_desc, min(sizeof(winusb_20_desc), setup.b.wLength.w));
+ USB_WritePacket_EP0((uint8_t*)winusb_20_desc, MIN(sizeof(winusb_20_desc), setup.b.wLength.w));
break;
// Extended Compat ID OS Descriptor
case WINUSB_REQ_GET_COMPATID_DESCRIPTOR:
- USB_WritePacket_EP0((uint8_t*)winusb_ext_compatid_os_desc, min(sizeof(winusb_ext_compatid_os_desc), setup.b.wLength.w));
+ USB_WritePacket_EP0((uint8_t*)winusb_ext_compatid_os_desc, MIN(sizeof(winusb_ext_compatid_os_desc), setup.b.wLength.w));
break;
// Extended Properties OS Descriptor
case WINUSB_REQ_GET_EXT_PROPS_OS:
- USB_WritePacket_EP0((uint8_t*)winusb_ext_prop_os_desc, min(sizeof(winusb_ext_prop_os_desc), setup.b.wLength.w));
+ USB_WritePacket_EP0((uint8_t*)winusb_ext_prop_os_desc, MIN(sizeof(winusb_ext_prop_os_desc), setup.b.wLength.w));
break;
default:
USB_WritePacket_EP0(0, 0);
@@ -658,12 +662,12 @@ void usb_setup() {
break;
default:
resp_len = usb_cb_control_msg(&setup, resp, 1);
- USB_WritePacket(resp, min(resp_len, setup.b.wLength.w), 0);
+ USB_WritePacket(resp, MIN(resp_len, setup.b.wLength.w), 0);
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
}
}
-void usb_init() {
+void usb_init(void) {
// full speed PHY, do reset and remove power down
/*puth(USBx->GRSTCTL);
puts(" resetting PHY\n");*/
@@ -756,27 +760,27 @@ void usb_irqhandler(void) {
puts(" USB interrupt!\n");
#endif
- if (gintsts & USB_OTG_GINTSTS_CIDSCHG) {
+ if ((gintsts & USB_OTG_GINTSTS_CIDSCHG) != 0) {
puts("connector ID status change\n");
}
- if (gintsts & USB_OTG_GINTSTS_ESUSP) {
+ if ((gintsts & USB_OTG_GINTSTS_ESUSP) != 0) {
puts("ESUSP detected\n");
}
- if (gintsts & USB_OTG_GINTSTS_USBRST) {
+ if ((gintsts & USB_OTG_GINTSTS_USBRST) != 0) {
puts("USB reset\n");
usb_reset();
}
- if (gintsts & USB_OTG_GINTSTS_ENUMDNE) {
+ if ((gintsts & USB_OTG_GINTSTS_ENUMDNE) != 0) {
puts("enumeration done");
// Full speed, ENUMSPD
//puth(USBx_DEVICE->DSTS);
puts("\n");
}
- if (gintsts & USB_OTG_GINTSTS_OTGINT) {
+ if ((gintsts & USB_OTG_GINTSTS_OTGINT) != 0) {
puts("OTG int:");
puth(USBx->GOTGINT);
puts("\n");
@@ -786,7 +790,7 @@ void usb_irqhandler(void) {
}
// RX FIFO first
- if (gintsts & USB_OTG_GINTSTS_RXFLVL) {
+ if ((gintsts & USB_OTG_GINTSTS_RXFLVL) != 0) {
// 1. Read the Receive status pop register
volatile unsigned int rxst = USBx->GRXSTSP;
@@ -848,7 +852,7 @@ void usb_irqhandler(void) {
USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGONAK | USB_OTG_DCTL_CGINAK;
}
- if (gintsts & USB_OTG_GINTSTS_SRQINT) {
+ if ((gintsts & USB_OTG_GINTSTS_SRQINT) != 0) {
// we want to do "A-device host negotiation protocol" since we are the A-device
/*puts("start request\n");
puth(USBx->GOTGCTL);
@@ -859,7 +863,7 @@ void usb_irqhandler(void) {
}
// out endpoint hit
- if (gintsts & USB_OTG_GINTSTS_OEPINT) {
+ if ((gintsts & USB_OTG_GINTSTS_OEPINT) != 0) {
#ifdef DEBUG_USB
puts(" 0:");
puth(USBx_OUTEP(0)->DOEPINT);
@@ -874,7 +878,7 @@ void usb_irqhandler(void) {
puts(" OUT ENDPOINT\n");
#endif
- if (USBx_OUTEP(2)->DOEPINT & USB_OTG_DOEPINT_XFRC) {
+ if ((USBx_OUTEP(2)->DOEPINT & USB_OTG_DOEPINT_XFRC) != 0) {
#ifdef DEBUG_USB
puts(" OUT2 PACKET XFRC\n");
#endif
@@ -882,32 +886,32 @@ void usb_irqhandler(void) {
USBx_OUTEP(2)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
}
- if (USBx_OUTEP(3)->DOEPINT & USB_OTG_DOEPINT_XFRC) {
+ if ((USBx_OUTEP(3)->DOEPINT & USB_OTG_DOEPINT_XFRC) != 0) {
#ifdef DEBUG_USB
puts(" OUT3 PACKET XFRC\n");
#endif
USBx_OUTEP(3)->DOEPTSIZ = (1 << 19) | 0x40;
USBx_OUTEP(3)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
- } else if (USBx_OUTEP(3)->DOEPINT & 0x2000) {
+ } else if ((USBx_OUTEP(3)->DOEPINT & 0x2000) != 0) {
#ifdef DEBUG_USB
puts(" OUT3 PACKET WTF\n");
#endif
// if NAK was set trigger this, unknown interrupt
USBx_OUTEP(3)->DOEPTSIZ = (1 << 19) | 0x40;
USBx_OUTEP(3)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
- } else if (USBx_OUTEP(3)->DOEPINT) {
+ } else if ((USBx_OUTEP(3)->DOEPINT) != 0) {
puts("OUTEP3 error ");
puth(USBx_OUTEP(3)->DOEPINT);
puts("\n");
}
- if (USBx_OUTEP(0)->DOEPINT & USB_OTG_DIEPINT_XFRC) {
+ if ((USBx_OUTEP(0)->DOEPINT & USB_OTG_DIEPINT_XFRC) != 0) {
// ready for next packet
USBx_OUTEP(0)->DOEPTSIZ = USB_OTG_DOEPTSIZ_STUPCNT | (USB_OTG_DOEPTSIZ_PKTCNT & (1 << 19)) | (1 * 8);
}
// respond to setup packets
- if (USBx_OUTEP(0)->DOEPINT & USB_OTG_DOEPINT_STUP) {
+ if ((USBx_OUTEP(0)->DOEPINT & USB_OTG_DOEPINT_STUP) != 0) {
usb_setup();
}
@@ -917,7 +921,7 @@ void usb_irqhandler(void) {
}
// interrupt endpoint hit (Page 1221)
- if (gintsts & USB_OTG_GINTSTS_IEPINT) {
+ if ((gintsts & USB_OTG_GINTSTS_IEPINT) != 0) {
#ifdef DEBUG_USB
puts(" ");
puth(USBx_INEP(0)->DIEPINT);
@@ -932,8 +936,8 @@ void usb_irqhandler(void) {
// No need to set NAK in OTG_DIEPCTL0 when nothing to send,
// Appears USB core automatically sets NAK. WritePacket clears it.
- // Handle the two interface alternate settings. Setting 0 is has
- // EP1 as bulk. Setting 1 has EP1 as interrupt. The code to handle
+ // Handle the two interface alternate settings. Setting 0 has EP1
+ // as bulk. Setting 1 has EP1 as interrupt. The code to handle
// these two EP variations are very similar and can be
// restructured for smaller code footprint. Keeping split out for
// now for clarity.
@@ -942,7 +946,7 @@ void usb_irqhandler(void) {
switch (current_int0_alt_setting) {
case 0: ////// Bulk config
// *** IN token received when TxFIFO is empty
- if (USBx_INEP(1)->DIEPINT & USB_OTG_DIEPMSK_ITTXFEMSK) {
+ if ((USBx_INEP(1)->DIEPINT & USB_OTG_DIEPMSK_ITTXFEMSK) != 0) {
#ifdef DEBUG_USB
puts(" IN PACKET QUEUE\n");
#endif
@@ -953,7 +957,7 @@ void usb_irqhandler(void) {
case 1: ////// Interrupt config
// *** IN token received when TxFIFO is empty
- if (USBx_INEP(1)->DIEPINT & USB_OTG_DIEPMSK_ITTXFEMSK) {
+ if ((USBx_INEP(1)->DIEPINT & USB_OTG_DIEPMSK_ITTXFEMSK) != 0) {
#ifdef DEBUG_USB
puts(" IN PACKET QUEUE\n");
#endif
@@ -964,15 +968,18 @@ void usb_irqhandler(void) {
}
}
break;
+ default:
+ puts("current_int0_alt_setting value invalid\n");
+ break;
}
- if (USBx_INEP(0)->DIEPINT & USB_OTG_DIEPMSK_ITTXFEMSK) {
+ if ((USBx_INEP(0)->DIEPINT & USB_OTG_DIEPMSK_ITTXFEMSK) != 0) {
#ifdef DEBUG_USB
puts(" IN PACKET QUEUE\n");
#endif
- if (ep0_txlen != 0 && (USBx_INEP(0)->DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV) >= 0x40) {
- uint16_t len = min(ep0_txlen, 0x40);
+ if ((ep0_txlen != 0) && ((USBx_INEP(0)->DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV) >= 0x40)) {
+ uint16_t len = MIN(ep0_txlen, 0x40);
USB_WritePacket(ep0_txdata, len, 0);
ep0_txdata += len;
ep0_txlen -= len;
diff --git a/panda/board/gpio.h b/panda/board/gpio.h
index 7ba0dff58..26a82d627 100644
--- a/panda/board/gpio.h
+++ b/panda/board/gpio.h
@@ -13,23 +13,25 @@
#define PULL_EFFECTIVE_DELAY 10
-int has_external_debug_serial = 0;
-int is_giant_panda = 0;
-int is_entering_bootmode = 0;
-int revision = PANDA_REV_AB;
-int is_grey_panda = 0;
+void puts(const char *a);
-int detect_with_pull(GPIO_TypeDef *GPIO, int pin, int mode) {
+bool has_external_debug_serial = 0;
+bool is_giant_panda = 0;
+bool is_entering_bootmode = 0;
+int revision = PANDA_REV_AB;
+bool is_grey_panda = 0;
+
+bool detect_with_pull(GPIO_TypeDef *GPIO, int pin, int mode) {
set_gpio_mode(GPIO, pin, MODE_INPUT);
set_gpio_pullup(GPIO, pin, mode);
for (volatile int i=0; iAHB1ENR |= RCC_AHB1ENR_GPIOAEN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
@@ -97,7 +99,7 @@ void periph_init() {
// ********************* setters *********************
-void set_can_enable(CAN_TypeDef *CAN, int enabled) {
+void set_can_enable(CAN_TypeDef *CAN, bool enabled) {
// enable CAN busses
if (CAN == CAN1) {
#ifdef PANDA
@@ -139,16 +141,16 @@ void set_can_enable(CAN_TypeDef *CAN, int enabled) {
#endif
void set_led(int led_num, int on) {
- if (led_num == -1) return;
-
+ if (led_num != -1) {
#ifdef PANDA
set_gpio_output(GPIOC, led_num, !on);
#else
set_gpio_output(GPIOB, led_num, !on);
#endif
+ }
}
-void set_can_mode(int can, int use_gmlan) {
+void set_can_mode(int can, bool use_gmlan) {
// connects to CAN2 xcvr or GMLAN xcvr
if (use_gmlan) {
if (can == 1) {
@@ -200,6 +202,7 @@ void set_can_mode(int can, int use_gmlan) {
int usb_power_mode = USB_POWER_NONE;
void set_usb_power_mode(int mode) {
+ bool valid_mode = true;
switch (mode) {
case USB_POWER_CLIENT:
// B2,A13: set client mode
@@ -216,8 +219,15 @@ void set_usb_power_mode(int mode) {
set_gpio_output(GPIOB, 2, 0);
set_gpio_output(GPIOA, 13, 0);
break;
+ default:
+ valid_mode = false;
+ puts("Invalid usb power mode\n");
+ break;
+ }
+
+ if (valid_mode) {
+ usb_power_mode = mode;
}
- usb_power_mode = mode;
}
#define ESP_DISABLED 0
@@ -240,13 +250,16 @@ void set_esp_mode(int mode) {
set_gpio_output(GPIOC, 14, 1);
set_gpio_output(GPIOC, 5, 0);
break;
+ default:
+ puts("Invalid esp mode\n");
+ break;
}
}
// ********************* big init function *********************
// board specific
-void gpio_init() {
+void gpio_init(void) {
// pull low to hold ESP in reset??
// enable OTG out tied to ground
GPIOA->ODR = 0;
@@ -366,7 +379,7 @@ void gpio_init() {
extern void *g_pfnVectors;
extern uint32_t enter_bootloader_mode;
-void jump_to_bootloader() {
+void jump_to_bootloader(void) {
// do enter bootloader
enter_bootloader_mode = 0;
void (*bootloader)(void) = (void (*)(void)) (*((uint32_t *)0x1fff0004));
@@ -379,11 +392,11 @@ void jump_to_bootloader() {
NVIC_SystemReset();
}
-void early() {
+void early(void) {
// after it's been in the bootloader, things are initted differently, so we reset
- if (enter_bootloader_mode != BOOT_NORMAL &&
- enter_bootloader_mode != ENTER_BOOTLOADER_MAGIC &&
- enter_bootloader_mode != ENTER_SOFTLOADER_MAGIC) {
+ if ((enter_bootloader_mode != BOOT_NORMAL) &&
+ (enter_bootloader_mode != ENTER_BOOTLOADER_MAGIC) &&
+ (enter_bootloader_mode != ENTER_SOFTLOADER_MAGIC)) {
enter_bootloader_mode = BOOT_NORMAL;
NVIC_SystemReset();
}
diff --git a/panda/board/libc.h b/panda/board/libc.h
index 8d80a3aad..564d29cd8 100644
--- a/panda/board/libc.h
+++ b/panda/board/libc.h
@@ -1,12 +1,12 @@
-// **** shitty libc ****
+// **** libc ****
void delay(int a) {
volatile int i;
- for (i=0;iIDR & (1 << 1)) == 0;
+ return (GPIOA->IDR & (1U << 1)) == 0;
}
-void EXTI1_IRQHandler() {
- volatile int pr = EXTI->PR & (1 << 1);
- if (pr & (1 << 1)) {
+void EXTI1_IRQHandler(void) {
+ volatile int pr = EXTI->PR & (1U << 1);
+ if ((pr & (1U << 1)) != 0) {
#ifdef DEBUG
puts("got started interrupt\n");
#endif
@@ -77,20 +80,17 @@ void EXTI1_IRQHandler() {
delay(100000);
// set power savings mode here
- if (is_gpio_started() == 1) {
- power_save_disable();
- } else {
- power_save_enable();
- }
- EXTI->PR = (1 << 1);
+ int power_save_state = is_gpio_started() ? POWER_SAVE_STATUS_DISABLED : POWER_SAVE_STATUS_ENABLED;
+ set_power_save_state(power_save_state);
+ EXTI->PR = (1U << 1);
}
}
-void started_interrupt_init() {
+void started_interrupt_init(void) {
SYSCFG->EXTICR[1] = SYSCFG_EXTICR1_EXTI1_PA;
- EXTI->IMR |= (1 << 1);
- EXTI->RTSR |= (1 << 1);
- EXTI->FTSR |= (1 << 1);
+ EXTI->IMR |= (1U << 1);
+ EXTI->RTSR |= (1U << 1);
+ EXTI->FTSR |= (1U << 1);
NVIC_EnableIRQ(EXTI1_IRQn);
}
@@ -139,25 +139,34 @@ int get_health_pkt(void *dat) {
return sizeof(*health);
}
-int usb_cb_ep1_in(uint8_t *usbdata, int len, int hardwired) {
+int usb_cb_ep1_in(uint8_t *usbdata, int len, bool hardwired) {
+ UNUSED(hardwired);
CAN_FIFOMailBox_TypeDef *reply = (CAN_FIFOMailBox_TypeDef *)usbdata;
int ilen = 0;
- while (ilen < min(len/0x10, 4) && can_pop(&can_rx_q, &reply[ilen])) ilen++;
+ while (ilen < MIN(len/0x10, 4) && can_pop(&can_rx_q, &reply[ilen])) {
+ ilen++;
+ }
return ilen*0x10;
}
// send on serial, first byte to select the ring
-void usb_cb_ep2_out(uint8_t *usbdata, int len, int hardwired) {
- if (len == 0) return;
+void usb_cb_ep2_out(uint8_t *usbdata, int len, bool hardwired) {
+ UNUSED(hardwired);
uart_ring *ur = get_ring_by_number(usbdata[0]);
- if (!ur) return;
- if ((usbdata[0] < 2) || safety_tx_lin_hook(usbdata[0]-2, usbdata+1, len-1)) {
- for (int i = 1; i < len; i++) while (!putc(ur, usbdata[i]));
+ if ((len != 0) && (ur != NULL)) {
+ if ((usbdata[0] < 2) || safety_tx_lin_hook(usbdata[0]-2, usbdata+1, len-1)) {
+ for (int i = 1; i < len; i++) {
+ while (!putc(ur, usbdata[i])) {
+ // wait
+ }
+ }
+ }
}
}
// send on CAN
-void usb_cb_ep3_out(uint8_t *usbdata, int len, int hardwired) {
+void usb_cb_ep3_out(uint8_t *usbdata, int len, bool hardwired) {
+ UNUSED(hardwired);
int dpkt = 0;
for (dpkt = 0; dpkt < len; dpkt += 0x10) {
uint32_t *tf = (uint32_t*)(&usbdata[dpkt]);
@@ -174,14 +183,14 @@ void usb_cb_ep3_out(uint8_t *usbdata, int len, int hardwired) {
}
}
-int is_enumerated = 0;
+bool is_enumerated = 0;
void usb_cb_enumeration_complete() {
puts("USB enumeration complete\n");
is_enumerated = 1;
}
-int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) {
+int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired) {
int resp_len = 0;
uart_ring *ur = NULL;
int i;
@@ -227,6 +236,9 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) {
enter_bootloader_mode = ENTER_SOFTLOADER_MAGIC;
NVIC_SystemReset();
break;
+ default:
+ puts("Bootloader mode invalid\n");
+ break;
}
break;
// **** 0xd2: get health packet
@@ -235,7 +247,7 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) {
break;
// **** 0xd6: get version
case 0xd6:
- COMPILE_TIME_ASSERT(sizeof(gitversion) <= MAX_RESP_LEN)
+ COMPILE_TIME_ASSERT(sizeof(gitversion) <= MAX_RESP_LEN);
memcpy(resp, gitversion, sizeof(gitversion));
resp_len = sizeof(gitversion)-1;
break;
@@ -288,7 +300,7 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) {
if (safety_ignition_hook() != -1) {
// if the ignition hook depends on something other than the started GPIO
// we have to disable power savings (fix for GM and Tesla)
- power_save_disable();
+ set_power_save_state(POWER_SAVE_STATUS_DISABLED);
}
#ifndef EON
// always LIVE on EON
@@ -334,10 +346,14 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) {
// **** 0xe0: uart read
case 0xe0:
ur = get_ring_by_number(setup->b.wValue.w);
- if (!ur) break;
- if (ur == &esp_ring) uart_dma_drain();
+ if (!ur) {
+ break;
+ }
+ if (ur == &esp_ring) {
+ uart_dma_drain();
+ }
// read
- while ((resp_len < min(setup->b.wLength.w, MAX_RESP_LEN)) &&
+ while ((resp_len < MIN(setup->b.wLength.w, MAX_RESP_LEN)) &&
getc(ur, (char*)&resp[resp_len])) {
++resp_len;
}
@@ -345,13 +361,17 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) {
// **** 0xe1: uart set baud rate
case 0xe1:
ur = get_ring_by_number(setup->b.wValue.w);
- if (!ur) break;
+ if (!ur) {
+ break;
+ }
uart_set_baud(ur->uart, setup->b.wIndex.w);
break;
// **** 0xe2: uart set parity
case 0xe2:
ur = get_ring_by_number(setup->b.wValue.w);
- if (!ur) break;
+ if (!ur) {
+ break;
+ }
switch (setup->b.wIndex.w) {
case 0:
// disable parity, 8-bit
@@ -374,7 +394,9 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) {
// **** 0xe4: uart set baud rate extended
case 0xe4:
ur = get_ring_by_number(setup->b.wValue.w);
- if (!ur) break;
+ if (!ur) {
+ break;
+ }
uart_set_baud(ur->uart, (int)setup->b.wIndex.w*300);
break;
// **** 0xe5: set CAN loopback (for testing)
@@ -398,11 +420,11 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) {
// **** 0xf0: do k-line wValue pulse on uart2 for Acura
case 0xf0:
if (setup->b.wValue.w == 1) {
- GPIOC->ODR &= ~(1 << 10);
+ GPIOC->ODR &= ~(1U << 10);
GPIOC->MODER &= ~GPIO_MODER_MODER10_1;
GPIOC->MODER |= GPIO_MODER_MODER10_0;
} else {
- GPIOC->ODR &= ~(1 << 12);
+ GPIOC->ODR &= ~(1U << 12);
GPIOC->MODER &= ~GPIO_MODER_MODER12_1;
GPIOC->MODER |= GPIO_MODER_MODER12_0;
}
@@ -410,11 +432,11 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) {
for (i = 0; i < 80; i++) {
delay(8000);
if (setup->b.wValue.w == 1) {
- GPIOC->ODR |= (1 << 10);
- GPIOC->ODR &= ~(1 << 10);
+ GPIOC->ODR |= (1U << 10);
+ GPIOC->ODR &= ~(1U << 10);
} else {
- GPIOC->ODR |= (1 << 12);
- GPIOC->ODR &= ~(1 << 12);
+ GPIOC->ODR |= (1U << 12);
+ GPIOC->ODR &= ~(1U << 12);
}
}
@@ -442,7 +464,7 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) {
case 0xf2:
{
uart_ring * rb = get_ring_by_number(setup->b.wValue.w);
- if (rb) {
+ if (rb != NULL) {
puts("Clearing UART queue.\n");
clear_uart_buff(rb);
}
@@ -461,7 +483,7 @@ int spi_cb_rx(uint8_t *data, int len, uint8_t *data_out) {
// data[0] = endpoint
// data[2] = length
// data[4:] = data
-
+ UNUSED(len);
int resp_len = 0;
switch (data[0]) {
case 0:
@@ -480,6 +502,9 @@ int spi_cb_rx(uint8_t *data, int len, uint8_t *data_out) {
// ep 3, send CAN
usb_cb_ep3_out(data+4, data[2], 0);
break;
+ default:
+ puts("SPI data invalid");
+ break;
}
return resp_len;
}
@@ -487,20 +512,20 @@ int spi_cb_rx(uint8_t *data, int len, uint8_t *data_out) {
// ***************************** main code *****************************
-void __initialize_hardware_early() {
+void __initialize_hardware_early(void) {
early();
}
-void __attribute__ ((noinline)) enable_fpu() {
+void __attribute__ ((noinline)) enable_fpu(void) {
// enable the FPU
- SCB->CPACR |= ((3UL << (10 * 2)) | (3UL << (11 * 2)));
+ SCB->CPACR |= ((3UL << (10U * 2)) | (3UL << (11U * 2)));
}
uint64_t tcnt = 0;
uint64_t marker = 0;
// called once per second
-void TIM3_IRQHandler() {
+void TIM3_IRQHandler(void) {
#define CURRENT_THRESHOLD 0xF00
#define CLICKS 5 // 5 seconds to switch modes
@@ -559,6 +584,9 @@ void TIM3_IRQHandler() {
marker = tcnt;
}
break;
+ default:
+ puts("USB power mode invalid\n"); // set_usb_power_mode prevents assigning invalid values
+ break;
}
// ~0x9a = 500 ma
@@ -566,8 +594,9 @@ void TIM3_IRQHandler() {
puts("\n");*/
// reset this every 16th pass
- if ((tcnt&0xF) == 0) pending_can_live = 0;
-
+ if ((tcnt&0xF) == 0) {
+ pending_can_live = 0;
+ }
#ifdef DEBUG
puts("** blink ");
puth(can_rx_q.r_ptr); puts(" "); puth(can_rx_q.w_ptr); puts(" ");
@@ -580,7 +609,7 @@ void TIM3_IRQHandler() {
// turn off the blue LED, turned on by CAN
// unless we are in power saving mode
- set_led(LED_BLUE, (tcnt&1) && power_save_status == POWER_SAVE_STATUS_ENABLED);
+ set_led(LED_BLUE, (tcnt & 1) && (power_save_status == POWER_SAVE_STATUS_ENABLED));
// on to the next one
tcnt += 1;
@@ -588,7 +617,7 @@ void TIM3_IRQHandler() {
TIM3->SR = 0;
}
-int main() {
+int main(void) {
// shouldn't have interrupts here, but just in case
__disable_irq();
@@ -609,7 +638,9 @@ int main() {
puts(is_entering_bootmode ? " ESP wants bootmode\n" : " no bootmode\n");
// non rev c panda are no longer supported
- while (revision != PANDA_REV_C);
+ while (revision != PANDA_REV_C) {
+ // hang
+ }
gpio_init();
@@ -659,7 +690,10 @@ int main() {
can_init_all();
adc_init();
+
+#ifndef EON
spi_init();
+#endif
#ifdef EON
// have to save power
@@ -667,8 +701,8 @@ int main() {
set_esp_mode(ESP_DISABLED);
}
// only enter power save after the first cycle
- /*if (is_gpio_started() == 0) {
- power_save_enable();
+ /*if (is_gpio_started()) {
+ set_power_save_state(POWER_SAVE_STATUS_ENABLED);
}*/
// interrupt on started line
started_interrupt_init();
@@ -683,8 +717,7 @@ int main() {
#endif
puts("**** INTERRUPTS ON ****\n");
-
- __enable_irq();
+ enable_interrupts();
// LED should keep on blinking all the time
uint64_t cnt = 0;
diff --git a/panda/board/pedal/main.c b/panda/board/pedal/main.c
index df3219e32..4656db283 100644
--- a/panda/board/pedal/main.c
+++ b/panda/board/pedal/main.c
@@ -19,7 +19,7 @@
#include "drivers/usb.h"
#else
// no serial either
- int puts(const char *a) { return 0; }
+ void puts(const char *a) {}
void puth(unsigned int i) {}
#endif
@@ -41,12 +41,12 @@ void debug_ring_callback(uart_ring *ring) {
}
}
-int usb_cb_ep1_in(uint8_t *usbdata, int len, int hardwired) { return 0; }
-void usb_cb_ep2_out(uint8_t *usbdata, int len, int hardwired) {}
-void usb_cb_ep3_out(uint8_t *usbdata, int len, int hardwired) {}
+int usb_cb_ep1_in(uint8_t *usbdata, int len, bool hardwired) { return 0; }
+void usb_cb_ep2_out(uint8_t *usbdata, int len, bool hardwired) {}
+void usb_cb_ep3_out(uint8_t *usbdata, int len, bool hardwired) {}
void usb_cb_enumeration_complete() {}
-int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) {
+int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired) {
int resp_len = 0;
uart_ring *ur = NULL;
switch (setup->b.bRequest) {
@@ -56,7 +56,7 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) {
if (!ur) break;
if (ur == &esp_ring) uart_dma_drain();
// read
- while ((resp_len < min(setup->b.wLength.w, MAX_RESP_LEN)) &&
+ while ((resp_len < MIN(setup->b.wLength.w, MAX_RESP_LEN)) &&
getc(ur, (char*)&resp[resp_len])) {
++resp_len;
}
@@ -246,8 +246,8 @@ void pedal() {
// write the pedal to the DAC
if (state == NO_FAULT) {
- dac_set(0, max(gas_set_0, pdl0));
- dac_set(1, max(gas_set_1, pdl1));
+ dac_set(0, MAX(gas_set_0, pdl0));
+ dac_set(1, MAX(gas_set_1, pdl1));
} else {
dac_set(0, pdl0);
dac_set(1, pdl1);
diff --git a/panda/board/power_saving.h b/panda/board/power_saving.h
index 3f40bce28..986adf3ce 100644
--- a/panda/board/power_saving.h
+++ b/panda/board/power_saving.h
@@ -3,55 +3,41 @@
int power_save_status = POWER_SAVE_STATUS_DISABLED;
-void power_save_enable(void) {
- if (power_save_status == POWER_SAVE_STATUS_ENABLED) return;
- puts("enable power savings\n");
+void set_power_save_state(int state) {
- // turn off can
- set_can_enable(CAN1, 0);
- set_can_enable(CAN2, 0);
- set_can_enable(CAN3, 0);
+ bool is_valid_state = (state == POWER_SAVE_STATUS_ENABLED) || (state == POWER_SAVE_STATUS_DISABLED);
+ if (is_valid_state && (state != power_save_status)) {
+ bool enable = false;
+ if (state == POWER_SAVE_STATUS_ENABLED) {
+ puts("enable power savings\n");
+ if (is_grey_panda) {
+ char UBLOX_SLEEP_MSG[] = "\xb5\x62\x06\x04\x04\x00\x01\x00\x08\x00\x17\x78";
+ uart_ring *ur = get_ring_by_number(1);
+ for (unsigned int i = 0; i < sizeof(UBLOX_SLEEP_MSG) - 1; i++) while (!putc(ur, UBLOX_SLEEP_MSG[i]));
+ }
+ } else {
+ puts("disable power savings\n");
+ if (is_grey_panda) {
+ char UBLOX_WAKE_MSG[] = "\xb5\x62\x06\x04\x04\x00\x01\x00\x09\x00\x18\x7a";
+ uart_ring *ur = get_ring_by_number(1);
+ for (unsigned int i = 0; i < sizeof(UBLOX_WAKE_MSG) - 1; i++) while (!putc(ur, UBLOX_WAKE_MSG[i]));
+ }
+ enable = true;
+ }
- // turn off GMLAN
- set_gpio_output(GPIOB, 14, 0);
- set_gpio_output(GPIOB, 15, 0);
+ // turn on can
+ set_can_enable(CAN1, enable);
+ set_can_enable(CAN2, enable);
+ set_can_enable(CAN3, enable);
- // turn off LIN
- set_gpio_output(GPIOB, 7, 0);
- set_gpio_output(GPIOA, 14, 0);
+ // turn on GMLAN
+ set_gpio_output(GPIOB, 14, enable);
+ set_gpio_output(GPIOB, 15, enable);
- if (is_grey_panda) {
- char UBLOX_SLEEP_MSG[] = "\xb5\x62\x06\x04\x04\x00\x01\x00\x08\x00\x17\x78";
- uart_ring *ur = get_ring_by_number(1);
- for (int i = 0; i < sizeof(UBLOX_SLEEP_MSG)-1; i++) while (!putc(ur, UBLOX_SLEEP_MSG[i]));
+ // turn on LIN
+ set_gpio_output(GPIOB, 7, enable);
+ set_gpio_output(GPIOA, 14, enable);
+
+ power_save_status = state;
}
-
- power_save_status = POWER_SAVE_STATUS_ENABLED;
}
-
-void power_save_disable(void) {
- if (power_save_status == POWER_SAVE_STATUS_DISABLED) return;
- puts("disable power savings\n");
-
- // turn on can
- set_can_enable(CAN1, 1);
- set_can_enable(CAN2, 1);
- set_can_enable(CAN3, 1);
-
- // turn on GMLAN
- set_gpio_output(GPIOB, 14, 1);
- set_gpio_output(GPIOB, 15, 1);
-
- // turn on LIN
- set_gpio_output(GPIOB, 7, 1);
- set_gpio_output(GPIOA, 14, 1);
-
- if (is_grey_panda) {
- char UBLOX_WAKE_MSG[] = "\xb5\x62\x06\x04\x04\x00\x01\x00\x09\x00\x18\x7a";
- uart_ring *ur = get_ring_by_number(1);
- for (int i = 0; i < sizeof(UBLOX_WAKE_MSG)-1; i++) while (!putc(ur, UBLOX_WAKE_MSG[i]));
- }
-
- power_save_status = POWER_SAVE_STATUS_DISABLED;
-}
-
diff --git a/panda/board/safety.h b/panda/board/safety.h
index 3addc6536..dd99e6db2 100644
--- a/panda/board/safety.h
+++ b/panda/board/safety.h
@@ -1,56 +1,5 @@
-// sample struct that keeps 3 samples in memory
-struct sample_t {
- int values[6];
- int min;
- int max;
-} sample_t_default = {{0}, 0, 0};
-
-// safety code requires floats
-struct lookup_t {
- float x[3];
- float y[3];
-};
-
-void safety_rx_hook(CAN_FIFOMailBox_TypeDef *to_push);
-int safety_tx_hook(CAN_FIFOMailBox_TypeDef *to_send);
-int safety_tx_lin_hook(int lin_num, uint8_t *data, int len);
-int safety_ignition_hook();
-uint32_t get_ts_elapsed(uint32_t ts, uint32_t ts_last);
-int to_signed(int d, int bits);
-void update_sample(struct sample_t *sample, int sample_new);
-int max_limit_check(int val, const int MAX, const int MIN);
-int dist_to_meas_check(int val, int val_last, struct sample_t *val_meas,
- const int MAX_RATE_UP, const int MAX_RATE_DOWN, const int MAX_ERROR);
-int driver_limit_check(int val, int val_last, struct sample_t *val_driver,
- const int MAX, const int MAX_RATE_UP, const int MAX_RATE_DOWN,
- const int MAX_ALLOWANCE, const int DRIVER_FACTOR);
-int rt_rate_limit_check(int val, int val_last, const int MAX_RT_DELTA);
-float interpolate(struct lookup_t xy, float x);
-
-typedef void (*safety_hook_init)(int16_t param);
-typedef void (*rx_hook)(CAN_FIFOMailBox_TypeDef *to_push);
-typedef int (*tx_hook)(CAN_FIFOMailBox_TypeDef *to_send);
-typedef int (*tx_lin_hook)(int lin_num, uint8_t *data, int len);
-typedef int (*ign_hook)();
-typedef int (*fwd_hook)(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd);
-
-typedef struct {
- safety_hook_init init;
- ign_hook ignition;
- rx_hook rx;
- tx_hook tx;
- tx_lin_hook tx_lin;
- fwd_hook fwd;
-} safety_hooks;
-
-// This can be set by the safety hooks.
-int controls_allowed = 0;
-int gas_interceptor_detected = 0;
-int gas_interceptor_prev = 0;
-
-// This is set by USB command 0xdf
-int long_controls_allowed = 1;
-
+// include first, needed by safety policies
+#include "safety_declarations.h"
// Include the actual safety policies.
#include "safety/safety_defaults.h"
#include "safety/safety_honda.h"
@@ -129,83 +78,94 @@ const safety_hook_config safety_hook_registry[] = {
{SAFETY_ELM327, &elm327_hooks},
};
-#define HOOK_CONFIG_COUNT (sizeof(safety_hook_registry)/sizeof(safety_hook_config))
-
int safety_set_mode(uint16_t mode, int16_t param) {
- for (int i = 0; i < HOOK_CONFIG_COUNT; i++) {
+ int set_status = -1; // not set
+ int hook_config_count = sizeof(safety_hook_registry) / sizeof(safety_hook_config);
+ for (int i = 0; i < hook_config_count; i++) {
if (safety_hook_registry[i].id == mode) {
current_hooks = safety_hook_registry[i].hooks;
- if (current_hooks->init) current_hooks->init(param);
- return 0;
+ set_status = 0; // set
+ break;
}
}
- return -1;
+ if ((set_status == 0) && (current_hooks->init != NULL)) {
+ current_hooks->init(param);
+ }
+ return set_status;
}
// compute the time elapsed (in microseconds) from 2 counter samples
+// case where ts < ts_last is ok: overflow is properly re-casted into uint32_t
uint32_t get_ts_elapsed(uint32_t ts, uint32_t ts_last) {
- return ts > ts_last ? ts - ts_last : (0xFFFFFFFF - ts_last) + 1 + ts;
+ return ts - ts_last;
}
// convert a trimmed integer to signed 32 bit int
int to_signed(int d, int bits) {
- if (d >= (1 << (bits - 1))) {
- d -= (1 << bits);
+ int d_signed = d;
+ if (d >= (1 << MAX((bits - 1), 0))) {
+ d_signed = d - (1 << MAX(bits, 0));
}
- return d;
+ return d_signed;
}
// given a new sample, update the smaple_t struct
void update_sample(struct sample_t *sample, int sample_new) {
- for (int i = sizeof(sample->values)/sizeof(sample->values[0]) - 1; i > 0; i--) {
+ int sample_size = sizeof(sample->values) / sizeof(sample->values[0]);
+ for (int i = sample_size - 1; i > 0; i--) {
sample->values[i] = sample->values[i-1];
}
sample->values[0] = sample_new;
// get the minimum and maximum measured samples
- sample->min = sample->max = sample->values[0];
- for (int i = 1; i < sizeof(sample->values)/sizeof(sample->values[0]); i++) {
- if (sample->values[i] < sample->min) sample->min = sample->values[i];
- if (sample->values[i] > sample->max) sample->max = sample->values[i];
+ sample->min = sample->values[0];
+ sample->max = sample->values[0];
+ for (int i = 1; i < sample_size; i++) {
+ if (sample->values[i] < sample->min) {
+ sample->min = sample->values[i];
+ }
+ if (sample->values[i] > sample->max) {
+ sample->max = sample->values[i];
+ }
}
}
-int max_limit_check(int val, const int MAX, const int MIN) {
- return (val > MAX) || (val < MIN);
+bool max_limit_check(int val, const int MAX_VAL, const int MIN_VAL) {
+ return (val > MAX_VAL) || (val < MIN_VAL);
}
// check that commanded value isn't too far from measured
-int dist_to_meas_check(int val, int val_last, struct sample_t *val_meas,
+bool dist_to_meas_check(int val, int val_last, struct sample_t *val_meas,
const int MAX_RATE_UP, const int MAX_RATE_DOWN, const int MAX_ERROR) {
// *** val rate limit check ***
- int highest_allowed_val = max(val_last, 0) + MAX_RATE_UP;
- int lowest_allowed_val = min(val_last, 0) - MAX_RATE_UP;
+ int highest_allowed_rl = MAX(val_last, 0) + MAX_RATE_UP;
+ int lowest_allowed_rl = MIN(val_last, 0) - MAX_RATE_UP;
// if we've exceeded the meas val, we must start moving toward 0
- highest_allowed_val = min(highest_allowed_val, max(val_last - MAX_RATE_DOWN, max(val_meas->max, 0) + MAX_ERROR));
- lowest_allowed_val = max(lowest_allowed_val, min(val_last + MAX_RATE_DOWN, min(val_meas->min, 0) - MAX_ERROR));
+ int highest_allowed = MIN(highest_allowed_rl, MAX(val_last - MAX_RATE_DOWN, MAX(val_meas->max, 0) + MAX_ERROR));
+ int lowest_allowed = MAX(lowest_allowed_rl, MIN(val_last + MAX_RATE_DOWN, MIN(val_meas->min, 0) - MAX_ERROR));
// check for violation
- return (val < lowest_allowed_val) || (val > highest_allowed_val);
+ return (val < lowest_allowed) || (val > highest_allowed);
}
// check that commanded value isn't fighting against driver
-int driver_limit_check(int val, int val_last, struct sample_t *val_driver,
- const int MAX, const int MAX_RATE_UP, const int MAX_RATE_DOWN,
+bool driver_limit_check(int val, int val_last, struct sample_t *val_driver,
+ const int MAX_VAL, const int MAX_RATE_UP, const int MAX_RATE_DOWN,
const int MAX_ALLOWANCE, const int DRIVER_FACTOR) {
- int highest_allowed = max(val_last, 0) + MAX_RATE_UP;
- int lowest_allowed = min(val_last, 0) - MAX_RATE_UP;
+ int highest_allowed_rl = MAX(val_last, 0) + MAX_RATE_UP;
+ int lowest_allowed_rl = MIN(val_last, 0) - MAX_RATE_UP;
- int driver_max_limit = MAX + (MAX_ALLOWANCE + val_driver->max) * DRIVER_FACTOR;
- int driver_min_limit = -MAX + (-MAX_ALLOWANCE + val_driver->min) * DRIVER_FACTOR;
+ int driver_max_limit = MAX_VAL + (MAX_ALLOWANCE + val_driver->max) * DRIVER_FACTOR;
+ int driver_min_limit = -MAX_VAL + (-MAX_ALLOWANCE + val_driver->min) * DRIVER_FACTOR;
// if we've exceeded the applied torque, we must start moving toward 0
- highest_allowed = min(highest_allowed, max(val_last - MAX_RATE_DOWN,
- max(driver_max_limit, 0)));
- lowest_allowed = max(lowest_allowed, min(val_last + MAX_RATE_DOWN,
- min(driver_min_limit, 0)));
+ int highest_allowed = MIN(highest_allowed_rl, MAX(val_last - MAX_RATE_DOWN,
+ MAX(driver_max_limit, 0)));
+ int lowest_allowed = MAX(lowest_allowed_rl, MIN(val_last + MAX_RATE_DOWN,
+ MIN(driver_min_limit, 0)));
// check for violation
return (val < lowest_allowed) || (val > highest_allowed);
@@ -213,11 +173,11 @@ int driver_limit_check(int val, int val_last, struct sample_t *val_driver,
// real time check, mainly used for steer torque rate limiter
-int rt_rate_limit_check(int val, int val_last, const int MAX_RT_DELTA) {
+bool rt_rate_limit_check(int val, int val_last, const int MAX_RT_DELTA) {
// *** torque real time rate limit check ***
- int highest_val = max(val_last, 0) + MAX_RT_DELTA;
- int lowest_val = min(val_last, 0) - MAX_RT_DELTA;
+ int highest_val = MAX(val_last, 0) + MAX_RT_DELTA;
+ int lowest_val = MIN(val_last, 0) - MAX_RT_DELTA;
// check for violation
return (val < lowest_val) || (val > highest_val);
@@ -226,25 +186,30 @@ int rt_rate_limit_check(int val, int val_last, const int MAX_RT_DELTA) {
// interp function that holds extreme values
float interpolate(struct lookup_t xy, float x) {
+
int size = sizeof(xy.x) / sizeof(xy.x[0]);
+ float ret = xy.y[size - 1]; // default output is last point
+
// x is lower than the first point in the x array. Return the first point
if (x <= xy.x[0]) {
- return xy.y[0];
+ ret = xy.y[0];
} else {
// find the index such that (xy.x[i] <= x < xy.x[i+1]) and linearly interp
- for (int i=0; i < size-1; i++) {
+ for (int i=0; i < (size - 1); i++) {
if (x < xy.x[i+1]) {
float x0 = xy.x[i];
float y0 = xy.y[i];
float dx = xy.x[i+1] - x0;
float dy = xy.y[i+1] - y0;
// dx should not be zero as xy.x is supposed ot be monotonic
- if (dx <= 0.) dx = 0.0001;
- return dy * (x - x0) / dx + y0;
+ if (dx <= 0.) {
+ dx = 0.0001;
+ }
+ ret = (dy * (x - x0) / dx) + y0;
+ break;
}
}
- // if no such point is found, then x > xy.x[size-1]. Return last point
- return xy.y[size - 1];
}
+ return ret;
}
diff --git a/panda/board/safety/safety_cadillac.h b/panda/board/safety/safety_cadillac.h
index 2a2d8b985..ef114abfe 100644
--- a/panda/board/safety/safety_cadillac.h
+++ b/panda/board/safety/safety_cadillac.h
@@ -1,8 +1,10 @@
+#define CADILLAC_TORQUE_MSG_N 4 // 4 torque messages: 0x151, 0x152, 0x153, 0x154
+
const int CADILLAC_MAX_STEER = 150; // 1s
// real time torque limit to prevent controls spamming
// the real time limit is 1500/sec
const int CADILLAC_MAX_RT_DELTA = 75; // max delta torque allowed for real time checks
-const int32_t CADILLAC_RT_INTERVAL = 250000; // 250ms between real time checks
+const uint32_t CADILLAC_RT_INTERVAL = 250000; // 250ms between real time checks
const int CADILLAC_MAX_RATE_UP = 2;
const int CADILLAC_MAX_RATE_DOWN = 5;
const int CADILLAC_DRIVER_TORQUE_ALLOWANCE = 50;
@@ -11,21 +13,19 @@ const int CADILLAC_DRIVER_TORQUE_FACTOR = 4;
int cadillac_ign = 0;
int cadillac_cruise_engaged_last = 0;
int cadillac_rt_torque_last = 0;
-int cadillac_desired_torque_last[4] = {0}; // 4 torque messages
+const int cadillac_torque_msgs_n = 4;
+int cadillac_desired_torque_last[CADILLAC_TORQUE_MSG_N] = {0};
uint32_t cadillac_ts_last = 0;
int cadillac_supercruise_on = 0;
struct sample_t cadillac_torque_driver; // last few driver torques measured
-int cadillac_get_torque_idx(uint32_t addr) {
- if (addr==0x151) return 0;
- else if (addr==0x152) return 1;
- else if (addr==0x153) return 2;
- else return 3;
+int cadillac_get_torque_idx(int addr, int array_size) {
+ return MIN(MAX(addr - 0x151, 0), array_size); // 0x151 is id 0, 0x152 is id 1 and so on...
}
static void cadillac_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
- int bus_number = (to_push->RDTR >> 4) & 0xFF;
- uint32_t addr = to_push->RIR >> 21;
+ int bus = GET_BUS(to_push);
+ int addr = GET_ADDR(to_push);
if (addr == 356) {
int torque_driver_new = ((to_push->RDLR & 0x7) << 8) | ((to_push->RDLR >> 8) & 0xFF);
@@ -35,16 +35,17 @@ static void cadillac_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
}
// this message isn't all zeros when ignition is on
- if (addr == 0x160 && bus_number == 0) {
+ if ((addr == 0x160) && (bus == 0)) {
cadillac_ign = to_push->RDLR > 0;
}
// enter controls on rising edge of ACC, exit controls on ACC off
- if ((addr == 0x370) && (bus_number == 0)) {
+ if ((addr == 0x370) && (bus == 0)) {
int cruise_engaged = to_push->RDLR & 0x800000; // bit 23
if (cruise_engaged && !cadillac_cruise_engaged_last) {
controls_allowed = 1;
- } else if (!cruise_engaged) {
+ }
+ if (!cruise_engaged) {
controls_allowed = 0;
}
cadillac_cruise_engaged_last = cruise_engaged;
@@ -57,14 +58,15 @@ static void cadillac_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
}
static int cadillac_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
- uint32_t addr = to_send->RIR >> 21;
+ int tx = 1;
+ int addr = GET_ADDR(to_send);
// steer cmd checks
- if (addr == 0x151 || addr == 0x152 || addr == 0x153 || addr == 0x154) {
+ if ((addr == 0x151) || (addr == 0x152) || (addr == 0x153) || (addr == 0x154)) {
int desired_torque = ((to_send->RDLR & 0x3f) << 8) + ((to_send->RDLR & 0xff00) >> 8);
int violation = 0;
uint32_t ts = TIM2->CNT;
- int idx = cadillac_get_torque_idx(addr);
+ int idx = cadillac_get_torque_idx(addr, CADILLAC_TORQUE_MSG_N);
desired_torque = to_signed(desired_torque, 14);
if (controls_allowed) {
@@ -105,19 +107,20 @@ static int cadillac_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
}
if (violation || cadillac_supercruise_on) {
- return false;
+ tx = 0;
}
}
- return true;
+ return tx;
}
static void cadillac_init(int16_t param) {
+ UNUSED(param);
controls_allowed = 0;
cadillac_ign = 0;
}
-static int cadillac_ign_hook() {
+static int cadillac_ign_hook(void) {
return cadillac_ign;
}
@@ -127,5 +130,5 @@ const safety_hooks cadillac_hooks = {
.tx = cadillac_tx_hook,
.tx_lin = nooutput_tx_lin_hook,
.ignition = cadillac_ign_hook,
- .fwd = alloutput_fwd_hook,
+ .fwd = default_fwd_hook,
};
diff --git a/panda/board/safety/safety_chrysler.h b/panda/board/safety/safety_chrysler.h
index 4af588401..19149b6b7 100644
--- a/panda/board/safety/safety_chrysler.h
+++ b/panda/board/safety/safety_chrysler.h
@@ -1,11 +1,11 @@
const int CHRYSLER_MAX_STEER = 261;
const int CHRYSLER_MAX_RT_DELTA = 112; // max delta torque allowed for real time checks
-const int32_t CHRYSLER_RT_INTERVAL = 250000; // 250ms between real time checks
+const uint32_t CHRYSLER_RT_INTERVAL = 250000; // 250ms between real time checks
const int CHRYSLER_MAX_RATE_UP = 3;
const int CHRYSLER_MAX_RATE_DOWN = 3;
const int CHRYSLER_MAX_TORQUE_ERROR = 80; // max torque cmd in excess of torque motor
-int chrysler_camera_detected = 0; // is giraffe switch 2 high?
+bool chrysler_camera_detected = 0; // is giraffe switch 2 high?
int chrysler_rt_torque_last = 0;
int chrysler_desired_torque_last = 0;
int chrysler_cruise_engaged_last = 0;
@@ -13,40 +13,32 @@ uint32_t chrysler_ts_last = 0;
struct sample_t chrysler_torque_meas; // last few torques measured
static void chrysler_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
- int bus = (to_push->RDTR >> 4) & 0xFF;
- uint32_t addr;
- if (to_push->RIR & 4) {
- // Extended
- // Not looked at, but have to be separated
- // to avoid address collision
- addr = to_push->RIR >> 3;
- } else {
- // Normal
- addr = to_push->RIR >> 21;
- }
+ int bus = GET_BUS(to_push);
+ int addr = GET_ADDR(to_push);
// Measured eps torque
if (addr == 544) {
- int rdhr = to_push->RDHR;
- int torque_meas_new = ((rdhr & 0x7) << 8) + ((rdhr & 0xFF00) >> 8) - 1024;
+ uint32_t rdhr = to_push->RDHR;
+ int torque_meas_new = ((rdhr & 0x7U) << 8) + ((rdhr & 0xFF00U) >> 8) - 1024U;
// update array of samples
update_sample(&chrysler_torque_meas, torque_meas_new);
}
// enter controls on rising edge of ACC, exit controls on ACC off
- if (addr == 0x1f4) {
+ if (addr == 0x1F4) {
int cruise_engaged = ((to_push->RDLR & 0x380000) >> 19) == 7;
if (cruise_engaged && !chrysler_cruise_engaged_last) {
controls_allowed = 1;
- } else if (!cruise_engaged) {
+ }
+ if (!cruise_engaged) {
controls_allowed = 0;
}
chrysler_cruise_engaged_last = cruise_engaged;
}
// check if stock camera ECU is still online
- if (bus == 0 && addr == 0x292) {
+ if ((bus == 0) && (addr == 0x292)) {
chrysler_camera_detected = 1;
controls_allowed = 0;
}
@@ -54,27 +46,21 @@ static void chrysler_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
static int chrysler_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
- // There can be only one! (camera)
+ int tx = 1;
+
+ // If camera is on bus 0, then nothing can be sent
if (chrysler_camera_detected) {
- return 0;
- }
-
- uint32_t addr;
- if (to_send->RIR & 4) {
- // Extended
- addr = to_send->RIR >> 3;
- } else {
- // Normal
- addr = to_send->RIR >> 21;
+ tx = 0;
}
+ int addr = GET_ADDR(to_send);
// LKA STEER
if (addr == 0x292) {
- int rdlr = to_send->RDLR;
- int desired_torque = ((rdlr & 0x7) << 8) + ((rdlr & 0xFF00) >> 8) - 1024;
+ uint32_t rdlr = to_send->RDLR;
+ int desired_torque = ((rdlr & 0x7U) << 8) + ((rdlr & 0xFF00U) >> 8) - 1024U;
uint32_t ts = TIM2->CNT;
- int violation = 0;
+ bool violation = 0;
if (controls_allowed) {
@@ -112,7 +98,7 @@ static int chrysler_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
}
if (violation) {
- return false;
+ tx = 0;
}
}
@@ -122,24 +108,28 @@ static int chrysler_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
// TODO: fix bug preventing the button msg to be fwd'd on bus 2
// 1 allows the message through
- return true;
+ return tx;
}
static void chrysler_init(int16_t param) {
+ UNUSED(param);
+ controls_allowed = 0;
chrysler_camera_detected = 0;
}
static int chrysler_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
- int32_t addr = to_fwd->RIR >> 21;
+
+ int bus_fwd = -1;
+ int addr = GET_ADDR(to_fwd);
// forward CAN 0 -> 2 so stock LKAS camera sees messages
- if (bus_num == 0 && !chrysler_camera_detected) {
- return 2;
+ if ((bus_num == 0) && !chrysler_camera_detected) {
+ bus_fwd = 2;
}
// forward all messages from camera except LKAS_COMMAND and LKAS_HUD
- if (bus_num == 2 && !chrysler_camera_detected && addr != 658 && addr != 678) {
- return 0;
+ if ((bus_num == 2) && !chrysler_camera_detected && (addr != 658) && (addr != 678)) {
+ bus_fwd = 0;
}
- return -1; // do not forward
+ return bus_fwd;
}
diff --git a/panda/board/safety/safety_defaults.h b/panda/board/safety/safety_defaults.h
index 196df65d2..9dc23b54b 100644
--- a/panda/board/safety/safety_defaults.h
+++ b/panda/board/safety/safety_defaults.h
@@ -1,24 +1,33 @@
-void default_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {}
+void default_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
+ UNUSED(to_push);
+}
-int default_ign_hook() {
+int default_ign_hook(void) {
return -1; // use GPIO to determine ignition
}
// *** no output safety mode ***
static void nooutput_init(int16_t param) {
+ UNUSED(param);
controls_allowed = 0;
}
static int nooutput_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
+ UNUSED(to_send);
return false;
}
static int nooutput_tx_lin_hook(int lin_num, uint8_t *data, int len) {
+ UNUSED(lin_num);
+ UNUSED(data);
+ UNUSED(len);
return false;
}
-static int nooutput_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
+static int default_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
+ UNUSED(bus_num);
+ UNUSED(to_fwd);
return -1;
}
@@ -28,32 +37,33 @@ const safety_hooks nooutput_hooks = {
.tx = nooutput_tx_hook,
.tx_lin = nooutput_tx_lin_hook,
.ignition = default_ign_hook,
- .fwd = nooutput_fwd_hook,
+ .fwd = default_fwd_hook,
};
// *** all output safety mode ***
static void alloutput_init(int16_t param) {
+ UNUSED(param);
controls_allowed = 1;
}
static int alloutput_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
+ UNUSED(to_send);
return true;
}
static int alloutput_tx_lin_hook(int lin_num, uint8_t *data, int len) {
+ UNUSED(lin_num);
+ UNUSED(data);
+ UNUSED(len);
return true;
}
-static int alloutput_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
- return -1;
-}
-
const safety_hooks alloutput_hooks = {
.init = alloutput_init,
.rx = default_rx_hook,
.tx = alloutput_tx_hook,
.tx_lin = alloutput_tx_lin_hook,
.ignition = default_ign_hook,
- .fwd = alloutput_fwd_hook,
+ .fwd = default_fwd_hook,
};
diff --git a/panda/board/safety/safety_elm327.h b/panda/board/safety/safety_elm327.h
index 823d553dd..1f44e992a 100644
--- a/panda/board/safety/safety_elm327.h
+++ b/panda/board/safety/safety_elm327.h
@@ -1,28 +1,42 @@
static int elm327_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
- //All ELM traffic must appear on CAN0
- if(((to_send->RDTR >> 4) & 0xf) != 0) return 0;
- //All ISO 15765-4 messages must be 8 bytes long
- if((to_send->RDTR & 0xf) != 8) return 0;
- if(to_send->RIR & 4){
- uint32_t addr = to_send->RIR >> 3;
- //Check valid 29 bit send addresses for ISO 15765-4
- if(!(addr == 0x18DB33F1 || (addr & 0x1FFF00FF) == 0x18DA00F1)) return 0;
- } else {
- uint32_t addr = to_send->RIR >> 21;
- //Check valid 11 bit send addresses for ISO 15765-4
- if(!(addr == 0x7DF || (addr & 0x7F8) == 0x7E0)) return 0;
+ int tx = 1;
+ int bus = GET_BUS(to_send);
+ int addr = GET_ADDR(to_send);
+ int len = GET_LEN(to_send);
+
+ //All ELM traffic must appear on CAN0
+ if (bus != 0) {
+ tx = 0;
}
- return true;
+ //All ISO 15765-4 messages must be 8 bytes long
+ if (len != 8) {
+ tx = 0;
+ }
+
+ //Check valid 29 bit send addresses for ISO 15765-4
+ //Check valid 11 bit send addresses for ISO 15765-4
+ if ((addr != 0x18DB33F1) && ((addr & 0x1FFF00FF) != 0x18DA00F1) &&
+ ((addr != 0x7DF) && ((addr & 0x7F8) != 0x7E0))) {
+ tx = 0;
+ }
+ return tx;
}
static int elm327_tx_lin_hook(int lin_num, uint8_t *data, int len) {
- if(lin_num != 0) return false; //Only operate on LIN 0, aka serial 2
- if(len < 5 || len > 11) return false; //Valid KWP size
- if(!((data[0] & 0xF8) == 0xC0 && (data[0] & 0x07) > 0 &&
- data[1] == 0x33 && data[2] == 0xF1)) return false; //Bad msg
- return true;
+ int tx = 1;
+ if (lin_num != 0) {
+ tx = 0; //Only operate on LIN 0, aka serial 2
+ }
+ if ((len < 5) || (len > 11)) {
+ tx = 0; //Valid KWP size
+ }
+ if (!(((data[0] & 0xF8U) == 0xC0U) && ((data[0] & 0x07U) != 0U) &&
+ (data[1] == 0x33U) && (data[2] == 0xF1U))) {
+ tx = 0; //Bad msg
+ }
+ return tx;
}
const safety_hooks elm327_hooks = {
@@ -31,5 +45,5 @@ const safety_hooks elm327_hooks = {
.tx = elm327_tx_hook,
.tx_lin = elm327_tx_lin_hook,
.ignition = default_ign_hook,
- .fwd = nooutput_fwd_hook,
+ .fwd = default_fwd_hook,
};
diff --git a/panda/board/safety/safety_ford.h b/panda/board/safety/safety_ford.h
index 075029fb6..21c9c54db 100644
--- a/panda/board/safety/safety_ford.h
+++ b/panda/board/safety/safety_ford.h
@@ -13,26 +13,29 @@ int ford_is_moving = 0;
static void ford_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
- if ((to_push->RIR>>21) == 0x217) {
+ int addr = GET_ADDR(to_push);
+
+ if (addr == 0x217) {
// wheel speeds are 14 bits every 16
ford_is_moving = 0xFCFF & (to_push->RDLR | (to_push->RDLR >> 16) |
to_push->RDHR | (to_push->RDHR >> 16));
}
// state machine to enter and exit controls
- if ((to_push->RIR>>21) == 0x83) {
- int cancel = ((to_push->RDLR >> 8) & 0x1);
- int set_or_resume = (to_push->RDLR >> 28) & 0x3;
+ if (addr == 0x83) {
+ bool cancel = (to_push->RDLR >> 8) & 0x1;
+ bool set_or_resume = (to_push->RDLR >> 28) & 0x3;
if (cancel) {
controls_allowed = 0;
- } else if (set_or_resume) {
+ }
+ if (set_or_resume) {
controls_allowed = 1;
}
}
// exit controls on rising edge of brake press or on brake press when
// speed > 0
- if ((to_push->RIR>>21) == 0x165) {
+ if (addr == 0x165) {
int brake = to_push->RDLR & 0x20;
if (brake && (!(ford_brake_prev) || ford_is_moving)) {
controls_allowed = 0;
@@ -41,7 +44,7 @@ static void ford_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
}
// exit controls on rising edge of gas press
- if ((to_push->RIR>>21) == 0x204) {
+ if (addr == 0x204) {
int gas = to_push->RDLR & 0xFF03;
if (gas && !(ford_gas_prev)) {
controls_allowed = 0;
@@ -58,29 +61,33 @@ static void ford_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
static int ford_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
+ int tx = 1;
// disallow actuator commands if gas or brake (with vehicle moving) are pressed
// and the the latching controls_allowed flag is True
int pedal_pressed = ford_gas_prev || (ford_brake_prev && ford_is_moving);
- int current_controls_allowed = controls_allowed && !(pedal_pressed);
+ bool current_controls_allowed = controls_allowed && !(pedal_pressed);
+ int addr = GET_ADDR(to_send);
// STEER: safety check
- if ((to_send->RIR>>21) == 0x3CA) {
- if (current_controls_allowed) {
- // all messages are fine here
- } else {
+ if (addr == 0x3CA) {
+ if (!current_controls_allowed) {
// bits 7-4 need to be 0xF to disallow lkas commands
- if (((to_send->RDLR >> 4) & 0xF) != 0xF) return 0;
+ if (((to_send->RDLR >> 4) & 0xF) != 0xF) {
+ tx = 0;
+ }
}
}
// FORCE CANCEL: safety check only relevant when spamming the cancel button
// ensuring that set and resume aren't sent
- if ((to_send->RIR>>21) == 0x83) {
- if ((to_send->RDLR >> 28) & 0x3) return 0;
+ if (addr == 0x83) {
+ if (((to_send->RDLR >> 28) & 0x3) != 0) {
+ tx = 0;
+ }
}
// 1 allows the message through
- return true;
+ return tx;
}
const safety_hooks ford_hooks = {
@@ -89,5 +96,5 @@ const safety_hooks ford_hooks = {
.tx = ford_tx_hook,
.tx_lin = nooutput_tx_lin_hook,
.ignition = default_ign_hook,
- .fwd = nooutput_fwd_hook,
+ .fwd = default_fwd_hook,
};
diff --git a/panda/board/safety/safety_gm.h b/panda/board/safety/safety_gm.h
index 996161127..949f5c7e7 100644
--- a/panda/board/safety/safety_gm.h
+++ b/panda/board/safety/safety_gm.h
@@ -10,7 +10,7 @@
const int GM_MAX_STEER = 300;
const int GM_MAX_RT_DELTA = 128; // max delta torque allowed for real time checks
-const int32_t GM_RT_INTERVAL = 250000; // 250ms between real time checks
+const uint32_t GM_RT_INTERVAL = 250000; // 250ms between real time checks
const int GM_MAX_RATE_UP = 7;
const int GM_MAX_RATE_DOWN = 17;
const int GM_DRIVER_TORQUE_ALLOWANCE = 50;
@@ -23,25 +23,16 @@ int gm_brake_prev = 0;
int gm_gas_prev = 0;
int gm_speed = 0;
// silence everything if stock car control ECUs are still online
-int gm_ascm_detected = 0;
-int gm_ignition_started = 0;
+bool gm_ascm_detected = 0;
+bool gm_ignition_started = 0;
int gm_rt_torque_last = 0;
int gm_desired_torque_last = 0;
uint32_t gm_ts_last = 0;
struct sample_t gm_torque_driver; // last few driver torques measured
static void gm_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
- int bus_number = (to_push->RDTR >> 4) & 0xFF;
- uint32_t addr;
- if (to_push->RIR & 4) {
- // Extended
- // Not looked at, but have to be separated
- // to avoid address collision
- addr = to_push->RIR >> 3;
- } else {
- // Normal
- addr = to_push->RIR >> 21;
- }
+ int bus_number = GET_BUS(to_push);
+ int addr = GET_ADDR(to_push);
if (addr == 388) {
int torque_driver_new = (((to_push->RDHR >> 16) & 0x7) << 8) | ((to_push->RDHR >> 24) & 0xFF);
@@ -50,11 +41,11 @@ static void gm_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
update_sample(&gm_torque_driver, torque_driver_new);
}
- if (addr == 0x1f1 && bus_number == 0) {
+ if ((addr == 0x1F1) && (bus_number == 0)) {
//Bit 5 should be ignition "on"
//Backup plan is Bit 2 (accessory power)
- uint32_t ign = (to_push->RDLR) & 0x20;
- gm_ignition_started = ign > 0;
+ bool ign = ((to_push->RDLR) & 0x20) != 0;
+ gm_ignition_started = ign;
}
// sample speed, really only care if car is moving or not
@@ -67,19 +58,24 @@ static void gm_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
// on powertrain bus.
// 384 = ASCMLKASteeringCmd
// 715 = ASCMGasRegenCmd
- if (bus_number == 0 && (addr == 384 || addr == 715)) {
+ if ((bus_number == 0) && ((addr == 384) || (addr == 715))) {
gm_ascm_detected = 1;
controls_allowed = 0;
}
// ACC steering wheel buttons
if (addr == 481) {
- int buttons = (to_push->RDHR >> 12) & 0x7;
- // res/set - enable, cancel button - disable
- if (buttons == 2 || buttons == 3) {
- controls_allowed = 1;
- } else if (buttons == 6) {
- controls_allowed = 0;
+ int button = (to_push->RDHR >> 12) & 0x7;
+ switch (button) {
+ case 2: // resume
+ case 3: // set
+ controls_allowed = 1;
+ break;
+ case 6: // cancel
+ controls_allowed = 0;
+ break;
+ default:
+ break; // any other button is irrelevant
}
}
@@ -109,7 +105,7 @@ static void gm_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
// exit controls on regen paddle
if (addr == 189) {
- int regen = to_push->RDLR & 0x20;
+ bool regen = to_push->RDLR & 0x20;
if (regen) {
controls_allowed = 0;
}
@@ -124,43 +120,41 @@ static void gm_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
static int gm_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
+ int tx = 1;
+
// There can be only one! (ASCM)
if (gm_ascm_detected) {
- return 0;
+ tx = 0;
}
// disallow actuator commands if gas or brake (with vehicle moving) are pressed
// and the the latching controls_allowed flag is True
int pedal_pressed = gm_gas_prev || (gm_brake_prev && gm_speed);
- int current_controls_allowed = controls_allowed && !pedal_pressed;
+ bool current_controls_allowed = controls_allowed && !pedal_pressed;
- uint32_t addr;
- if (to_send->RIR & 4) {
- // Extended
- addr = to_send->RIR >> 3;
- } else {
- // Normal
- addr = to_send->RIR >> 21;
- }
+ int addr = GET_ADDR(to_send);
// BRAKE: safety check
if (addr == 789) {
- int rdlr = to_send->RDLR;
- int brake = ((rdlr & 0xF) << 8) + ((rdlr & 0xFF00) >> 8);
+ uint32_t rdlr = to_send->RDLR;
+ int brake = ((rdlr & 0xFU) << 8) + ((rdlr & 0xFF00U) >> 8);
brake = (0x1000 - brake) & 0xFFF;
- if (current_controls_allowed && long_controls_allowed) {
- if (brake > GM_MAX_BRAKE) return 0;
- } else {
- if (brake != 0) return 0;
+ if (!current_controls_allowed || !long_controls_allowed) {
+ if (brake != 0) {
+ tx = 0;
+ }
+ }
+ if (brake > GM_MAX_BRAKE) {
+ tx = 0;
}
}
// LKA STEER: safety check
if (addr == 384) {
- int rdlr = to_send->RDLR;
- int desired_torque = ((rdlr & 0x7) << 8) + ((rdlr & 0xFF00) >> 8);
+ uint32_t rdlr = to_send->RDLR;
+ int desired_torque = ((rdlr & 0x7U) << 8) + ((rdlr & 0xFF00U) >> 8);
uint32_t ts = TIM2->CNT;
- int violation = 0;
+ bool violation = 0;
desired_torque = to_signed(desired_torque, 11);
if (current_controls_allowed) {
@@ -200,37 +194,43 @@ static int gm_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
}
if (violation) {
- return false;
+ tx = 0;
}
}
// PARK ASSIST STEER: unlimited torque, no thanks
- if (addr == 823) return 0;
+ if (addr == 823) {
+ tx = 0;
+ }
// GAS/REGEN: safety check
if (addr == 715) {
- int rdlr = to_send->RDLR;
- int gas_regen = ((rdlr & 0x7F0000) >> 11) + ((rdlr & 0xF8000000) >> 27);
- int apply = rdlr & 1;
- if (current_controls_allowed && long_controls_allowed) {
- if (gas_regen > GM_MAX_GAS) return 0;
- } else {
- // Disabled message is !engaed with gas
- // value that corresponds to max regen.
- if (apply || gas_regen != GM_MAX_REGEN) return 0;
+ uint32_t rdlr = to_send->RDLR;
+ int gas_regen = ((rdlr & 0x7F0000U) >> 11) + ((rdlr & 0xF8000000U) >> 27);
+ // Disabled message is !engaed with gas
+ // value that corresponds to max regen.
+ if (!current_controls_allowed || !long_controls_allowed) {
+ bool apply = (rdlr & 1U) != 0U;
+ if (apply || (gas_regen != GM_MAX_REGEN)) {
+ tx = 0;
+ }
+ }
+ if (gas_regen > GM_MAX_GAS) {
+ tx = 0;
}
}
// 1 allows the message through
- return true;
+ return tx;
}
static void gm_init(int16_t param) {
+ UNUSED(param);
controls_allowed = 0;
gm_ignition_started = 0;
}
-static int gm_ign_hook() {
+static int gm_ign_hook(void) {
return gm_ignition_started;
}
@@ -240,5 +240,5 @@ const safety_hooks gm_hooks = {
.tx = gm_tx_hook,
.tx_lin = nooutput_tx_lin_hook,
.ignition = gm_ign_hook,
- .fwd = nooutput_fwd_hook,
+ .fwd = default_fwd_hook,
};
diff --git a/panda/board/safety/safety_gm_ascm.h b/panda/board/safety/safety_gm_ascm.h
index 70a042ec5..d452818d6 100644
--- a/panda/board/safety/safety_gm_ascm.h
+++ b/panda/board/safety/safety_gm_ascm.h
@@ -3,42 +3,35 @@
static int gm_ascm_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
- uint32_t addr = to_fwd->RIR>>21;
+ int bus_fwd = -1;
if (bus_num == 0) {
-
- // do not propagate lkas messages from ascm to actuators
+ int addr = GET_ADDR(to_fwd);
+ bus_fwd = 2;
+ // do not propagate lkas messages from ascm to actuators, unless supercruise is on
// block 0x152 and 0x154, which are the lkas command from ASCM1 and ASCM2
// block 0x315 and 0x2cb, which are the brake and accel commands from ASCM1
//if ((addr == 0x152) || (addr == 0x154) || (addr == 0x315) || (addr == 0x2cb)) {
if ((addr == 0x152) || (addr == 0x154)) {
- int supercruise_on = (to_fwd->RDHR>>4) & 0x1; // bit 36
- if (!supercruise_on) return -1;
+ int supercruise_on = (to_fwd->RDHR >> 4) & 0x1; // bit 36
+ if (!supercruise_on) {
+ bus_fwd = -1;
+ }
}
-
- // on the chassis bus, the OBDII port is on the module side, so we need to read
- // the lkas messages sent by openpilot (put on unused 0x151 ane 0x153 addrs) and send it to
- // the actuator as 0x152 and 0x154
- if (addr == 0x151) {
- to_fwd->RIR = (0x152 << 21) | (to_fwd->RIR & 0x1fffff);
+ if ((addr == 0x151) || (addr == 0x153) || (addr == 0x314)) {
+ // on the chassis bus, the OBDII port is on the module side, so we need to read
+ // the lkas messages sent by openpilot (put on unused 0x151 ane 0x153 addrs) and send it to
+ // the actuator as 0x152 and 0x154
+ uint32_t fwd_addr = addr + 1;
+ to_fwd->RIR = (fwd_addr << 21) | (to_fwd->RIR & 0x1fffff);
}
- if (addr == 0x153) {
- to_fwd->RIR = (0x154 << 21) | (to_fwd->RIR & 0x1fffff);
- }
-
- // brake
- if (addr == 0x314) {
- to_fwd->RIR = (0x315 << 21) | (to_fwd->RIR & 0x1fffff);
- }
-
- return 2;
}
if (bus_num == 2) {
- return 0;
+ bus_fwd = 0;
}
- return -1;
+ return bus_fwd;
}
const safety_hooks gm_ascm_hooks = {
diff --git a/panda/board/safety/safety_honda.h b/panda/board/safety/safety_honda.h
index 3aeeefe83..44a57ec97 100644
--- a/panda/board/safety/safety_honda.h
+++ b/panda/board/safety/safety_honda.h
@@ -16,20 +16,29 @@ bool honda_alt_brake_msg = false;
static void honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
+ int addr = GET_ADDR(to_push);
+ int len = GET_LEN(to_push);
+
// sample speed
- if ((to_push->RIR>>21) == 0x158) {
+ if (addr == 0x158) {
// first 2 bytes
honda_ego_speed = to_push->RDLR & 0xFFFF;
}
// state machine to enter and exit controls
// 0x1A6 for the ILX, 0x296 for the Civic Touring
- if ((to_push->RIR>>21) == 0x1A6 || (to_push->RIR>>21) == 0x296) {
- int buttons = (to_push->RDLR & 0xE0) >> 5;
- if (buttons == 4 || buttons == 3) {
- controls_allowed = 1;
- } else if (buttons == 2) {
- controls_allowed = 0;
+ if ((addr == 0x1A6) || (addr == 0x296)) {
+ int button = (to_push->RDLR & 0xE0) >> 5;
+ switch (button) {
+ case 2: // cancel
+ controls_allowed = 0;
+ break;
+ case 3: // set
+ case 4: // resume
+ controls_allowed = 1;
+ break;
+ default:
+ break; // any other button is irrelevant
}
}
@@ -39,11 +48,12 @@ static void honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
// in these cases, this is used instead.
// most hondas: 0x17C bit 53
// accord, crv: 0x1BE bit 4
- #define IS_USER_BRAKE_MSG(to_push) (!honda_alt_brake_msg ? to_push->RIR>>21 == 0x17C : to_push->RIR>>21 == 0x1BE)
- #define USER_BRAKE_VALUE(to_push) (!honda_alt_brake_msg ? to_push->RDHR & 0x200000 : to_push->RDLR & 0x10)
+ #define IS_USER_BRAKE_MSG(addr) (!honda_alt_brake_msg ? ((addr) == 0x17C) : ((addr) == 0x1BE))
+ #define USER_BRAKE_VALUE(to_push) (!honda_alt_brake_msg ? ((to_push)->RDHR & 0x200000) : ((to_push)->RDLR & 0x10))
// exit controls on rising edge of brake press or on brake press when
// speed > 0
- if (IS_USER_BRAKE_MSG(to_push)) {
+ bool is_user_brake_msg = IS_USER_BRAKE_MSG(addr); // needed to enforce type
+ if (is_user_brake_msg) {
int brake = USER_BRAKE_VALUE(to_push);
if (brake && (!(honda_brake_prev) || honda_ego_speed)) {
controls_allowed = 0;
@@ -53,7 +63,7 @@ static void honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
// exit controls on rising edge of gas press if interceptor (0x201 w/ len = 6)
// length check because bosch hardware also uses this id (0x201 w/ len = 8)
- if ((to_push->RIR>>21) == 0x201 && (to_push->RDTR & 0xf) == 6) {
+ if ((addr == 0x201) && (len == 6)) {
gas_interceptor_detected = 1;
int gas_interceptor = ((to_push->RDLR & 0xFF) << 8) | ((to_push->RDLR & 0xFF00) >> 8);
if ((gas_interceptor > HONDA_GAS_INTERCEPTOR_THRESHOLD) &&
@@ -66,7 +76,7 @@ static void honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
// exit controls on rising edge of gas press if no interceptor
if (!gas_interceptor_detected) {
- if ((to_push->RIR>>21) == 0x17C) {
+ if (addr == 0x17C) {
int gas = to_push->RDLR & 0xFF;
if (gas && !(honda_gas_prev) && long_controls_allowed) {
controls_allowed = 0;
@@ -84,52 +94,62 @@ static void honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
static int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
+ int tx = 1;
+ int addr = GET_ADDR(to_send);
+ int bus = GET_BUS(to_send);
+
// disallow actuator commands if gas or brake (with vehicle moving) are pressed
// and the the latching controls_allowed flag is True
int pedal_pressed = honda_gas_prev || (gas_interceptor_prev > HONDA_GAS_INTERCEPTOR_THRESHOLD) ||
(honda_brake_prev && honda_ego_speed);
- int current_controls_allowed = controls_allowed && !(pedal_pressed);
+ bool current_controls_allowed = controls_allowed && !(pedal_pressed);
// BRAKE: safety check
- if ((to_send->RIR>>21) == 0x1FA) {
- if (current_controls_allowed && long_controls_allowed) {
- if ((to_send->RDLR & 0xFFFFFF3F) != to_send->RDLR) return 0;
- } else {
- if ((to_send->RDLR & 0xFFFF0000) != to_send->RDLR) return 0;
+ if (addr == 0x1FA) {
+ if (!current_controls_allowed || !long_controls_allowed) {
+ if ((to_send->RDLR & 0xFFFF0000) != to_send->RDLR) {
+ tx = 0;
+ }
+ }
+ if ((to_send->RDLR & 0xFFFFFF3F) != to_send->RDLR) {
+ tx = 0;
}
}
// STEER: safety check
- if ((to_send->RIR>>21) == 0xE4 || (to_send->RIR>>21) == 0x194) {
- if (current_controls_allowed) {
- // all messages are fine here
- } else {
- if ((to_send->RDLR & 0xFFFF0000) != to_send->RDLR) return 0;
+ if ((addr == 0xE4) || (addr == 0x194)) {
+ if (!current_controls_allowed) {
+ if ((to_send->RDLR & 0xFFFF0000) != to_send->RDLR) {
+ tx = 0;
+ }
}
}
// GAS: safety check
- if ((to_send->RIR>>21) == 0x200) {
- if (current_controls_allowed && long_controls_allowed) {
- // all messages are fine here
- } else {
- if ((to_send->RDLR & 0xFFFF0000) != to_send->RDLR) return 0;
+ if (addr == 0x200) {
+ if (!current_controls_allowed || !long_controls_allowed) {
+ if ((to_send->RDLR & 0xFFFF0000) != to_send->RDLR) {
+ tx = 0;
+ }
}
}
// FORCE CANCEL: safety check only relevant when spamming the cancel button in Bosch HW
// ensuring that only the cancel button press is sent (VAL 2) when controls are off.
// This avoids unintended engagements while still allowing resume spam
- if (((to_send->RIR>>21) == 0x296) && honda_bosch_hardware &&
- !current_controls_allowed && ((to_send->RDTR >> 4) & 0xFF) == 0) {
- if (((to_send->RDLR >> 5) & 0x7) != 2) return 0;
+ if ((addr == 0x296) && honda_bosch_hardware &&
+ !current_controls_allowed && (bus == 0)) {
+ if (((to_send->RDLR >> 5) & 0x7) != 2) {
+ tx = 0;
+ }
}
// 1 allows the message through
- return true;
+ return tx;
}
static void honda_init(int16_t param) {
+ UNUSED(param);
controls_allowed = 0;
honda_bosch_hardware = false;
honda_alt_brake_msg = false;
@@ -139,7 +159,7 @@ static void honda_bosch_init(int16_t param) {
controls_allowed = 0;
honda_bosch_hardware = true;
// Checking for alternate brake override from safety parameter
- honda_alt_brake_msg = param == 1 ? true : false;
+ honda_alt_brake_msg = (param == 1) ? true : false;
}
static int honda_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
@@ -147,27 +167,38 @@ static int honda_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
// 0xE4 is steering on all cars except CRV and RDX, 0x194 for CRV and RDX,
// 0x1FA is brake control, 0x30C is acc hud, 0x33D is lkas hud,
// 0x39f is radar hud
- int addr = to_fwd->RIR>>21;
+ int bus_fwd = -1;
+
if (bus_num == 0) {
- return 2;
- } else if (bus_num == 2) {
- // block stock lkas messages and stock acc messages (if OP is doing ACC)
- int is_lkas_msg = (addr == 0xE4 || addr == 0x194 || addr == 0x33D);
- int is_acc_msg = (addr == 0x1FA || addr == 0x30C || addr == 0x39F);
- if (is_lkas_msg || (is_acc_msg && long_controls_allowed)) {
- return -1;
- }
- return 0;
+ bus_fwd = 2;
}
- return -1;
+ if (bus_num == 2) {
+ // block stock lkas messages and stock acc messages (if OP is doing ACC)
+ int addr = GET_ADDR(to_fwd);
+ int is_lkas_msg = (addr == 0xE4) || (addr == 0x194) || (addr == 0x33D);
+ int is_acc_msg = (addr == 0x1FA) || (addr == 0x30C) || (addr == 0x39F);
+ int block_fwd = is_lkas_msg || (is_acc_msg && long_controls_allowed);
+ if (!block_fwd) {
+ bus_fwd = 0;
+ }
+ }
+ return bus_fwd;
}
static int honda_bosch_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
- if (bus_num == 1 || bus_num == 2) {
- int addr = to_fwd->RIR>>21;
- return addr != 0xE4 && addr != 0x33D ? (uint8_t)(~bus_num & 0x3) : -1;
+ int bus_fwd = -1;
+
+ if (bus_num == 2) {
+ bus_fwd = 1;
}
- return -1;
+ if (bus_num == 1) {
+ int addr = GET_ADDR(to_fwd);
+ int is_lkas_msg = (addr == 0xE4) || (addr == 0x33D);
+ if (!is_lkas_msg) {
+ bus_fwd = 2;
+ }
+ }
+ return bus_fwd;
}
const safety_hooks honda_hooks = {
diff --git a/panda/board/safety/safety_hyundai.h b/panda/board/safety/safety_hyundai.h
index b67632141..c1b55359b 100644
--- a/panda/board/safety/safety_hyundai.h
+++ b/panda/board/safety/safety_hyundai.h
@@ -1,14 +1,14 @@
const int HYUNDAI_MAX_STEER = 255; // like stock
const int HYUNDAI_MAX_RT_DELTA = 112; // max delta torque allowed for real time checks
-const int32_t HYUNDAI_RT_INTERVAL = 250000; // 250ms between real time checks
+const uint32_t HYUNDAI_RT_INTERVAL = 250000; // 250ms between real time checks
const int HYUNDAI_MAX_RATE_UP = 3;
const int HYUNDAI_MAX_RATE_DOWN = 7;
const int HYUNDAI_DRIVER_TORQUE_ALLOWANCE = 50;
const int HYUNDAI_DRIVER_TORQUE_FACTOR = 2;
-int hyundai_camera_detected = 0;
+bool hyundai_camera_detected = 0;
+bool hyundai_giraffe_switch_2 = 0; // is giraffe switch 2 high?
int hyundai_camera_bus = 0;
-int hyundai_giraffe_switch_2 = 0; // is giraffe switch 2 high?
int hyundai_rt_torque_last = 0;
int hyundai_desired_torque_last = 0;
int hyundai_cruise_engaged_last = 0;
@@ -16,17 +16,8 @@ uint32_t hyundai_ts_last = 0;
struct sample_t hyundai_torque_driver; // last few driver torques measured
static void hyundai_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
- int bus = (to_push->RDTR >> 4) & 0xFF;
- uint32_t addr;
- if (to_push->RIR & 4) {
- // Extended
- // Not looked at, but have to be separated
- // to avoid address collision
- addr = to_push->RIR >> 3;
- } else {
- // Normal
- addr = to_push->RIR >> 21;
- }
+ int bus = GET_BUS(to_push);
+ int addr = GET_ADDR(to_push);
if (addr == 897) {
int torque_driver_new = ((to_push->RDLR >> 11) & 0xfff) - 2048;
@@ -35,7 +26,7 @@ static void hyundai_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
}
// check if stock camera ECU is still online
- if (bus == 0 && addr == 832) {
+ if ((bus == 0) && (addr == 832)) {
hyundai_camera_detected = 1;
controls_allowed = 0;
}
@@ -46,44 +37,39 @@ static void hyundai_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
}
// enter controls on rising edge of ACC, exit controls on ACC off
- if ((to_push->RIR>>21) == 1057) {
+ if (addr == 1057) {
// 2 bits: 13-14
int cruise_engaged = (to_push->RDLR >> 13) & 0x3;
if (cruise_engaged && !hyundai_cruise_engaged_last) {
controls_allowed = 1;
- } else if (!cruise_engaged) {
+ }
+ if (!cruise_engaged) {
controls_allowed = 0;
}
hyundai_cruise_engaged_last = cruise_engaged;
}
// 832 is lkas cmd. If it is on camera bus, then giraffe switch 2 is high
- if ((to_push->RIR>>21) == 832 && (bus == hyundai_camera_bus) && (hyundai_camera_bus != 0)) {
+ if ((addr == 832) && (bus == hyundai_camera_bus) && (hyundai_camera_bus != 0)) {
hyundai_giraffe_switch_2 = 1;
}
}
static int hyundai_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
+ int tx = 1;
+ int addr = GET_ADDR(to_send);
+
// There can be only one! (camera)
if (hyundai_camera_detected) {
- return 0;
- }
-
- uint32_t addr;
- if (to_send->RIR & 4) {
- // Extended
- addr = to_send->RIR >> 3;
- } else {
- // Normal
- addr = to_send->RIR >> 21;
+ tx = 0;
}
// LKA STEER: safety check
if (addr == 832) {
int desired_torque = ((to_send->RDLR >> 16) & 0x7ff) - 1024;
uint32_t ts = TIM2->CNT;
- int violation = 0;
+ bool violation = 0;
if (controls_allowed) {
@@ -122,7 +108,7 @@ static int hyundai_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
}
if (violation) {
- return false;
+ tx = 0;
}
}
@@ -130,26 +116,36 @@ static int hyundai_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
// ensuring that only the cancel button press is sent (VAL 4) when controls are off.
// This avoids unintended engagements while still allowing resume spam
// TODO: fix bug preventing the button msg to be fwd'd on bus 2
- //if (((to_send->RIR>>21) == 1265) && !controls_allowed && ((to_send->RDTR >> 4) & 0xFF) == 0) {
- // if ((to_send->RDLR & 0x7) != 4) return 0;
+ //if ((addr == 1265) && !controls_allowed && (bus == 0) {
+ // if ((to_send->RDLR & 0x7) != 4) {
+ // tx = 0;
+ // }
//}
// 1 allows the message through
- return true;
+ return tx;
}
static int hyundai_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
- // forward cam to ccan and viceversa, except lkas cmd
- if ((bus_num == 0 || bus_num == hyundai_camera_bus) && hyundai_giraffe_switch_2) {
- if ((to_fwd->RIR>>21) == 832 && bus_num == hyundai_camera_bus) return -1;
- if (bus_num == 0) return hyundai_camera_bus;
- if (bus_num == hyundai_camera_bus) return 0;
+ int bus_fwd = -1;
+ // forward cam to ccan and viceversa, except lkas cmd
+ if (hyundai_giraffe_switch_2) {
+ if (bus_num == 0) {
+ bus_fwd = hyundai_camera_bus;
+ }
+ if (bus_num == hyundai_camera_bus) {
+ int addr = GET_ADDR(to_fwd);
+ if (addr != 832) {
+ bus_fwd = 0;
+ }
+ }
}
- return -1;
+ return bus_fwd;
}
static void hyundai_init(int16_t param) {
+ UNUSED(param);
controls_allowed = 0;
hyundai_giraffe_switch_2 = 0;
}
diff --git a/panda/board/safety/safety_subaru.h b/panda/board/safety/safety_subaru.h
index e64c77719..c7a8c20e5 100644
--- a/panda/board/safety/safety_subaru.h
+++ b/panda/board/safety/safety_subaru.h
@@ -2,7 +2,7 @@ const int SUBARU_MAX_STEER = 2047; // 1s
// real time torque limit to prevent controls spamming
// the real time limit is 1500/sec
const int SUBARU_MAX_RT_DELTA = 940; // max delta torque allowed for real time checks
-const int32_t SUBARU_RT_INTERVAL = 250000; // 250ms between real time checks
+const uint32_t SUBARU_RT_INTERVAL = 250000; // 250ms between real time checks
const int SUBARU_MAX_RATE_UP = 50;
const int SUBARU_MAX_RATE_DOWN = 70;
const int SUBARU_DRIVER_TORQUE_ALLOWANCE = 60;
@@ -14,14 +14,12 @@ int subaru_desired_torque_last = 0;
uint32_t subaru_ts_last = 0;
struct sample_t subaru_torque_driver; // last few driver torques measured
-static void subaru_init(int16_t param) {
-}
static void subaru_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
- int bus_number = (to_push->RDTR >> 4) & 0xFF;
- uint32_t addr = to_push->RIR >> 21;
+ int bus = GET_BUS(to_push);
+ int addr = GET_ADDR(to_push);
- if ((addr == 0x119) && (bus_number == 0)){
+ if ((addr == 0x119) && (bus == 0)){
int torque_driver_new = ((to_push->RDLR >> 16) & 0x7FF);
torque_driver_new = to_signed(torque_driver_new, 11);
// update array of samples
@@ -29,11 +27,12 @@ static void subaru_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
}
// enter controls on rising edge of ACC, exit controls on ACC off
- if ((addr == 0x240) && (bus_number == 0)) {
+ if ((addr == 0x240) && (bus == 0)) {
int cruise_engaged = (to_push->RDHR >> 9) & 1;
if (cruise_engaged && !subaru_cruise_engaged_last) {
controls_allowed = 1;
- } else if (!cruise_engaged) {
+ }
+ if (!cruise_engaged) {
controls_allowed = 0;
}
subaru_cruise_engaged_last = cruise_engaged;
@@ -41,12 +40,13 @@ static void subaru_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
}
static int subaru_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
- uint32_t addr = to_send->RIR >> 21;
+ int tx = 1;
+ int addr = GET_ADDR(to_send);
// steer cmd checks
if (addr == 0x122) {
int desired_torque = ((to_send->RDLR >> 16) & 0x1FFF);
- int violation = 0;
+ bool violation = 0;
uint32_t ts = TIM2->CNT;
desired_torque = to_signed(desired_torque, 13);
@@ -88,52 +88,37 @@ static int subaru_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
}
if (violation) {
- return false;
+ tx = 0;
}
}
- return true;
+ return tx;
}
static int subaru_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
- // shifts bits 29 > 11
- int32_t addr = to_fwd->RIR >> 21;
-
- // forward CAN 0 > 1
+ int bus_fwd = -1;
if (bus_num == 0) {
-
- return 2; // ES CAN
+ bus_fwd = 2; // Camera CAN
}
- // forward CAN 1 > 0, except ES_LKAS
- else if (bus_num == 2) {
-
- // outback 2015
- if (addr == 0x164) {
- return -1;
+ if (bus_num == 2) {
+ // 356 is LKAS for outback 2015
+ // 356 is LKAS for Global Platform
+ // 545 is ES_Distance
+ // 802 is ES_LKAS
+ int addr = GET_ADDR(to_fwd);
+ int block_msg = (addr == 290) || (addr == 356) || (addr == 545) || (addr == 802);
+ if (!block_msg) {
+ bus_fwd = 0; // Main CAN
}
- // global platform
- if (addr == 0x122) {
- return -1;
- }
- // ES Distance
- if (addr == 545) {
- return -1;
- }
- // ES LKAS
- if (addr == 802) {
- return -1;
- }
-
- return 0; // Main CAN
}
// fallback to do not forward
- return -1;
+ return bus_fwd;
}
const safety_hooks subaru_hooks = {
- .init = subaru_init,
+ .init = nooutput_init,
.rx = subaru_rx_hook,
.tx = subaru_tx_hook,
.tx_lin = nooutput_tx_lin_hook,
diff --git a/panda/board/safety/safety_tesla.h b/panda/board/safety/safety_tesla.h
index 430a42ce9..b58e6b2bb 100644
--- a/panda/board/safety/safety_tesla.h
+++ b/panda/board/safety/safety_tesla.h
@@ -8,8 +8,8 @@
// brake rising edge
// brake > 0mph
//
-int fmax_limit_check(float val, const float MAX, const float MIN) {
- return (val > MAX) || (val < MIN);
+bool fmax_limit_check(float val, const float MAX_VAL, const float MIN_VAL) {
+ return (val > MAX_VAL) || (val < MIN_VAL);
}
// 2m/s are added to be less restrictive
@@ -25,7 +25,7 @@ const struct lookup_t TESLA_LOOKUP_MAX_ANGLE = {
{2., 29., 38.},
{410., 92., 36.}};
-const int TESLA_RT_INTERVAL = 250000; // 250ms between real time checks
+const uint32_t TESLA_RT_INTERVAL = 250000; // 250ms between real time checks
// state of angle limits
float tesla_desired_angle_last = 0; // last desired steer angle
@@ -47,46 +47,27 @@ void reset_gmlan_switch_timeout(void);
void gmlan_switch_init(int timeout_enable);
-static void tesla_rx_hook(CAN_FIFOMailBox_TypeDef *to_push)
-{
+static void tesla_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
set_gmlan_digital_output(0); // #define GMLAN_HIGH 0
reset_gmlan_switch_timeout(); //we're still in tesla safety mode, reset the timeout counter and make sure our output is enabled
- //int bus_number = (to_push->RDTR >> 4) & 0xFF;
- uint32_t addr;
- if (to_push->RIR & 4)
- {
- // Extended
- // Not looked at, but have to be separated
- // to avoid address collision
- addr = to_push->RIR >> 3;
- }
- else
- {
- // Normal
- addr = to_push->RIR >> 21;
- }
+ int addr = GET_ADDR(to_push);
- if (addr == 0x45)
- {
+ if (addr == 0x45) {
// 6 bits starting at position 0
int lever_position = (to_push->RDLR & 0x3F);
- if (lever_position == 2)
- { // pull forward
+ if (lever_position == 2) { // pull forward
// activate openpilot
controls_allowed = 1;
- //}
}
- else if (lever_position == 1)
- { // push towards the back
+ if (lever_position == 1) { // push towards the back
// deactivate openpilot
controls_allowed = 0;
}
}
// Detect drive rail on (ignition) (start recording)
- if (addr == 0x348)
- {
+ if (addr == 0x348) {
// GTW_status
int drive_rail_on = (to_push->RDLR & 0x0001);
tesla_ignition_started = drive_rail_on == 1;
@@ -94,66 +75,56 @@ static void tesla_rx_hook(CAN_FIFOMailBox_TypeDef *to_push)
// exit controls on brake press
// DI_torque2::DI_brakePedal 0x118
- if (addr == 0x118)
- {
+ if (addr == 0x118) {
// 1 bit at position 16
- if (((to_push->RDLR & 0x8000)) >> 15 == 1)
- {
- //disable break cancel by commenting line below
+ if ((((to_push->RDLR & 0x8000)) >> 15) == 1) {
+ // disable break cancel by commenting line below
controls_allowed = 0;
}
//get vehicle speed in m/s. Tesla gives MPH
- tesla_speed = ((((((to_push->RDLR >> 24) & 0x0F) << 8) + ((to_push->RDLR >> 16) & 0xFF)) * 0.05 - 25) * 1.609 / 3.6);
- if (tesla_speed < 0)
- {
+ tesla_speed = ((((((to_push->RDLR >> 24) & 0xF) << 8) + ((to_push->RDLR >> 16) & 0xFF)) * 0.05) - 25) * 1.609 / 3.6;
+ if (tesla_speed < 0) {
tesla_speed = 0;
}
}
// exit controls on EPAS error
// EPAS_sysStatus::EPAS_eacStatus 0x370
- if (addr == 0x370)
- {
+ if (addr == 0x370) {
// if EPAS_eacStatus is not 1 or 2, disable control
eac_status = ((to_push->RDHR >> 21)) & 0x7;
// For human steering override we must not disable controls when eac_status == 0
// Additional safety: we could only allow eac_status == 0 when we have human steering allowed
- if ((controls_allowed == 1) && (eac_status != 0) && (eac_status != 1) && (eac_status != 2))
- {
+ if (controls_allowed && (eac_status != 0) && (eac_status != 1) && (eac_status != 2)) {
controls_allowed = 0;
//puts("EPAS error! \n");
}
}
//get latest steering wheel angle
- if (addr == 0x00E)
- {
- float angle_meas_now = (int)((((to_push->RDLR & 0x3F) << 8) + ((to_push->RDLR >> 8) & 0xFF)) * 0.1 - 819.2);
+ if (addr == 0x00E) {
+ float angle_meas_now = (int)(((((to_push->RDLR & 0x3F) << 8) + ((to_push->RDLR >> 8) & 0xFF)) * 0.1) - 819.2);
uint32_t ts = TIM2->CNT;
uint32_t ts_elapsed = get_ts_elapsed(ts, tesla_ts_angle_last);
// *** angle real time check
// add 1 to not false trigger the violation and multiply by 25 since the check is done every 250 ms and steer angle is updated at 100Hz
- float rt_delta_angle_up = interpolate(TESLA_LOOKUP_ANGLE_RATE_UP, tesla_speed) * 25. + 1.;
- float rt_delta_angle_down = interpolate(TESLA_LOOKUP_ANGLE_RATE_DOWN, tesla_speed) * 25. + 1.;
- float highest_rt_angle = tesla_rt_angle_last + (tesla_rt_angle_last > 0 ? rt_delta_angle_up : rt_delta_angle_down);
- float lowest_rt_angle = tesla_rt_angle_last - (tesla_rt_angle_last > 0 ? rt_delta_angle_down : rt_delta_angle_up);
+ float rt_delta_angle_up = (interpolate(TESLA_LOOKUP_ANGLE_RATE_UP, tesla_speed) * 25.) + 1.;
+ float rt_delta_angle_down = (interpolate(TESLA_LOOKUP_ANGLE_RATE_DOWN, tesla_speed) * 25.) + 1.;
+ float highest_rt_angle = tesla_rt_angle_last + ((tesla_rt_angle_last > 0.) ? rt_delta_angle_up : rt_delta_angle_down);
+ float lowest_rt_angle = tesla_rt_angle_last - ((tesla_rt_angle_last > 0.) ? rt_delta_angle_down : rt_delta_angle_up);
- if ((ts_elapsed > TESLA_RT_INTERVAL) || (controls_allowed && !tesla_controls_allowed_last))
- {
+ if ((ts_elapsed > TESLA_RT_INTERVAL) || (controls_allowed && !tesla_controls_allowed_last)) {
tesla_rt_angle_last = angle_meas_now;
tesla_ts_angle_last = ts;
}
// check for violation;
- if (fmax_limit_check(angle_meas_now, highest_rt_angle, lowest_rt_angle))
- {
+ if (fmax_limit_check(angle_meas_now, highest_rt_angle, lowest_rt_angle)) {
// We should not be able to STEER under these conditions
// Other sending is fine (to allow human override)
controls_allowed = 0;
//puts("WARN: RT Angle - No steer allowed! \n");
- }
- else
- {
+ } else {
controls_allowed = 1;
}
@@ -167,37 +138,28 @@ static void tesla_rx_hook(CAN_FIFOMailBox_TypeDef *to_push)
// else
// block all commands that produce actuation
-static int tesla_tx_hook(CAN_FIFOMailBox_TypeDef *to_send)
-{
+static int tesla_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
- uint32_t addr;
- float angle_raw;
- float desired_angle;
-
- addr = to_send->RIR >> 21;
+ int tx = 1;
+ int addr = GET_ADDR(to_send);
// do not transmit CAN message if steering angle too high
// DAS_steeringControl::DAS_steeringAngleRequest
- if (addr == 0x488)
- {
- angle_raw = ((to_send->RDLR & 0x7F) << 8) + ((to_send->RDLR & 0xFF00) >> 8);
- desired_angle = angle_raw * 0.1 - 1638.35;
- int16_t violation = 0;
+ if (addr == 0x488) {
+ float angle_raw = ((to_send->RDLR & 0x7F) << 8) + ((to_send->RDLR & 0xFF00) >> 8);
+ float desired_angle = (angle_raw * 0.1) - 1638.35;
+ bool violation = 0;
int st_enabled = (to_send->RDLR & 0x400000) >> 22;
if (st_enabled == 0) {
//steering is not enabled, do not check angles and do send
tesla_desired_angle_last = desired_angle;
- return true;
- }
-
- if (controls_allowed)
- {
+ } else if (controls_allowed) {
// add 1 to not false trigger the violation
float delta_angle_up = interpolate(TESLA_LOOKUP_ANGLE_RATE_UP, tesla_speed) + 1.;
float delta_angle_down = interpolate(TESLA_LOOKUP_ANGLE_RATE_DOWN, tesla_speed) + 1.;
- float highest_desired_angle = tesla_desired_angle_last + (tesla_desired_angle_last > 0 ? delta_angle_up : delta_angle_down);
- float lowest_desired_angle = tesla_desired_angle_last - (tesla_desired_angle_last > 0 ? delta_angle_down : delta_angle_up);
+ float highest_desired_angle = tesla_desired_angle_last + ((tesla_desired_angle_last > 0.) ? delta_angle_up : delta_angle_down);
+ float lowest_desired_angle = tesla_desired_angle_last - ((tesla_desired_angle_last > 0.) ? delta_angle_down : delta_angle_up);
float TESLA_MAX_ANGLE = interpolate(TESLA_LOOKUP_MAX_ANGLE, tesla_speed) + 1.;
//check for max angles
@@ -206,69 +168,55 @@ static int tesla_tx_hook(CAN_FIFOMailBox_TypeDef *to_send)
//check for angle delta changes
violation |= fmax_limit_check(desired_angle, highest_desired_angle, lowest_desired_angle);
- if (violation)
- {
+ if (violation) {
controls_allowed = 0;
- return false;
+ tx = 0;
}
tesla_desired_angle_last = desired_angle;
- return true;
+ } else {
+ tx = 0;
}
- return false;
}
- return true;
+ return tx;
}
-static void tesla_init(int16_t param)
-{
+static void tesla_init(int16_t param) {
+ UNUSED(param);
controls_allowed = 0;
tesla_ignition_started = 0;
gmlan_switch_init(1); //init the gmlan switch with 1s timeout enabled
}
-static int tesla_ign_hook()
-{
+static int tesla_ign_hook(void) {
return tesla_ignition_started;
}
-static int tesla_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd)
-{
+static int tesla_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
- int32_t addr = to_fwd->RIR >> 21;
-
- if (bus_num == 0)
- {
+ int bus_fwd = -1;
+ int addr = GET_ADDR(to_fwd);
+ if (bus_num == 0) {
// change inhibit of GTW_epasControl
- if (addr == 0x101)
- {
+
+ if (addr != 0x214) {
+ // remove EPB_epasControl
+ bus_fwd = 2; // Custom EPAS bus
+ }
+ if (addr == 0x101) {
to_fwd->RDLR = to_fwd->RDLR | 0x4000; // 0x4000: WITH_ANGLE, 0xC000: WITH_BOTH (angle and torque)
- int checksum = (((to_fwd->RDLR & 0xFF00) >> 8) + (to_fwd->RDLR & 0xFF) + 2) & 0xFF;
+ uint32_t checksum = (((to_fwd->RDLR & 0xFF00) >> 8) + (to_fwd->RDLR & 0xFF) + 2) & 0xFF;
to_fwd->RDLR = to_fwd->RDLR & 0xFFFF;
to_fwd->RDLR = to_fwd->RDLR + (checksum << 16);
- return 2;
}
-
- // remove EPB_epasControl
- if (addr == 0x214)
- {
- return -1;
- }
-
- return 2; // Custom EPAS bus
}
- if (bus_num == 2)
- {
-
+ if (bus_num == 2) {
// remove GTW_epasControl in forwards
- if (addr == 0x101)
- {
- return -1;
+ if (addr != 0x101) {
+ bus_fwd = 0; // Chassis CAN
}
-
- return 0; // Chassis CAN
}
- return -1;
+ return bus_fwd;
}
const safety_hooks tesla_hooks = {
diff --git a/panda/board/safety/safety_toyota.h b/panda/board/safety/safety_toyota.h
index d0fd90785..c4d579563 100644
--- a/panda/board/safety/safety_toyota.h
+++ b/panda/board/safety/safety_toyota.h
@@ -10,7 +10,7 @@ const int TOYOTA_MAX_TORQUE_ERROR = 350; // max torque cmd in excess of torque
// real time torque limit to prevent controls spamming
// the real time limit is 1500/sec
const int TOYOTA_MAX_RT_DELTA = 375; // max delta torque allowed for real time checks
-const int TOYOTA_RT_INTERVAL = 250000; // 250ms between real time checks
+const uint32_t TOYOTA_RT_INTERVAL = 250000; // 250ms between real time checks
// longitudinal limits
const int TOYOTA_MAX_ACCEL = 1500; // 1.5 m/s2
@@ -33,8 +33,12 @@ struct sample_t toyota_torque_meas; // last 3 motor torques produced by th
static void toyota_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
+
+ int bus = GET_BUS(to_push);
+ int addr = GET_ADDR(to_push);
+
// get eps motor torque (0.66 factor in dbc)
- if ((to_push->RIR>>21) == 0x260) {
+ if (addr == 0x260) {
int torque_meas_new = (((to_push->RDHR) & 0xFF00) | ((to_push->RDHR >> 16) & 0xFF));
torque_meas_new = to_signed(torque_meas_new, 16);
@@ -50,19 +54,20 @@ static void toyota_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
}
// enter controls on rising edge of ACC, exit controls on ACC off
- if ((to_push->RIR>>21) == 0x1D2) {
+ if (addr == 0x1D2) {
// 5th bit is CRUISE_ACTIVE
int cruise_engaged = to_push->RDLR & 0x20;
if (!cruise_engaged) {
controls_allowed = 0;
- } else if (cruise_engaged && !toyota_cruise_engaged_last) {
+ }
+ if (cruise_engaged && !toyota_cruise_engaged_last) {
controls_allowed = 1;
}
toyota_cruise_engaged_last = cruise_engaged;
}
- // exit controls on rising edge of gas press if interceptor (0x201)
- if ((to_push->RIR>>21) == 0x201) {
+ // exit controls on rising edge of interceptor gas press
+ if (addr == 0x201) {
gas_interceptor_detected = 1;
int gas_interceptor = ((to_push->RDLR & 0xFF) << 8) | ((to_push->RDLR & 0xFF00) >> 8);
if ((gas_interceptor > TOYOTA_GAS_INTERCEPTOR_THRESHOLD) &&
@@ -74,7 +79,7 @@ static void toyota_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
}
// exit controls on rising edge of gas press
- if ((to_push->RIR>>21) == 0x2C1) {
+ if (addr == 0x2C1) {
int gas = (to_push->RDHR >> 16) & 0xFF;
if ((gas > 0) && (toyota_gas_prev == 0) && !gas_interceptor_detected && long_controls_allowed) {
controls_allowed = 0;
@@ -82,52 +87,60 @@ static void toyota_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
toyota_gas_prev = gas;
}
- int bus = (to_push->RDTR >> 4) & 0xF;
// msgs are only on bus 2 if panda is connected to frc
if (bus == 2) {
toyota_camera_forwarded = 1;
}
// 0x2E4 is lkas cmd. If it is on bus 0, then giraffe switch 1 is high
- if ((to_push->RIR>>21) == 0x2E4 && (bus == 0)) {
+ if ((addr == 0x2E4) && (bus == 0)) {
toyota_giraffe_switch_1 = 1;
}
}
static int toyota_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
+ int tx = 1;
+ int addr = GET_ADDR(to_send);
+ int bus = GET_BUS(to_send);
+
// Check if msg is sent on BUS 0
- if (((to_send->RDTR >> 4) & 0xF) == 0) {
+ if (bus == 0) {
// no IPAS in non IPAS mode
- if (((to_send->RIR>>21) == 0x266) || ((to_send->RIR>>21) == 0x167)) return false;
+ if ((addr == 0x266) || (addr == 0x167)) {
+ tx = 0;
+ }
// GAS PEDAL: safety check
- if ((to_send->RIR>>21) == 0x200) {
- if (controls_allowed && long_controls_allowed) {
- // all messages are fine here
- } else {
- if ((to_send->RDLR & 0xFFFF0000) != to_send->RDLR) return 0;
+ if (addr == 0x200) {
+ if (!controls_allowed || !long_controls_allowed) {
+ if ((to_send->RDLR & 0xFFFF0000) != to_send->RDLR) {
+ tx = 0;
+ }
}
}
// ACCEL: safety check on byte 1-2
- if ((to_send->RIR>>21) == 0x343) {
+ if (addr == 0x343) {
int desired_accel = ((to_send->RDLR & 0xFF) << 8) | ((to_send->RDLR >> 8) & 0xFF);
desired_accel = to_signed(desired_accel, 16);
- if (controls_allowed && long_controls_allowed) {
- int violation = max_limit_check(desired_accel, TOYOTA_MAX_ACCEL, TOYOTA_MIN_ACCEL);
- if (violation) return 0;
- } else if (desired_accel != 0) {
- return 0;
+ if (!controls_allowed || !long_controls_allowed) {
+ if (desired_accel != 0) {
+ tx = 0;
+ }
+ }
+ bool violation = max_limit_check(desired_accel, TOYOTA_MAX_ACCEL, TOYOTA_MIN_ACCEL);
+ if (violation) {
+ tx = 0;
}
}
// STEER: safety check on bytes 2-3
- if ((to_send->RIR>>21) == 0x2E4) {
+ if (addr == 0x2E4) {
int desired_torque = (to_send->RDLR & 0xFF00) | ((to_send->RDLR >> 16) & 0xFF);
desired_torque = to_signed(desired_torque, 16);
- int violation = 0;
+ bool violation = 0;
uint32_t ts = TIM2->CNT;
@@ -167,13 +180,13 @@ static int toyota_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
}
if (violation) {
- return false;
+ tx = 0;
}
}
}
// 1 allows the message through
- return true;
+ return tx;
}
static void toyota_init(int16_t param) {
@@ -185,22 +198,25 @@ static void toyota_init(int16_t param) {
static int toyota_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
+ int bus_fwd = -1;
if (toyota_camera_forwarded && !toyota_giraffe_switch_1) {
- int addr = to_fwd->RIR>>21;
if (bus_num == 0) {
- return 2;
- } else if (bus_num == 2) {
+ bus_fwd = 2;
+ }
+ if (bus_num == 2) {
+ int addr = GET_ADDR(to_fwd);
// block stock lkas messages and stock acc messages (if OP is doing ACC)
- int is_lkas_msg = (addr == 0x2E4 || addr == 0x412);
- // in TSSP 2.0 the camera does ACC as well, so filter 0x343
+ // in TSS2, 0.191 is LTA which we need to block to avoid controls collision
+ int is_lkas_msg = ((addr == 0x2E4) || (addr == 0x412) || (addr == 0x191));
+ // in TSS2 the camera does ACC as well, so filter 0x343
int is_acc_msg = (addr == 0x343);
- if (is_lkas_msg || (is_acc_msg && long_controls_allowed)) {
- return -1;
+ int block_msg = is_lkas_msg || (is_acc_msg && long_controls_allowed);
+ if (!block_msg) {
+ bus_fwd = 0;
}
- return 0;
}
}
- return -1;
+ return bus_fwd;
}
const safety_hooks toyota_hooks = {
diff --git a/panda/board/safety/safety_toyota_ipas.h b/panda/board/safety/safety_toyota_ipas.h
index 2f0b42f64..99e6dae05 100644
--- a/panda/board/safety/safety_toyota_ipas.h
+++ b/panda/board/safety/safety_toyota_ipas.h
@@ -35,7 +35,9 @@ static void toyota_ipas_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
// check standard toyota stuff as well
toyota_rx_hook(to_push);
- if ((to_push->RIR>>21) == 0x260) {
+ int addr = GET_ADDR(to_push);
+
+ if (addr == 0x260) {
// get driver steering torque
int16_t torque_driver_new = (((to_push->RDLR) & 0xFF00) | ((to_push->RDLR >> 16) & 0xFF));
@@ -44,7 +46,7 @@ static void toyota_ipas_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
}
// get steer angle
- if ((to_push->RIR>>21) == 0x25) {
+ if (addr == 0x25) {
int angle_meas_new = ((to_push->RDLR & 0xf) << 8) + ((to_push->RDLR & 0xff00) >> 8);
uint32_t ts = TIM2->CNT;
@@ -55,10 +57,10 @@ static void toyota_ipas_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
// *** angle real time check
// add 1 to not false trigger the violation and multiply by 20 since the check is done every 250ms and steer angle is updated at 80Hz
- int rt_delta_angle_up = ((int)(RT_ANGLE_FUDGE * (interpolate(LOOKUP_ANGLE_RATE_UP, speed) * 20. * CAN_TO_DEG + 1.)));
- int rt_delta_angle_down = ((int)(RT_ANGLE_FUDGE * (interpolate(LOOKUP_ANGLE_RATE_DOWN, speed) * 20. * CAN_TO_DEG + 1.)));
- int highest_rt_angle = rt_angle_last + (rt_angle_last > 0? rt_delta_angle_up:rt_delta_angle_down);
- int lowest_rt_angle = rt_angle_last - (rt_angle_last > 0? rt_delta_angle_down:rt_delta_angle_up);
+ int rt_delta_angle_up = ((int)(RT_ANGLE_FUDGE * ((interpolate(LOOKUP_ANGLE_RATE_UP, speed) * 20. * CAN_TO_DEG) + 1.)));
+ int rt_delta_angle_down = ((int)(RT_ANGLE_FUDGE * ((interpolate(LOOKUP_ANGLE_RATE_DOWN, speed) * 20. * CAN_TO_DEG) + 1.)));
+ int highest_rt_angle = rt_angle_last + ((rt_angle_last > 0) ? rt_delta_angle_up : rt_delta_angle_down);
+ int lowest_rt_angle = rt_angle_last - ((rt_angle_last > 0) ? rt_delta_angle_down : rt_delta_angle_up);
// every RT_INTERVAL or when controls are turned on, set the new limits
uint32_t ts_elapsed = get_ts_elapsed(ts, ts_angle_last);
@@ -78,12 +80,12 @@ static void toyota_ipas_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
}
// get speed
- if ((to_push->RIR>>21) == 0xb4) {
+ if (addr == 0xb4) {
speed = ((float) (((to_push->RDHR) & 0xFF00) | ((to_push->RDHR >> 16) & 0xFF))) * 0.01 / 3.6;
}
// get ipas state
- if ((to_push->RIR>>21) == 0x262) {
+ if (addr == 0x262) {
ipas_state = (to_push->RDLR & 0xf);
}
@@ -97,25 +99,34 @@ static void toyota_ipas_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
static int toyota_ipas_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
+ int tx = 1;
+ int bypass_standard_tx_hook = 0;
+ int bus = GET_BUS(to_send);
+ int addr = GET_ADDR(to_send);
+
// Check if msg is sent on BUS 0
- if (((to_send->RDTR >> 4) & 0xF) == 0) {
+ if (bus == 0) {
// STEER ANGLE
- if (((to_send->RIR>>21) == 0x266) || ((to_send->RIR>>21) == 0x167)) {
+ if ((addr == 0x266) || (addr == 0x167)) {
angle_control = 1; // we are in angle control mode
int desired_angle = ((to_send->RDLR & 0xf) << 8) + ((to_send->RDLR & 0xff00) >> 8);
int ipas_state_cmd = ((to_send->RDLR & 0xff) >> 4);
- int16_t violation = 0;
+ bool violation = 0;
desired_angle = to_signed(desired_angle, 12);
if (controls_allowed) {
// add 1 to not false trigger the violation
- int delta_angle_up = (int) (interpolate(LOOKUP_ANGLE_RATE_UP, speed) * CAN_TO_DEG + 1.);
- int delta_angle_down = (int) (interpolate(LOOKUP_ANGLE_RATE_DOWN, speed) * CAN_TO_DEG + 1.);
- int highest_desired_angle = desired_angle_last + (desired_angle_last > 0? delta_angle_up:delta_angle_down);
- int lowest_desired_angle = desired_angle_last - (desired_angle_last > 0? delta_angle_down:delta_angle_up);
+ float delta_angle_float;
+ delta_angle_float = (interpolate(LOOKUP_ANGLE_RATE_UP, speed) * CAN_TO_DEG) + 1.;
+ int delta_angle_up = (int) (delta_angle_float);
+ delta_angle_float = (interpolate(LOOKUP_ANGLE_RATE_DOWN, speed) * CAN_TO_DEG) + 1.;
+ int delta_angle_down = (int) (delta_angle_float);
+
+ int highest_desired_angle = desired_angle_last + ((desired_angle_last > 0) ? delta_angle_up : delta_angle_down);
+ int lowest_desired_angle = desired_angle_last - ((desired_angle_last > 0) ? delta_angle_down : delta_angle_up);
if ((desired_angle > highest_desired_angle) ||
(desired_angle < lowest_desired_angle)){
violation = 1;
@@ -134,15 +145,18 @@ static int toyota_ipas_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
desired_angle_last = desired_angle;
if (violation) {
- return false;
+ tx = 0;
}
-
- return true;
+ bypass_standard_tx_hook = 1;
}
}
- // check standard toyota stuff as well
- return toyota_tx_hook(to_send);
+ // check standard toyota stuff as well if addr isn't IPAS related
+ if (!bypass_standard_tx_hook) {
+ tx &= toyota_tx_hook(to_send);
+ }
+
+ return tx;
}
const safety_hooks toyota_ipas_hooks = {
diff --git a/panda/board/safety_declarations.h b/panda/board/safety_declarations.h
new file mode 100644
index 000000000..21e863869
--- /dev/null
+++ b/panda/board/safety_declarations.h
@@ -0,0 +1,56 @@
+#define GET_BUS(msg) (((msg)->RDTR >> 4) & 0xFF)
+#define GET_LEN(msg) ((msg)->RDTR & 0xf)
+#define GET_ADDR(msg) ((((msg)->RIR & 4) != 0) ? ((msg)->RIR >> 3) : ((msg)->RIR >> 21))
+
+// sample struct that keeps 3 samples in memory
+struct sample_t {
+ int values[6];
+ int min;
+ int max;
+} sample_t_default = {{0}, 0, 0};
+
+// safety code requires floats
+struct lookup_t {
+ float x[3];
+ float y[3];
+};
+
+void safety_rx_hook(CAN_FIFOMailBox_TypeDef *to_push);
+int safety_tx_hook(CAN_FIFOMailBox_TypeDef *to_send);
+int safety_tx_lin_hook(int lin_num, uint8_t *data, int len);
+int safety_ignition_hook(void);
+uint32_t get_ts_elapsed(uint32_t ts, uint32_t ts_last);
+int to_signed(int d, int bits);
+void update_sample(struct sample_t *sample, int sample_new);
+bool max_limit_check(int val, const int MAX, const int MIN);
+bool dist_to_meas_check(int val, int val_last, struct sample_t *val_meas,
+ const int MAX_RATE_UP, const int MAX_RATE_DOWN, const int MAX_ERROR);
+bool driver_limit_check(int val, int val_last, struct sample_t *val_driver,
+ const int MAX, const int MAX_RATE_UP, const int MAX_RATE_DOWN,
+ const int MAX_ALLOWANCE, const int DRIVER_FACTOR);
+bool rt_rate_limit_check(int val, int val_last, const int MAX_RT_DELTA);
+float interpolate(struct lookup_t xy, float x);
+
+typedef void (*safety_hook_init)(int16_t param);
+typedef void (*rx_hook)(CAN_FIFOMailBox_TypeDef *to_push);
+typedef int (*tx_hook)(CAN_FIFOMailBox_TypeDef *to_send);
+typedef int (*tx_lin_hook)(int lin_num, uint8_t *data, int len);
+typedef int (*ign_hook)(void);
+typedef int (*fwd_hook)(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd);
+
+typedef struct {
+ safety_hook_init init;
+ ign_hook ignition;
+ rx_hook rx;
+ tx_hook tx;
+ tx_lin_hook tx_lin;
+ fwd_hook fwd;
+} safety_hooks;
+
+// This can be set by the safety hooks.
+bool controls_allowed = 0;
+bool gas_interceptor_detected = 0;
+int gas_interceptor_prev = 0;
+
+// This is set by USB command 0xdf
+bool long_controls_allowed = 1;
diff --git a/panda/board/spi_flasher.h b/panda/board/spi_flasher.h
index 48e00aa22..94d41c7e3 100644
--- a/panda/board/spi_flasher.h
+++ b/panda/board/spi_flasher.h
@@ -6,7 +6,7 @@ int unlocked = 0;
void debug_ring_callback(uart_ring *ring) {}
#endif
-int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) {
+int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired) {
int resp_len = 0;
// flasher machine
@@ -80,7 +80,7 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) {
break;
// **** 0xd6: get version
case 0xd6:
- COMPILE_TIME_ASSERT(sizeof(gitversion) <= MAX_RESP_LEN)
+ COMPILE_TIME_ASSERT(sizeof(gitversion) <= MAX_RESP_LEN);
memcpy(resp, gitversion, sizeof(gitversion));
resp_len = sizeof(gitversion);
break;
@@ -92,8 +92,8 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) {
return resp_len;
}
-int usb_cb_ep1_in(uint8_t *usbdata, int len, int hardwired) { return 0; }
-void usb_cb_ep3_out(uint8_t *usbdata, int len, int hardwired) { }
+int usb_cb_ep1_in(uint8_t *usbdata, int len, bool hardwired) { return 0; }
+void usb_cb_ep3_out(uint8_t *usbdata, int len, bool hardwired) { }
int is_enumerated = 0;
void usb_cb_enumeration_complete() {
@@ -101,7 +101,7 @@ void usb_cb_enumeration_complete() {
is_enumerated = 1;
}
-void usb_cb_ep2_out(uint8_t *usbdata, int len, int hardwired) {
+void usb_cb_ep2_out(uint8_t *usbdata, int len, bool hardwired) {
set_led(LED_RED, 0);
for (int i = 0; i < len/4; i++) {
// program byte 1
diff --git a/panda/boardesp/elm327.c b/panda/boardesp/elm327.c
index 6c18c4463..58ac4c863 100644
--- a/panda/boardesp/elm327.c
+++ b/panda/boardesp/elm327.c
@@ -10,8 +10,8 @@
//#define ELM_DEBUG
-#define min(a,b) ((a) < (b) ? (a) : (b))
-#define max(a,b) ((a) > (b) ? (a) : (b))
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
int ICACHE_FLASH_ATTR spi_comm(char *dat, int len, uint32_t *recvData, int recvDataLen);
#define ELM_PORT 35000
@@ -855,7 +855,7 @@ static void ICACHE_FLASH_ATTR elm_process_obd_cmd_LINFast(const elm_protocol_t*
panda_kline_wakeup_pulse();
} else {
- bytelen = min(bytelen, 7);
+ bytelen = MIN(bytelen, 7);
for(int i = 0; i < bytelen; i++){
msg.dat[i] = elm_decode_hex_byte(&cmd[i*2]);
msg.dat[bytelen] += msg.dat[i];
@@ -1059,7 +1059,7 @@ static void ICACHE_FLASH_ATTR elm_process_obd_cmd_ISO15765(const elm_protocol_t*
return;
}
- msg.len = min(msg.len, 7);
+ msg.len = MIN(msg.len, 7);
for(int i = 0; i < msg.len; i++)
msg.dat[i] = elm_decode_hex_byte(&cmd[i*2]);
@@ -1398,7 +1398,7 @@ static void ICACHE_FLASH_ATTR elm_process_at_cmd(char *cmd, uint16_t len) {
}
tmp = elm_decode_hex_byte(&cmd[2]);
- elm_mode_keepalive_period = tmp ? max(tmp, 0x20) * 20 : 0;
+ elm_mode_keepalive_period = tmp ? MAX(tmp, 0x20) * 20 : 0;
if(lin_bus_initialized){
os_timer_disarm(&elm_proto_aux_timeout);
diff --git a/panda/boardesp/proxy.c b/panda/boardesp/proxy.c
index bb89743c1..65586d609 100644
--- a/panda/boardesp/proxy.c
+++ b/panda/boardesp/proxy.c
@@ -9,12 +9,12 @@
#include "driver/uart.h"
#include "crypto/sha.h"
-#define min(a,b) \
+#define MIN(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a < _b ? _a : _b; })
-#define max(a,b) \
+#define MAX(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a > _b ? _a : _b; })
diff --git a/panda/boardesp/webserver.c b/panda/boardesp/webserver.c
index 9266b08f7..f855f88c9 100644
--- a/panda/boardesp/webserver.c
+++ b/panda/boardesp/webserver.c
@@ -14,8 +14,8 @@
#include "obj/gitversion.h"
#include "obj/cert.h"
-#define max(a,b) ((a) > (b) ? (a) : (b))
-#define min(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define espconn_send_string(conn, x) espconn_send(conn, x, strlen(x))
#define MAX_RESP 0x800
@@ -116,7 +116,7 @@ void ICACHE_FLASH_ATTR st_flash() {
// real content length will always be 0x10 aligned
os_printf("st_flash: flashing\n");
for (int i = 0; i < real_content_length; i += 0x10) {
- int rl = min(0x10, real_content_length-i);
+ int rl = MIN(0x10, real_content_length-i);
usb_cmd(2, rl, 0, 0, 0, &st_firmware[i]);
system_soft_wdt_feed();
}
@@ -288,7 +288,7 @@ static void ICACHE_FLASH_ATTR web_rx_cb(void *arg, char *data, uint16_t len) {
}
} else if (state == RECEIVING_ST_FIRMWARE) {
os_printf("receiving st firmware: %d/%d\n", len, content_length);
- memcpy(st_firmware_ptr, data, min(content_length, len));
+ memcpy(st_firmware_ptr, data, MIN(content_length, len));
st_firmware_ptr += len;
content_length -= len;
@@ -333,7 +333,7 @@ static void ICACHE_FLASH_ATTR web_rx_cb(void *arg, char *data, uint16_t len) {
SHA_init(&ctx);
for (ll = start_address; ll < esp_address-RSANUMBYTES; ll += 0x80) {
spi_flash_read(ll, dat, 0x80);
- SHA_update(&ctx, dat, min((esp_address-RSANUMBYTES)-ll, 0x80));
+ SHA_update(&ctx, dat, MIN((esp_address-RSANUMBYTES)-ll, 0x80));
}
memcpy(digest, SHA_final(&ctx), SHA_DIGEST_SIZE);
diff --git a/panda/drivers/windows/pandaJ2534DLL/MessageRx.h b/panda/drivers/windows/pandaJ2534DLL/MessageRx.h
index e22278d4d..2af24364f 100644
--- a/panda/drivers/windows/pandaJ2534DLL/MessageRx.h
+++ b/panda/drivers/windows/pandaJ2534DLL/MessageRx.h
@@ -21,7 +21,7 @@ public:
}
this->next_part = (this->next_part + 1) % 0x10;
- unsigned int payload_len = min(expected_size - msg.size(), max_packet_size);
+ unsigned int payload_len = MIN(expected_size - msg.size(), max_packet_size);
if (piece.size() < payload_len) {
//A frame was received that could have held more data.
//No examples of this protocol show that happening, so
diff --git a/panda/drivers/windows/pandaJ2534DLL/PandaJ2534Device.cpp b/panda/drivers/windows/pandaJ2534DLL/PandaJ2534Device.cpp
index 1b961579e..4cda1fa2e 100644
--- a/panda/drivers/windows/pandaJ2534DLL/PandaJ2534Device.cpp
+++ b/panda/drivers/windows/pandaJ2534DLL/PandaJ2534Device.cpp
@@ -170,7 +170,7 @@ DWORD PandaJ2534Device::msg_tx_thread() {
} else { //Ran out of things that need to be sent now. Sleep!
auto time_diff = std::chrono::duration_cast
(this->task_queue.front()->expire - std::chrono::steady_clock::now());
- sleepDuration = max(1, time_diff.count());
+ sleepDuration = MAX(1, time_diff.count());
goto break_flow_ctrl_loop;
}
}
diff --git a/panda/python/dfu.py b/panda/python/dfu.py
index 782b4dca4..02deed47b 100644
--- a/panda/python/dfu.py
+++ b/panda/python/dfu.py
@@ -18,7 +18,7 @@ class PandaDFU(object):
for device in context.getDeviceList(skip_on_error=True):
if device.getVendorID() == 0x0483 and device.getProductID() == 0xdf11:
try:
- this_dfu_serial = device._getASCIIStringDescriptor(3)
+ this_dfu_serial = device.open().getASCIIStringDescriptor(3)
except Exception:
continue
if this_dfu_serial == dfu_serial or dfu_serial is None:
@@ -35,7 +35,7 @@ class PandaDFU(object):
for device in context.getDeviceList(skip_on_error=True):
if device.getVendorID() == 0x0483 and device.getProductID() == 0xdf11:
try:
- dfu_serials.append(device._getASCIIStringDescriptor(3))
+ dfu_serials.append(device.open().getASCIIStringDescriptor(3))
except Exception:
pass
except Exception:
@@ -73,7 +73,7 @@ class PandaDFU(object):
def program(self, address, dat, block_size=None):
if block_size == None:
block_size = len(dat)
-
+
# Set Address Pointer
self._handle.controlWrite(0x21, DFU_DNLOAD, 0, 0, "\x21" + struct.pack("I", address))
self.status()
@@ -119,4 +119,3 @@ class PandaDFU(object):
stat = str(self._handle.controlRead(0x21, DFU_GETSTATUS, 0, 0, 6))
except Exception:
pass
-
diff --git a/panda/python/esptool.py b/panda/python/esptool.py
index 970aa3d4d..e68e6cd6e 100755
--- a/panda/python/esptool.py
+++ b/panda/python/esptool.py
@@ -1216,7 +1216,7 @@ def main():
operation_func = globals()[args.operation]
operation_args,_,_,_ = inspect.getargspec(operation_func)
if operation_args[0] == 'esp': # operation function takes an ESPROM connection object
- initial_baud = min(ESPROM.ESP_ROM_BAUD, args.baud) # don't sync faster than the default baud rate
+ initial_baud = MIN(ESPROM.ESP_ROM_BAUD, args.baud) # don't sync faster than the default baud rate
esp = ESPROM(args.port, initial_baud)
esp.connect()
operation_func(esp, args)
diff --git a/panda/tests/automated/5_wifi_udp.py b/panda/tests/automated/5_wifi_udp.py
index d55baa659..873f78bdb 100644
--- a/panda/tests/automated/5_wifi_udp.py
+++ b/panda/tests/automated/5_wifi_udp.py
@@ -34,7 +34,7 @@ def test_udp_doesnt_drop(serial=None):
sys.stdout.flush()
else:
print("UDP WIFI loopback %d messages at speed %d, comp speed is %.2f, percent %.2f" % (msg_count, speed, comp_kbps, saturation_pct))
- assert_greater(saturation_pct, 20) #sometimes the wifi can be slow...
+ assert_greater(saturation_pct, 15) #sometimes the wifi can be slow...
assert_less(saturation_pct, 100)
saturation_pcts.append(saturation_pct)
if len(saturation_pcts) > 0:
diff --git a/panda/tests/build_strict/test_build_strict.sh b/panda/tests/build_strict/test_build_strict.sh
new file mode 100755
index 000000000..ee57ba8ad
--- /dev/null
+++ b/panda/tests/build_strict/test_build_strict.sh
@@ -0,0 +1,15 @@
+#!/bin/bash -e
+
+cd ../../board/
+
+make -f Makefile.strict clean
+make -f Makefile.strict bin 2> compiler_output.txt
+
+
+if [[ -s "compiler_output.txt" ]]
+then
+ echo "Found alerts from the compiler:"
+ cat compiler_output.txt
+ exit 1
+fi
+
diff --git a/panda/tests/elm_car_simulator.py b/panda/tests/elm_car_simulator.py
index f931e66ff..bcee821cd 100755
--- a/panda/tests/elm_car_simulator.py
+++ b/panda/tests/elm_car_simulator.py
@@ -152,7 +152,7 @@ class ELMCarSimulator():
if len(outmsg) <= 5:
self._lin_send(0x10, obd_header + outmsg)
else:
- first_msg_len = min(4, len(outmsg)%4) or 4
+ first_msg_len = MIN(4, len(outmsg)%4) or 4
self._lin_send(0x10, obd_header + b'\x01' +
b'\x00'*(4-first_msg_len) +
outmsg[:first_msg_len])
@@ -229,7 +229,7 @@ class ELMCarSimulator():
outaddr = 0x7E8 if address == 0x7DF or address == 0x7E0 else 0x18DAF110
msgnum = 1
while(self.__can_multipart_data):
- datalen = min(7, len(self.__can_multipart_data))
+ datalen = MIN(7, len(self.__can_multipart_data))
msgpiece = struct.pack("B", 0x20 | msgnum) + self.__can_multipart_data[:datalen]
self._can_send(outaddr, msgpiece)
self.__can_multipart_data = self.__can_multipart_data[7:]
@@ -246,7 +246,7 @@ class ELMCarSimulator():
self._can_send(outaddr,
struct.pack("BBB", len(outmsg)+2, 0x40|data[1], pid) + outmsg)
else:
- first_msg_len = min(3, len(outmsg)%7)
+ first_msg_len = MIN(3, len(outmsg)%7)
payload_len = len(outmsg)+3
msgpiece = struct.pack("BBBBB", 0x10 | ((payload_len>>8)&0xF),
payload_len&0xFF,
diff --git a/panda/tests/misra/test_misra.sh b/panda/tests/misra/test_misra.sh
index 5d2650dc0..835f4ebcf 100755
--- a/panda/tests/misra/test_misra.sh
+++ b/panda/tests/misra/test_misra.sh
@@ -1,8 +1,24 @@
#!/bin/bash -e
+
git clone https://github.com/danmar/cppcheck.git || true
cd cppcheck
-git checkout 29e5992e51ecf1ddba469c73a0eed0b28b131de5
+git fetch
+git checkout 44d6066c6fad32e2b0332b3f2b24bd340febaef8
make -j4
cd ../../../
-tests/misra/cppcheck/cppcheck --dump board/main.c
-python tests/misra/cppcheck/addons/misra.py board/main.c.dump 2>/tmp/misra/output.txt || true
+
+# whole panda code
+tests/misra/cppcheck/cppcheck --dump --enable=all --inline-suppr board/main.c 2>/tmp/misra/cppcheck_output.txt || true
+python tests/misra/cppcheck/addons/misra.py board/main.c.dump 2>/tmp/misra/misra_output.txt || true
+
+# violations in safety files
+(cat /tmp/misra/misra_output.txt | grep safety) > /tmp/misra/misra_safety_output.txt || true
+(cat /tmp/misra/cppcheck_output.txt | grep safety) > /tmp/misra/cppcheck_safety_output.txt || true
+
+if [[ -s "/tmp/misra/misra_safety_output.txt" ]] || [[ -s "/tmp/misra/cppcheck_safety_output.txt" ]]
+then
+ echo "Found Misra violations in the safety code:"
+ cat /tmp/misra/misra_safety_output.txt
+ cat /tmp/misra/cppcheck_safety_output.txt
+ exit 1
+fi
diff --git a/pyextra/gunicorn/instrument/__init__.py b/panda/tests/safety/__init__.py
similarity index 100%
rename from pyextra/gunicorn/instrument/__init__.py
rename to panda/tests/safety/__init__.py
diff --git a/panda/tests/safety/libpandasafety_py.py b/panda/tests/safety/libpandasafety_py.py
index 84f3b00d0..dc5e5be5a 100644
--- a/panda/tests/safety/libpandasafety_py.py
+++ b/panda/tests/safety/libpandasafety_py.py
@@ -30,76 +30,63 @@ typedef struct
uint32_t CNT;
} TIM_TypeDef;
-void set_controls_allowed(int c);
-int get_controls_allowed(void);
-void set_long_controls_allowed(int c);
-int get_long_controls_allowed(void);
-void set_gas_interceptor_detected(int c);
-int get_gas_interceptor_detetcted(void);
+void set_controls_allowed(bool c);
+bool get_controls_allowed(void);
+void set_long_controls_allowed(bool c);
+bool get_long_controls_allowed(void);
+void set_gas_interceptor_detected(bool c);
+bool get_gas_interceptor_detetcted(void);
int get_gas_interceptor_prev(void);
-void set_timer(int t);
+void set_timer(uint32_t t);
void reset_angle_control(void);
+void safety_rx_hook(CAN_FIFOMailBox_TypeDef *to_send);
+int safety_tx_hook(CAN_FIFOMailBox_TypeDef *to_push);
+int safety_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd);
+int safety_set_mode(uint16_t mode, int16_t param);
+
void init_tests_toyota(void);
-void toyota_rx_hook(CAN_FIFOMailBox_TypeDef *to_push);
-int toyota_tx_hook(CAN_FIFOMailBox_TypeDef *to_send);
-void toyota_init(int16_t param);
int get_toyota_torque_meas_min(void);
int get_toyota_torque_meas_max(void);
int get_toyota_gas_prev(void);
void set_toyota_torque_meas(int min, int max);
void set_toyota_desired_torque_last(int t);
+void set_toyota_camera_forwarded(int t);
void set_toyota_rt_torque_last(int t);
void init_tests_honda(void);
int get_honda_ego_speed(void);
-void honda_init(int16_t param);
-void honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push);
-int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send);
int get_honda_brake_prev(void);
int get_honda_gas_prev(void);
void set_honda_alt_brake_msg(bool);
void set_honda_bosch_hardware(bool);
void init_tests_cadillac(void);
-void cadillac_init(int16_t param);
-void cadillac_rx_hook(CAN_FIFOMailBox_TypeDef *to_push);
-int cadillac_tx_hook(CAN_FIFOMailBox_TypeDef *to_send);
void set_cadillac_desired_torque_last(int t);
void set_cadillac_rt_torque_last(int t);
void set_cadillac_torque_driver(int min, int max);
void init_tests_gm(void);
-void gm_init(int16_t param);
-void gm_rx_hook(CAN_FIFOMailBox_TypeDef *to_push);
-int gm_tx_hook(CAN_FIFOMailBox_TypeDef *to_send);
void set_gm_desired_torque_last(int t);
void set_gm_rt_torque_last(int t);
void set_gm_torque_driver(int min, int max);
void init_tests_hyundai(void);
-void nooutput_init(int16_t param);
-void hyundai_rx_hook(CAN_FIFOMailBox_TypeDef *to_push);
-int hyundai_tx_hook(CAN_FIFOMailBox_TypeDef *to_send);
void set_hyundai_desired_torque_last(int t);
void set_hyundai_rt_torque_last(int t);
void set_hyundai_torque_driver(int min, int max);
-
-void toyota_ipas_rx_hook(CAN_FIFOMailBox_TypeDef *to_push);
-int toyota_ipas_tx_hook(CAN_FIFOMailBox_TypeDef *to_send);
+void set_hyundai_giraffe_switch_2(int t);
+void set_hyundai_camera_bus(int t);
void init_tests_chrysler(void);
-void chrysler_rx_hook(CAN_FIFOMailBox_TypeDef *to_push);
-int chrysler_tx_hook(CAN_FIFOMailBox_TypeDef *to_send);
void set_chrysler_desired_torque_last(int t);
void set_chrysler_rt_torque_last(int t);
+void set_chrysler_camera_detected(int t);
int get_chrysler_torque_meas_min(void);
int get_chrysler_torque_meas_max(void);
void set_chrysler_torque_meas(int min, int max);
void init_tests_subaru(void);
-void subaru_rx_hook(CAN_FIFOMailBox_TypeDef *to_push);
-int subaru_tx_hook(CAN_FIFOMailBox_TypeDef *to_send);
void set_subaru_desired_torque_last(int t);
void set_subaru_rt_torque_last(int t);
void set_subaru_torque_driver(int min, int max);
diff --git a/panda/tests/safety/test.c b/panda/tests/safety/test.c
index ce75df82a..be13d346a 100644
--- a/panda/tests/safety/test.c
+++ b/panda/tests/safety/test.c
@@ -32,30 +32,32 @@ struct sample_t subaru_torque_driver;
TIM_TypeDef timer;
TIM_TypeDef *TIM2 = &timer;
-#define min(a,b) \
+#define MIN(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a < _b ? _a : _b; })
-#define max(a,b) \
+#define MAX(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a > _b ? _a : _b; })
+#define UNUSED(x) (void)(x)
#define PANDA
+#define NULL ((void*)0)
#define static
#include "safety.h"
-void set_controls_allowed(int c){
+void set_controls_allowed(bool c){
controls_allowed = c;
}
-void set_long_controls_allowed(int c){
+void set_long_controls_allowed(bool c){
long_controls_allowed = c;
}
-void set_gas_interceptor_detected(int c){
+void set_gas_interceptor_detected(bool c){
gas_interceptor_detected = c;
}
@@ -63,15 +65,15 @@ void reset_angle_control(void){
angle_control = 0;
}
-int get_controls_allowed(void){
+bool get_controls_allowed(void){
return controls_allowed;
}
-int get_long_controls_allowed(void){
+bool get_long_controls_allowed(void){
return long_controls_allowed;
}
-int get_gas_interceptor_detected(void){
+bool get_gas_interceptor_detected(void){
return gas_interceptor_detected;
}
@@ -79,10 +81,14 @@ int get_gas_interceptor_prev(void){
return gas_interceptor_prev;
}
-void set_timer(int t){
+void set_timer(uint32_t t){
timer.CNT = t;
}
+void set_toyota_camera_forwarded(int t){
+ toyota_camera_forwarded = t;
+}
+
void set_toyota_torque_meas(int min, int max){
toyota_torque_meas.min = min;
toyota_torque_meas.max = max;
@@ -103,6 +109,18 @@ void set_hyundai_torque_driver(int min, int max){
hyundai_torque_driver.max = max;
}
+void set_hyundai_camera_bus(int t){
+ hyundai_camera_bus = t;
+}
+
+void set_hyundai_giraffe_switch_2(int t){
+ hyundai_giraffe_switch_2 = t;
+}
+
+void set_chrysler_camera_detected(int t){
+ chrysler_camera_detected = t;
+}
+
void set_chrysler_torque_meas(int min, int max){
chrysler_torque_meas.min = min;
chrysler_torque_meas.max = max;
diff --git a/panda/tests/safety/test_cadillac.py b/panda/tests/safety/test_cadillac.py
index 53c943e96..af89e69cc 100644
--- a/panda/tests/safety/test_cadillac.py
+++ b/panda/tests/safety/test_cadillac.py
@@ -31,9 +31,16 @@ class TestCadillacSafety(unittest.TestCase):
@classmethod
def setUp(cls):
cls.safety = libpandasafety_py.libpandasafety
- cls.safety.cadillac_init(0)
+ cls.safety.safety_set_mode(6, 0)
cls.safety.init_tests_cadillac()
+ def _send_msg(self, bus, addr, length):
+ to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
+ to_send[0].RIR = addr << 21
+ to_send[0].RDTR = length
+ to_send[0].RDTR = bus << 4
+ return to_send
+
def _set_prev_torque(self, t):
self.safety.set_cadillac_desired_torque_last(t)
self.safety.set_cadillac_rt_torque_last(t)
@@ -46,10 +53,6 @@ class TestCadillacSafety(unittest.TestCase):
to_send[0].RDLR = ((t >> 8) & 0x7) | ((t & 0xFF) << 8)
return to_send
- def _torque_driver_msg_array(self, torque):
- for i in range(3):
- self.safety.cadillac_ipas_rx_hook(self._torque_driver_msg(torque))
-
def _torque_msg(self, torque):
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
to_send[0].RIR = 0x151 << 21
@@ -72,7 +75,7 @@ class TestCadillacSafety(unittest.TestCase):
to_push[0].RDLR = 0x800000
to_push[0].RDTR = 0
- self.safety.cadillac_rx_hook(to_push)
+ self.safety.safety_rx_hook(to_push)
self.assertTrue(self.safety.get_controls_allowed())
def test_disable_control_allowed_from_cruise(self):
@@ -82,7 +85,7 @@ class TestCadillacSafety(unittest.TestCase):
to_push[0].RDTR = 0
self.safety.set_controls_allowed(1)
- self.safety.cadillac_rx_hook(to_push)
+ self.safety.safety_rx_hook(to_push)
self.assertFalse(self.safety.get_controls_allowed())
def test_torque_absolute_limits(self):
@@ -98,22 +101,22 @@ class TestCadillacSafety(unittest.TestCase):
else:
send = torque == 0
- self.assertEqual(send, self.safety.cadillac_tx_hook(self._torque_msg(torque)))
+ self.assertEqual(send, self.safety.safety_tx_hook(self._torque_msg(torque)))
def test_non_realtime_limit_up(self):
self.safety.set_cadillac_torque_driver(0, 0)
self.safety.set_controls_allowed(True)
self._set_prev_torque(0)
- self.assertTrue(self.safety.cadillac_tx_hook(self._torque_msg(MAX_RATE_UP)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(MAX_RATE_UP)))
self._set_prev_torque(0)
- self.assertTrue(self.safety.cadillac_tx_hook(self._torque_msg(-MAX_RATE_UP)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(-MAX_RATE_UP)))
self._set_prev_torque(0)
- self.assertFalse(self.safety.cadillac_tx_hook(self._torque_msg(MAX_RATE_UP + 1)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(MAX_RATE_UP + 1)))
self.safety.set_controls_allowed(True)
self._set_prev_torque(0)
- self.assertFalse(self.safety.cadillac_tx_hook(self._torque_msg(-MAX_RATE_UP - 1)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(-MAX_RATE_UP - 1)))
def test_non_realtime_limit_down(self):
self.safety.set_cadillac_torque_driver(0, 0)
@@ -127,10 +130,10 @@ class TestCadillacSafety(unittest.TestCase):
t *= -sign
self.safety.set_cadillac_torque_driver(t, t)
self._set_prev_torque(MAX_TORQUE * sign)
- self.assertTrue(self.safety.cadillac_tx_hook(self._torque_msg(MAX_TORQUE * sign)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(MAX_TORQUE * sign)))
self.safety.set_cadillac_torque_driver(DRIVER_TORQUE_ALLOWANCE + 1, DRIVER_TORQUE_ALLOWANCE + 1)
- self.assertFalse(self.safety.cadillac_tx_hook(self._torque_msg(-MAX_TORQUE)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(-MAX_TORQUE)))
# spot check some individual cases
for sign in [-1, 1]:
@@ -139,20 +142,20 @@ class TestCadillacSafety(unittest.TestCase):
delta = 1 * sign
self._set_prev_torque(torque_desired)
self.safety.set_cadillac_torque_driver(-driver_torque, -driver_torque)
- self.assertTrue(self.safety.cadillac_tx_hook(self._torque_msg(torque_desired)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(torque_desired)))
self._set_prev_torque(torque_desired + delta)
self.safety.set_cadillac_torque_driver(-driver_torque, -driver_torque)
- self.assertFalse(self.safety.cadillac_tx_hook(self._torque_msg(torque_desired + delta)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(torque_desired + delta)))
self._set_prev_torque(MAX_TORQUE * sign)
self.safety.set_cadillac_torque_driver(-MAX_TORQUE * sign, -MAX_TORQUE * sign)
- self.assertTrue(self.safety.cadillac_tx_hook(self._torque_msg((MAX_TORQUE - MAX_RATE_DOWN) * sign)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg((MAX_TORQUE - MAX_RATE_DOWN) * sign)))
self._set_prev_torque(MAX_TORQUE * sign)
self.safety.set_cadillac_torque_driver(-MAX_TORQUE * sign, -MAX_TORQUE * sign)
- self.assertTrue(self.safety.cadillac_tx_hook(self._torque_msg(0)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(0)))
self._set_prev_torque(MAX_TORQUE * sign)
self.safety.set_cadillac_torque_driver(-MAX_TORQUE * sign, -MAX_TORQUE * sign)
- self.assertFalse(self.safety.cadillac_tx_hook(self._torque_msg((MAX_TORQUE - MAX_RATE_DOWN + 1) * sign)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg((MAX_TORQUE - MAX_RATE_DOWN + 1) * sign)))
def test_realtime_limits(self):
@@ -164,18 +167,29 @@ class TestCadillacSafety(unittest.TestCase):
self.safety.set_cadillac_torque_driver(0, 0)
for t in np.arange(0, MAX_RT_DELTA, 1):
t *= sign
- self.assertTrue(self.safety.cadillac_tx_hook(self._torque_msg(t)))
- self.assertFalse(self.safety.cadillac_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA + 1))))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(t)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA + 1))))
self._set_prev_torque(0)
for t in np.arange(0, MAX_RT_DELTA, 1):
t *= sign
- self.assertTrue(self.safety.cadillac_tx_hook(self._torque_msg(t)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(t)))
# Increase timer to update rt_torque_last
self.safety.set_timer(RT_INTERVAL + 1)
- self.assertTrue(self.safety.cadillac_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA - 1))))
- self.assertTrue(self.safety.cadillac_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA + 1))))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA - 1))))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA + 1))))
+
+
+ def test_fwd_hook(self):
+ # nothing allowed
+ buss = range(0x0, 0x3)
+ msgs = range(0x1, 0x800)
+
+ for b in buss:
+ for m in msgs:
+ # assume len 8
+ self.assertEqual(-1, self.safety.safety_fwd_hook(b, self._send_msg(b, m, 8)))
if __name__ == "__main__":
diff --git a/panda/tests/safety/test_chrysler.py b/panda/tests/safety/test_chrysler.py
index 0fcfc3bcf..09aa424dd 100755
--- a/panda/tests/safety/test_chrysler.py
+++ b/panda/tests/safety/test_chrysler.py
@@ -35,9 +35,16 @@ class TestChryslerSafety(unittest.TestCase):
@classmethod
def setUp(cls):
cls.safety = libpandasafety_py.libpandasafety
- cls.safety.nooutput_init(0)
+ cls.safety.safety_set_mode(9, 0)
cls.safety.init_tests_chrysler()
+ def _send_msg(self, bus, addr, length):
+ to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
+ to_send[0].RIR = addr << 21
+ to_send[0].RDTR = length
+ to_send[0].RDTR = bus << 4
+ return to_send
+
def _button_msg(self, buttons):
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
to_send[0].RIR = 1265 << 21
@@ -70,9 +77,9 @@ class TestChryslerSafety(unittest.TestCase):
self.safety.set_controls_allowed(enabled)
self._set_prev_torque(t)
if abs(t) > MAX_STEER or (not enabled and abs(t) > 0):
- self.assertFalse(self.safety.chrysler_tx_hook(self._torque_msg(t)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(t)))
else:
- self.assertTrue(self.safety.chrysler_tx_hook(self._torque_msg(t)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(t)))
def test_manually_enable_controls_allowed(self):
self.safety.set_controls_allowed(1)
@@ -85,7 +92,7 @@ class TestChryslerSafety(unittest.TestCase):
to_push[0].RIR = 0x1f4 << 21
to_push[0].RDLR = 0x380000
- self.safety.chrysler_rx_hook(to_push)
+ self.safety.safety_rx_hook(to_push)
self.assertTrue(self.safety.get_controls_allowed())
def test_disable_control_allowed_from_cruise(self):
@@ -94,17 +101,17 @@ class TestChryslerSafety(unittest.TestCase):
to_push[0].RDLR = 0
self.safety.set_controls_allowed(1)
- self.safety.chrysler_rx_hook(to_push)
+ self.safety.safety_rx_hook(to_push)
self.assertFalse(self.safety.get_controls_allowed())
def test_non_realtime_limit_up(self):
self.safety.set_controls_allowed(True)
self._set_prev_torque(0)
- self.assertTrue(self.safety.chrysler_tx_hook(self._torque_msg(MAX_RATE_UP)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(MAX_RATE_UP)))
self._set_prev_torque(0)
- self.assertFalse(self.safety.chrysler_tx_hook(self._torque_msg(MAX_RATE_UP + 1)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(MAX_RATE_UP + 1)))
def test_non_realtime_limit_down(self):
self.safety.set_controls_allowed(True)
@@ -113,12 +120,12 @@ class TestChryslerSafety(unittest.TestCase):
torque_meas = MAX_STEER - MAX_TORQUE_ERROR - 20
self.safety.set_chrysler_torque_meas(torque_meas, torque_meas)
self.safety.set_chrysler_desired_torque_last(MAX_STEER)
- self.assertTrue(self.safety.chrysler_tx_hook(self._torque_msg(MAX_STEER - MAX_RATE_DOWN)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(MAX_STEER - MAX_RATE_DOWN)))
self.safety.set_chrysler_rt_torque_last(MAX_STEER)
self.safety.set_chrysler_torque_meas(torque_meas, torque_meas)
self.safety.set_chrysler_desired_torque_last(MAX_STEER)
- self.assertFalse(self.safety.chrysler_tx_hook(self._torque_msg(MAX_STEER - MAX_RATE_DOWN + 1)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(MAX_STEER - MAX_RATE_DOWN + 1)))
def test_exceed_torque_sensor(self):
self.safety.set_controls_allowed(True)
@@ -127,9 +134,9 @@ class TestChryslerSafety(unittest.TestCase):
self._set_prev_torque(0)
for t in np.arange(0, MAX_TORQUE_ERROR + 2, 2): # step needs to be smaller than MAX_TORQUE_ERROR
t *= sign
- self.assertTrue(self.safety.chrysler_tx_hook(self._torque_msg(t)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(t)))
- self.assertFalse(self.safety.chrysler_tx_hook(self._torque_msg(sign * (MAX_TORQUE_ERROR + 2))))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(sign * (MAX_TORQUE_ERROR + 2))))
def test_realtime_limit_up(self):
self.safety.set_controls_allowed(True)
@@ -140,65 +147,61 @@ class TestChryslerSafety(unittest.TestCase):
for t in np.arange(0, MAX_RT_DELTA+1, 1):
t *= sign
self.safety.set_chrysler_torque_meas(t, t)
- self.assertTrue(self.safety.chrysler_tx_hook(self._torque_msg(t)))
- self.assertFalse(self.safety.chrysler_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA + 1))))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(t)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA + 1))))
self._set_prev_torque(0)
for t in np.arange(0, MAX_RT_DELTA+1, 1):
t *= sign
self.safety.set_chrysler_torque_meas(t, t)
- self.assertTrue(self.safety.chrysler_tx_hook(self._torque_msg(t)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(t)))
# Increase timer to update rt_torque_last
self.safety.set_timer(RT_INTERVAL + 1)
- self.assertTrue(self.safety.chrysler_tx_hook(self._torque_msg(sign * MAX_RT_DELTA)))
- self.assertTrue(self.safety.chrysler_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA + 1))))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(sign * MAX_RT_DELTA)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA + 1))))
def test_torque_measurements(self):
- self.safety.chrysler_rx_hook(self._torque_meas_msg(50))
- self.safety.chrysler_rx_hook(self._torque_meas_msg(-50))
- self.safety.chrysler_rx_hook(self._torque_meas_msg(0))
- self.safety.chrysler_rx_hook(self._torque_meas_msg(0))
- self.safety.chrysler_rx_hook(self._torque_meas_msg(0))
- self.safety.chrysler_rx_hook(self._torque_meas_msg(0))
+ self.safety.safety_rx_hook(self._torque_meas_msg(50))
+ self.safety.safety_rx_hook(self._torque_meas_msg(-50))
+ self.safety.safety_rx_hook(self._torque_meas_msg(0))
+ self.safety.safety_rx_hook(self._torque_meas_msg(0))
+ self.safety.safety_rx_hook(self._torque_meas_msg(0))
+ self.safety.safety_rx_hook(self._torque_meas_msg(0))
self.assertEqual(-50, self.safety.get_chrysler_torque_meas_min())
self.assertEqual(50, self.safety.get_chrysler_torque_meas_max())
- self.safety.chrysler_rx_hook(self._torque_meas_msg(0))
+ self.safety.safety_rx_hook(self._torque_meas_msg(0))
self.assertEqual(0, self.safety.get_chrysler_torque_meas_max())
self.assertEqual(-50, self.safety.get_chrysler_torque_meas_min())
- self.safety.chrysler_rx_hook(self._torque_meas_msg(0))
+ self.safety.safety_rx_hook(self._torque_meas_msg(0))
self.assertEqual(0, self.safety.get_chrysler_torque_meas_max())
self.assertEqual(0, self.safety.get_chrysler_torque_meas_min())
- def _replay_drive(self, csv_reader):
- for row in csv_reader:
- if len(row) != 4: # sometimes truncated at end of the file
- continue
- if row[0] == 'time': # skip CSV header
- continue
- addr = int(row[1])
- bus = int(row[2])
- data_str = row[3] # Example '081407ff0806e06f'
- to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
- to_send[0].RIR = addr << 21
- to_send[0].RDHR = swap_bytes(data_str[8:])
- to_send[0].RDLR = swap_bytes(data_str[:8])
- if (bus == 128):
- self.assertTrue(self.safety.chrysler_tx_hook(to_send), msg=row)
- else:
- self.safety.chrysler_rx_hook(to_send)
+ def test_fwd_hook(self):
+ buss = range(0x0, 0x3)
+ msgs = range(0x1, 0x800)
+ chrysler_camera_detected = [0, 1]
- def test_replay_drive(self):
- # In Cabana, click "Save Log" and then put the downloaded CSV in this directory.
- test_files = glob.glob('chrysler_*.csv')
- for filename in test_files:
- print 'testing %s' % filename
- with open(filename) as csvfile:
- reader = csv.reader(csvfile)
- self._replay_drive(reader)
+ for ccd in chrysler_camera_detected:
+ self.safety.set_chrysler_camera_detected(ccd)
+ blocked_msgs = [658, 678]
+ for b in buss:
+ for m in msgs:
+ if not ccd:
+ if b == 0:
+ fwd_bus = 2
+ elif b == 1:
+ fwd_bus = -1
+ elif b == 2:
+ fwd_bus = -1 if m in blocked_msgs else 0
+ else:
+ fwd_bus = -1
+
+ # assume len 8
+ self.assertEqual(fwd_bus, self.safety.safety_fwd_hook(b, self._send_msg(b, m, 8)))
if __name__ == "__main__":
diff --git a/panda/tests/safety/test_gm.py b/panda/tests/safety/test_gm.py
index ecdf40fed..d9a1d39ec 100644
--- a/panda/tests/safety/test_gm.py
+++ b/panda/tests/safety/test_gm.py
@@ -32,9 +32,16 @@ class TestGmSafety(unittest.TestCase):
@classmethod
def setUp(cls):
cls.safety = libpandasafety_py.libpandasafety
- cls.safety.gm_init(0)
+ cls.safety.safety_set_mode(3, 0)
cls.safety.init_tests_gm()
+ def _send_msg(self, bus, addr, length):
+ to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
+ to_send[0].RIR = addr << 21
+ to_send[0].RDTR = length
+ to_send[0].RDTR = bus << 4
+ return to_send
+
def _speed_msg(self, speed):
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
to_send[0].RIR = 842 << 21
@@ -98,62 +105,62 @@ class TestGmSafety(unittest.TestCase):
def test_resume_button(self):
RESUME_BTN = 2
self.safety.set_controls_allowed(0)
- self.safety.gm_rx_hook(self._button_msg(RESUME_BTN))
+ self.safety.safety_rx_hook(self._button_msg(RESUME_BTN))
self.assertTrue(self.safety.get_controls_allowed())
def test_set_button(self):
SET_BTN = 3
self.safety.set_controls_allowed(0)
- self.safety.gm_rx_hook(self._button_msg(SET_BTN))
+ self.safety.safety_rx_hook(self._button_msg(SET_BTN))
self.assertTrue(self.safety.get_controls_allowed())
def test_cancel_button(self):
CANCEL_BTN = 6
self.safety.set_controls_allowed(1)
- self.safety.gm_rx_hook(self._button_msg(CANCEL_BTN))
+ self.safety.safety_rx_hook(self._button_msg(CANCEL_BTN))
self.assertFalse(self.safety.get_controls_allowed())
def test_disengage_on_brake(self):
self.safety.set_controls_allowed(1)
- self.safety.gm_rx_hook(self._brake_msg(True))
+ self.safety.safety_rx_hook(self._brake_msg(True))
self.assertFalse(self.safety.get_controls_allowed())
def test_allow_brake_at_zero_speed(self):
# Brake was already pressed
- self.safety.gm_rx_hook(self._brake_msg(True))
+ self.safety.safety_rx_hook(self._brake_msg(True))
self.safety.set_controls_allowed(1)
- self.safety.gm_rx_hook(self._brake_msg(True))
+ self.safety.safety_rx_hook(self._brake_msg(True))
self.assertTrue(self.safety.get_controls_allowed())
- self.safety.gm_rx_hook(self._brake_msg(False))
+ self.safety.safety_rx_hook(self._brake_msg(False))
def test_not_allow_brake_when_moving(self):
# Brake was already pressed
- self.safety.gm_rx_hook(self._brake_msg(True))
- self.safety.gm_rx_hook(self._speed_msg(100))
+ self.safety.safety_rx_hook(self._brake_msg(True))
+ self.safety.safety_rx_hook(self._speed_msg(100))
self.safety.set_controls_allowed(1)
- self.safety.gm_rx_hook(self._brake_msg(True))
+ self.safety.safety_rx_hook(self._brake_msg(True))
self.assertFalse(self.safety.get_controls_allowed())
- self.safety.gm_rx_hook(self._brake_msg(False))
+ self.safety.safety_rx_hook(self._brake_msg(False))
def test_disengage_on_gas(self):
for long_controls_allowed in [0, 1]:
self.safety.set_long_controls_allowed(long_controls_allowed)
self.safety.set_controls_allowed(1)
- self.safety.gm_rx_hook(self._gas_msg(True))
+ self.safety.safety_rx_hook(self._gas_msg(True))
if long_controls_allowed:
self.assertFalse(self.safety.get_controls_allowed())
else:
self.assertTrue(self.safety.get_controls_allowed())
- self.safety.gm_rx_hook(self._gas_msg(False))
+ self.safety.safety_rx_hook(self._gas_msg(False))
def test_allow_engage_with_gas_pressed(self):
- self.safety.gm_rx_hook(self._gas_msg(True))
+ self.safety.safety_rx_hook(self._gas_msg(True))
self.safety.set_controls_allowed(1)
- self.safety.gm_rx_hook(self._gas_msg(True))
+ self.safety.safety_rx_hook(self._gas_msg(True))
self.assertTrue(self.safety.get_controls_allowed())
- self.safety.gm_rx_hook(self._gas_msg(False))
+ self.safety.safety_rx_hook(self._gas_msg(False))
def test_brake_safety_check(self):
for long_controls_allowed in [0, 1]:
@@ -162,9 +169,9 @@ class TestGmSafety(unittest.TestCase):
for b in range(0, 500):
self.safety.set_controls_allowed(enabled)
if abs(b) > MAX_BRAKE or ((not enabled or not long_controls_allowed) and b != 0):
- self.assertFalse(self.safety.gm_tx_hook(self._send_brake_msg(b)))
+ self.assertFalse(self.safety.safety_tx_hook(self._send_brake_msg(b)))
else:
- self.assertTrue(self.safety.gm_tx_hook(self._send_brake_msg(b)))
+ self.assertTrue(self.safety.safety_tx_hook(self._send_brake_msg(b)))
self.safety.set_long_controls_allowed(True)
def test_gas_safety_check(self):
@@ -174,9 +181,9 @@ class TestGmSafety(unittest.TestCase):
for g in range(0, 2**12-1):
self.safety.set_controls_allowed(enabled)
if abs(g) > MAX_GAS or ((not enabled or not long_controls_allowed) and g != MAX_REGEN):
- self.assertFalse(self.safety.gm_tx_hook(self._send_gas_msg(g)))
+ self.assertFalse(self.safety.safety_tx_hook(self._send_gas_msg(g)))
else:
- self.assertTrue(self.safety.gm_tx_hook(self._send_gas_msg(g)))
+ self.assertTrue(self.safety.safety_tx_hook(self._send_gas_msg(g)))
self.safety.set_long_controls_allowed(True)
def test_steer_safety_check(self):
@@ -185,9 +192,9 @@ class TestGmSafety(unittest.TestCase):
self.safety.set_controls_allowed(enabled)
self._set_prev_torque(t)
if abs(t) > MAX_STEER or (not enabled and abs(t) > 0):
- self.assertFalse(self.safety.gm_tx_hook(self._torque_msg(t)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(t)))
else:
- self.assertTrue(self.safety.gm_tx_hook(self._torque_msg(t)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(t)))
def test_manually_enable_controls_allowed(self):
self.safety.set_controls_allowed(1)
@@ -200,15 +207,15 @@ class TestGmSafety(unittest.TestCase):
self.safety.set_controls_allowed(True)
self._set_prev_torque(0)
- self.assertTrue(self.safety.gm_tx_hook(self._torque_msg(MAX_RATE_UP)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(MAX_RATE_UP)))
self._set_prev_torque(0)
- self.assertTrue(self.safety.gm_tx_hook(self._torque_msg(-MAX_RATE_UP)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(-MAX_RATE_UP)))
self._set_prev_torque(0)
- self.assertFalse(self.safety.gm_tx_hook(self._torque_msg(MAX_RATE_UP + 1)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(MAX_RATE_UP + 1)))
self.safety.set_controls_allowed(True)
self._set_prev_torque(0)
- self.assertFalse(self.safety.gm_tx_hook(self._torque_msg(-MAX_RATE_UP - 1)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(-MAX_RATE_UP - 1)))
def test_non_realtime_limit_down(self):
self.safety.set_gm_torque_driver(0, 0)
@@ -222,10 +229,10 @@ class TestGmSafety(unittest.TestCase):
t *= -sign
self.safety.set_gm_torque_driver(t, t)
self._set_prev_torque(MAX_STEER * sign)
- self.assertTrue(self.safety.gm_tx_hook(self._torque_msg(MAX_STEER * sign)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(MAX_STEER * sign)))
self.safety.set_gm_torque_driver(DRIVER_TORQUE_ALLOWANCE + 1, DRIVER_TORQUE_ALLOWANCE + 1)
- self.assertFalse(self.safety.gm_tx_hook(self._torque_msg(-MAX_STEER)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(-MAX_STEER)))
# spot check some individual cases
for sign in [-1, 1]:
@@ -234,20 +241,20 @@ class TestGmSafety(unittest.TestCase):
delta = 1 * sign
self._set_prev_torque(torque_desired)
self.safety.set_gm_torque_driver(-driver_torque, -driver_torque)
- self.assertTrue(self.safety.gm_tx_hook(self._torque_msg(torque_desired)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(torque_desired)))
self._set_prev_torque(torque_desired + delta)
self.safety.set_gm_torque_driver(-driver_torque, -driver_torque)
- self.assertFalse(self.safety.gm_tx_hook(self._torque_msg(torque_desired + delta)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(torque_desired + delta)))
self._set_prev_torque(MAX_STEER * sign)
self.safety.set_gm_torque_driver(-MAX_STEER * sign, -MAX_STEER * sign)
- self.assertTrue(self.safety.gm_tx_hook(self._torque_msg((MAX_STEER - MAX_RATE_DOWN) * sign)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg((MAX_STEER - MAX_RATE_DOWN) * sign)))
self._set_prev_torque(MAX_STEER * sign)
self.safety.set_gm_torque_driver(-MAX_STEER * sign, -MAX_STEER * sign)
- self.assertTrue(self.safety.gm_tx_hook(self._torque_msg(0)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(0)))
self._set_prev_torque(MAX_STEER * sign)
self.safety.set_gm_torque_driver(-MAX_STEER * sign, -MAX_STEER * sign)
- self.assertFalse(self.safety.gm_tx_hook(self._torque_msg((MAX_STEER - MAX_RATE_DOWN + 1) * sign)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg((MAX_STEER - MAX_RATE_DOWN + 1) * sign)))
def test_realtime_limits(self):
@@ -259,18 +266,29 @@ class TestGmSafety(unittest.TestCase):
self.safety.set_gm_torque_driver(0, 0)
for t in np.arange(0, MAX_RT_DELTA, 1):
t *= sign
- self.assertTrue(self.safety.gm_tx_hook(self._torque_msg(t)))
- self.assertFalse(self.safety.gm_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA + 1))))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(t)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA + 1))))
self._set_prev_torque(0)
for t in np.arange(0, MAX_RT_DELTA, 1):
t *= sign
- self.assertTrue(self.safety.gm_tx_hook(self._torque_msg(t)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(t)))
# Increase timer to update rt_torque_last
self.safety.set_timer(RT_INTERVAL + 1)
- self.assertTrue(self.safety.gm_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA - 1))))
- self.assertTrue(self.safety.gm_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA + 1))))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA - 1))))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA + 1))))
+
+
+ def test_fwd_hook(self):
+ # nothing allowed
+ buss = range(0x0, 0x3)
+ msgs = range(0x1, 0x800)
+
+ for b in buss:
+ for m in msgs:
+ # assume len 8
+ self.assertEqual(-1, self.safety.safety_fwd_hook(b, self._send_msg(b, m, 8)))
if __name__ == "__main__":
diff --git a/panda/tests/safety/test_honda.py b/panda/tests/safety/test_honda.py
index 4e131f2fc..bc5e8d192 100755
--- a/panda/tests/safety/test_honda.py
+++ b/panda/tests/safety/test_honda.py
@@ -9,9 +9,17 @@ class TestHondaSafety(unittest.TestCase):
@classmethod
def setUp(cls):
cls.safety = libpandasafety_py.libpandasafety
- cls.safety.honda_init(0)
+ cls.safety.safety_set_mode(1, 0)
cls.safety.init_tests_honda()
+ def _send_msg(self, bus, addr, length):
+ to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
+ to_send[0].RIR = addr << 21
+ to_send[0].RDTR = length
+ to_send[0].RDTR = bus << 4
+
+ return to_send
+
def _speed_msg(self, speed):
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
to_send[0].RIR = 0x158 << 21
@@ -75,85 +83,85 @@ class TestHondaSafety(unittest.TestCase):
def test_resume_button(self):
RESUME_BTN = 4
self.safety.set_controls_allowed(0)
- self.safety.honda_rx_hook(self._button_msg(RESUME_BTN, 0x1A6))
+ self.safety.safety_rx_hook(self._button_msg(RESUME_BTN, 0x1A6))
self.assertTrue(self.safety.get_controls_allowed())
def test_set_button(self):
SET_BTN = 3
self.safety.set_controls_allowed(0)
- self.safety.honda_rx_hook(self._button_msg(SET_BTN, 0x1A6))
+ self.safety.safety_rx_hook(self._button_msg(SET_BTN, 0x1A6))
self.assertTrue(self.safety.get_controls_allowed())
def test_cancel_button(self):
CANCEL_BTN = 2
self.safety.set_controls_allowed(1)
- self.safety.honda_rx_hook(self._button_msg(CANCEL_BTN, 0x1A6))
+ self.safety.safety_rx_hook(self._button_msg(CANCEL_BTN, 0x1A6))
self.assertFalse(self.safety.get_controls_allowed())
def test_sample_speed(self):
self.assertEqual(0, self.safety.get_honda_ego_speed())
- self.safety.honda_rx_hook(self._speed_msg(100))
+ self.safety.safety_rx_hook(self._speed_msg(100))
self.assertEqual(100, self.safety.get_honda_ego_speed())
def test_prev_brake(self):
self.assertFalse(self.safety.get_honda_brake_prev())
- self.safety.honda_rx_hook(self._brake_msg(True))
+ self.safety.safety_rx_hook(self._brake_msg(True))
self.assertTrue(self.safety.get_honda_brake_prev())
def test_disengage_on_brake(self):
self.safety.set_controls_allowed(1)
- self.safety.honda_rx_hook(self._brake_msg(1))
+ self.safety.safety_rx_hook(self._brake_msg(1))
self.assertFalse(self.safety.get_controls_allowed())
def test_alt_disengage_on_brake(self):
self.safety.set_honda_alt_brake_msg(1)
self.safety.set_controls_allowed(1)
- self.safety.honda_rx_hook(self._alt_brake_msg(1))
+ self.safety.safety_rx_hook(self._alt_brake_msg(1))
self.assertFalse(self.safety.get_controls_allowed())
self.safety.set_honda_alt_brake_msg(0)
self.safety.set_controls_allowed(1)
- self.safety.honda_rx_hook(self._alt_brake_msg(1))
+ self.safety.safety_rx_hook(self._alt_brake_msg(1))
self.assertTrue(self.safety.get_controls_allowed())
def test_allow_brake_at_zero_speed(self):
# Brake was already pressed
- self.safety.honda_rx_hook(self._brake_msg(True))
+ self.safety.safety_rx_hook(self._brake_msg(True))
self.safety.set_controls_allowed(1)
- self.safety.honda_rx_hook(self._brake_msg(True))
+ self.safety.safety_rx_hook(self._brake_msg(True))
self.assertTrue(self.safety.get_controls_allowed())
- self.safety.honda_rx_hook(self._brake_msg(False)) # reset no brakes
+ self.safety.safety_rx_hook(self._brake_msg(False)) # reset no brakes
def test_not_allow_brake_when_moving(self):
# Brake was already pressed
- self.safety.honda_rx_hook(self._brake_msg(True))
- self.safety.honda_rx_hook(self._speed_msg(100))
+ self.safety.safety_rx_hook(self._brake_msg(True))
+ self.safety.safety_rx_hook(self._speed_msg(100))
self.safety.set_controls_allowed(1)
- self.safety.honda_rx_hook(self._brake_msg(True))
+ self.safety.safety_rx_hook(self._brake_msg(True))
self.assertFalse(self.safety.get_controls_allowed())
def test_prev_gas(self):
- self.safety.honda_rx_hook(self._gas_msg(False))
+ self.safety.safety_rx_hook(self._gas_msg(False))
self.assertFalse(self.safety.get_honda_gas_prev())
- self.safety.honda_rx_hook(self._gas_msg(True))
+ self.safety.safety_rx_hook(self._gas_msg(True))
self.assertTrue(self.safety.get_honda_gas_prev())
def test_prev_gas_interceptor(self):
- self.safety.honda_rx_hook(self._send_interceptor_msg(0x0, 0x201))
+ self.safety.safety_rx_hook(self._send_interceptor_msg(0x0, 0x201))
self.assertFalse(self.safety.get_gas_interceptor_prev())
- self.safety.honda_rx_hook(self._send_interceptor_msg(0x1000, 0x201))
+ self.safety.safety_rx_hook(self._send_interceptor_msg(0x1000, 0x201))
self.assertTrue(self.safety.get_gas_interceptor_prev())
- self.safety.honda_rx_hook(self._send_interceptor_msg(0x0, 0x201))
+ self.safety.safety_rx_hook(self._send_interceptor_msg(0x0, 0x201))
self.safety.set_gas_interceptor_detected(False)
def test_disengage_on_gas(self):
for long_controls_allowed in [0, 1]:
self.safety.set_long_controls_allowed(long_controls_allowed)
- self.safety.honda_rx_hook(self._gas_msg(0))
+ self.safety.safety_rx_hook(self._gas_msg(0))
self.safety.set_controls_allowed(1)
- self.safety.honda_rx_hook(self._gas_msg(1))
+ self.safety.safety_rx_hook(self._gas_msg(1))
if long_controls_allowed:
self.assertFalse(self.safety.get_controls_allowed())
else:
@@ -161,31 +169,31 @@ class TestHondaSafety(unittest.TestCase):
self.safety.set_long_controls_allowed(True)
def test_allow_engage_with_gas_pressed(self):
- self.safety.honda_rx_hook(self._gas_msg(1))
+ self.safety.safety_rx_hook(self._gas_msg(1))
self.safety.set_controls_allowed(1)
- self.safety.honda_rx_hook(self._gas_msg(1))
+ self.safety.safety_rx_hook(self._gas_msg(1))
self.assertTrue(self.safety.get_controls_allowed())
def test_disengage_on_gas_interceptor(self):
for long_controls_allowed in [0, 1]:
self.safety.set_long_controls_allowed(long_controls_allowed)
- self.safety.honda_rx_hook(self._send_interceptor_msg(0, 0x201))
+ self.safety.safety_rx_hook(self._send_interceptor_msg(0, 0x201))
self.safety.set_controls_allowed(1)
- self.safety.honda_rx_hook(self._send_interceptor_msg(0x1000, 0x201))
+ self.safety.safety_rx_hook(self._send_interceptor_msg(0x1000, 0x201))
if long_controls_allowed:
self.assertFalse(self.safety.get_controls_allowed())
else:
self.assertTrue(self.safety.get_controls_allowed())
- self.safety.honda_rx_hook(self._send_interceptor_msg(0, 0x201))
+ self.safety.safety_rx_hook(self._send_interceptor_msg(0, 0x201))
self.safety.set_gas_interceptor_detected(False)
self.safety.set_long_controls_allowed(True)
def test_allow_engage_with_gas_interceptor_pressed(self):
- self.safety.honda_rx_hook(self._send_interceptor_msg(0x1000, 0x201))
+ self.safety.safety_rx_hook(self._send_interceptor_msg(0x1000, 0x201))
self.safety.set_controls_allowed(1)
- self.safety.honda_rx_hook(self._send_interceptor_msg(0x1000, 0x201))
+ self.safety.safety_rx_hook(self._send_interceptor_msg(0x1000, 0x201))
self.assertTrue(self.safety.get_controls_allowed())
- self.safety.honda_rx_hook(self._send_interceptor_msg(0, 0x201))
+ self.safety.safety_rx_hook(self._send_interceptor_msg(0, 0x201))
self.safety.set_gas_interceptor_detected(False)
def test_brake_safety_check(self):
@@ -198,7 +206,7 @@ class TestHondaSafety(unittest.TestCase):
send = MAX_BRAKE >= brake >= 0
else:
send = brake == 0
- self.assertEqual(send, self.safety.honda_tx_hook(self._send_brake_msg(brake)))
+ self.assertEqual(send, self.safety.safety_tx_hook(self._send_brake_msg(brake)))
self.safety.set_long_controls_allowed(True)
def test_gas_interceptor_safety_check(self):
@@ -211,13 +219,13 @@ class TestHondaSafety(unittest.TestCase):
send = True
else:
send = gas == 0
- self.assertEqual(send, self.safety.honda_tx_hook(self._send_interceptor_msg(gas, 0x200)))
+ self.assertEqual(send, self.safety.safety_tx_hook(self._send_interceptor_msg(gas, 0x200)))
self.safety.set_long_controls_allowed(True)
def test_steer_safety_check(self):
self.safety.set_controls_allowed(0)
- self.assertTrue(self.safety.honda_tx_hook(self._send_steer_msg(0x0000)))
- self.assertFalse(self.safety.honda_tx_hook(self._send_steer_msg(0x1000)))
+ self.assertTrue(self.safety.safety_tx_hook(self._send_steer_msg(0x0000)))
+ self.assertFalse(self.safety.safety_tx_hook(self._send_steer_msg(0x1000)))
def test_spam_cancel_safety_check(self):
RESUME_BTN = 4
@@ -226,12 +234,39 @@ class TestHondaSafety(unittest.TestCase):
BUTTON_MSG = 0x296
self.safety.set_honda_bosch_hardware(1)
self.safety.set_controls_allowed(0)
- self.assertTrue(self.safety.honda_tx_hook(self._button_msg(CANCEL_BTN, BUTTON_MSG)))
- self.assertFalse(self.safety.honda_tx_hook(self._button_msg(RESUME_BTN, BUTTON_MSG)))
- self.assertFalse(self.safety.honda_tx_hook(self._button_msg(SET_BTN, BUTTON_MSG)))
+ self.assertTrue(self.safety.safety_tx_hook(self._button_msg(CANCEL_BTN, BUTTON_MSG)))
+ self.assertFalse(self.safety.safety_tx_hook(self._button_msg(RESUME_BTN, BUTTON_MSG)))
+ self.assertFalse(self.safety.safety_tx_hook(self._button_msg(SET_BTN, BUTTON_MSG)))
# do not block resume if we are engaged already
self.safety.set_controls_allowed(1)
- self.assertTrue(self.safety.honda_tx_hook(self._button_msg(RESUME_BTN, BUTTON_MSG)))
+ self.assertTrue(self.safety.safety_tx_hook(self._button_msg(RESUME_BTN, BUTTON_MSG)))
+
+ def test_fwd_hook(self):
+ buss = range(0x0, 0x3)
+ msgs = range(0x1, 0x800)
+ long_controls_allowed = [0, 1]
+
+ self.safety.set_honda_bosch_hardware(0)
+
+ for l in long_controls_allowed:
+ self.safety.set_long_controls_allowed(l)
+ blocked_msgs = [0xE4, 0x194, 0x33D]
+ if l:
+ blocked_msgs += [0x1FA ,0x30C, 0x39F]
+ for b in buss:
+ for m in msgs:
+ if b == 0:
+ fwd_bus = 2
+ elif b == 1:
+ fwd_bus = -1
+ elif b == 2:
+ fwd_bus = -1 if m in blocked_msgs else 0
+
+ # assume len 8
+ self.assertEqual(fwd_bus, self.safety.safety_fwd_hook(b, self._send_msg(b, m, 8)))
+
+ self.safety.set_long_controls_allowed(True)
+
if __name__ == "__main__":
diff --git a/panda/tests/safety/test_honda_bosch.py b/panda/tests/safety/test_honda_bosch.py
new file mode 100755
index 000000000..11c939140
--- /dev/null
+++ b/panda/tests/safety/test_honda_bosch.py
@@ -0,0 +1,42 @@
+#!/usr/bin/env python2
+import unittest
+import numpy as np
+import libpandasafety_py
+
+MAX_BRAKE = 255
+
+class TestHondaSafety(unittest.TestCase):
+ @classmethod
+ def setUp(cls):
+ cls.safety = libpandasafety_py.libpandasafety
+ cls.safety.safety_set_mode(4, 0)
+ cls.safety.init_tests_honda()
+
+ def _send_msg(self, bus, addr, length):
+ to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
+ to_send[0].RIR = addr << 21
+ to_send[0].RDTR = length
+ to_send[0].RDTR = bus << 4
+
+ return to_send
+
+ def test_fwd_hook(self):
+ buss = range(0x0, 0x3)
+ msgs = range(0x1, 0x800)
+
+ blocked_msgs = [0xE4, 0x33D]
+ for b in buss:
+ for m in msgs:
+ if b == 0:
+ fwd_bus = -1
+ elif b == 1:
+ fwd_bus = -1 if m in blocked_msgs else 2
+ elif b == 2:
+ fwd_bus = 1
+
+ # assume len 8
+ self.assertEqual(fwd_bus, self.safety.safety_fwd_hook(b, self._send_msg(b, m, 8)))
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/panda/tests/safety/test_hyundai.py b/panda/tests/safety/test_hyundai.py
index bcf9b7611..539982fab 100644
--- a/panda/tests/safety/test_hyundai.py
+++ b/panda/tests/safety/test_hyundai.py
@@ -29,9 +29,16 @@ class TestHyundaiSafety(unittest.TestCase):
@classmethod
def setUp(cls):
cls.safety = libpandasafety_py.libpandasafety
- cls.safety.nooutput_init(0)
+ cls.safety.safety_set_mode(7, 0)
cls.safety.init_tests_hyundai()
+ def _send_msg(self, bus, addr, length):
+ to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
+ to_send[0].RIR = addr << 21
+ to_send[0].RDTR = length
+ to_send[0].RDTR = bus << 4
+ return to_send
+
def _button_msg(self, buttons):
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
to_send[0].RIR = 1265 << 21
@@ -63,9 +70,9 @@ class TestHyundaiSafety(unittest.TestCase):
self.safety.set_controls_allowed(enabled)
self._set_prev_torque(t)
if abs(t) > MAX_STEER or (not enabled and abs(t) > 0):
- self.assertFalse(self.safety.hyundai_tx_hook(self._torque_msg(t)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(t)))
else:
- self.assertTrue(self.safety.hyundai_tx_hook(self._torque_msg(t)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(t)))
def test_manually_enable_controls_allowed(self):
self.safety.set_controls_allowed(1)
@@ -78,7 +85,7 @@ class TestHyundaiSafety(unittest.TestCase):
to_push[0].RIR = 1057 << 21
to_push[0].RDLR = 1 << 13
- self.safety.hyundai_rx_hook(to_push)
+ self.safety.safety_rx_hook(to_push)
self.assertTrue(self.safety.get_controls_allowed())
def test_disable_control_allowed_from_cruise(self):
@@ -87,7 +94,7 @@ class TestHyundaiSafety(unittest.TestCase):
to_push[0].RDLR = 0
self.safety.set_controls_allowed(1)
- self.safety.hyundai_rx_hook(to_push)
+ self.safety.safety_rx_hook(to_push)
self.assertFalse(self.safety.get_controls_allowed())
def test_non_realtime_limit_up(self):
@@ -95,15 +102,15 @@ class TestHyundaiSafety(unittest.TestCase):
self.safety.set_controls_allowed(True)
self._set_prev_torque(0)
- self.assertTrue(self.safety.hyundai_tx_hook(self._torque_msg(MAX_RATE_UP)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(MAX_RATE_UP)))
self._set_prev_torque(0)
- self.assertTrue(self.safety.hyundai_tx_hook(self._torque_msg(-MAX_RATE_UP)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(-MAX_RATE_UP)))
self._set_prev_torque(0)
- self.assertFalse(self.safety.hyundai_tx_hook(self._torque_msg(MAX_RATE_UP + 1)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(MAX_RATE_UP + 1)))
self.safety.set_controls_allowed(True)
self._set_prev_torque(0)
- self.assertFalse(self.safety.hyundai_tx_hook(self._torque_msg(-MAX_RATE_UP - 1)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(-MAX_RATE_UP - 1)))
def test_non_realtime_limit_down(self):
self.safety.set_hyundai_torque_driver(0, 0)
@@ -117,10 +124,10 @@ class TestHyundaiSafety(unittest.TestCase):
t *= -sign
self.safety.set_hyundai_torque_driver(t, t)
self._set_prev_torque(MAX_STEER * sign)
- self.assertTrue(self.safety.hyundai_tx_hook(self._torque_msg(MAX_STEER * sign)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(MAX_STEER * sign)))
self.safety.set_hyundai_torque_driver(DRIVER_TORQUE_ALLOWANCE + 1, DRIVER_TORQUE_ALLOWANCE + 1)
- self.assertFalse(self.safety.hyundai_tx_hook(self._torque_msg(-MAX_STEER)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(-MAX_STEER)))
# spot check some individual cases
for sign in [-1, 1]:
@@ -129,20 +136,20 @@ class TestHyundaiSafety(unittest.TestCase):
delta = 1 * sign
self._set_prev_torque(torque_desired)
self.safety.set_hyundai_torque_driver(-driver_torque, -driver_torque)
- self.assertTrue(self.safety.hyundai_tx_hook(self._torque_msg(torque_desired)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(torque_desired)))
self._set_prev_torque(torque_desired + delta)
self.safety.set_hyundai_torque_driver(-driver_torque, -driver_torque)
- self.assertFalse(self.safety.hyundai_tx_hook(self._torque_msg(torque_desired + delta)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(torque_desired + delta)))
self._set_prev_torque(MAX_STEER * sign)
self.safety.set_hyundai_torque_driver(-MAX_STEER * sign, -MAX_STEER * sign)
- self.assertTrue(self.safety.hyundai_tx_hook(self._torque_msg((MAX_STEER - MAX_RATE_DOWN) * sign)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg((MAX_STEER - MAX_RATE_DOWN) * sign)))
self._set_prev_torque(MAX_STEER * sign)
self.safety.set_hyundai_torque_driver(-MAX_STEER * sign, -MAX_STEER * sign)
- self.assertTrue(self.safety.hyundai_tx_hook(self._torque_msg(0)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(0)))
self._set_prev_torque(MAX_STEER * sign)
self.safety.set_hyundai_torque_driver(-MAX_STEER * sign, -MAX_STEER * sign)
- self.assertFalse(self.safety.hyundai_tx_hook(self._torque_msg((MAX_STEER - MAX_RATE_DOWN + 1) * sign)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg((MAX_STEER - MAX_RATE_DOWN + 1) * sign)))
def test_realtime_limits(self):
@@ -154,18 +161,18 @@ class TestHyundaiSafety(unittest.TestCase):
self.safety.set_hyundai_torque_driver(0, 0)
for t in np.arange(0, MAX_RT_DELTA, 1):
t *= sign
- self.assertTrue(self.safety.hyundai_tx_hook(self._torque_msg(t)))
- self.assertFalse(self.safety.hyundai_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA + 1))))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(t)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA + 1))))
self._set_prev_torque(0)
for t in np.arange(0, MAX_RT_DELTA, 1):
t *= sign
- self.assertTrue(self.safety.hyundai_tx_hook(self._torque_msg(t)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(t)))
# Increase timer to update rt_torque_last
self.safety.set_timer(RT_INTERVAL + 1)
- self.assertTrue(self.safety.hyundai_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA - 1))))
- self.assertTrue(self.safety.hyundai_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA + 1))))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA - 1))))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA + 1))))
#def test_spam_cancel_safety_check(self):
@@ -174,12 +181,37 @@ class TestHyundaiSafety(unittest.TestCase):
# CANCEL_BTN = 4
# BUTTON_MSG = 1265
# self.safety.set_controls_allowed(0)
- # self.assertTrue(self.safety.hyundai_tx_hook(self._button_msg(CANCEL_BTN)))
- # self.assertFalse(self.safety.hyundai_tx_hook(self._button_msg(RESUME_BTN)))
- # self.assertFalse(self.safety.hyundai_tx_hook(self._button_msg(SET_BTN)))
+ # self.assertTrue(self.safety.safety_tx_hook(self._button_msg(CANCEL_BTN)))
+ # self.assertFalse(self.safety.safety_tx_hook(self._button_msg(RESUME_BTN)))
+ # self.assertFalse(self.safety.safety_tx_hook(self._button_msg(SET_BTN)))
# # do not block resume if we are engaged already
# self.safety.set_controls_allowed(1)
- # self.assertTrue(self.safety.hyundai_tx_hook(self._button_msg(RESUME_BTN)))
+ # self.assertTrue(self.safety.safety_tx_hook(self._button_msg(RESUME_BTN)))
+
+ def test_fwd_hook(self):
+
+ buss = range(0x0, 0x3)
+ msgs = range(0x1, 0x800)
+ hyundai_giraffe_switch_2 = [0, 1]
+
+ self.safety.set_hyundai_camera_bus(2)
+ for hgs in hyundai_giraffe_switch_2:
+ self.safety.set_hyundai_giraffe_switch_2(hgs)
+ blocked_msgs = [832]
+ for b in buss:
+ for m in msgs:
+ if hgs:
+ if b == 0:
+ fwd_bus = 2
+ elif b == 1:
+ fwd_bus = -1
+ elif b == 2:
+ fwd_bus = -1 if m in blocked_msgs else 0
+ else:
+ fwd_bus = -1
+
+ # assume len 8
+ self.assertEqual(fwd_bus, self.safety.safety_fwd_hook(b, self._send_msg(b, m, 8)))
if __name__ == "__main__":
diff --git a/panda/tests/safety/test_subaru.py b/panda/tests/safety/test_subaru.py
index a1e03fea1..13fe1fb14 100644
--- a/panda/tests/safety/test_subaru.py
+++ b/panda/tests/safety/test_subaru.py
@@ -29,9 +29,16 @@ class TestSubaruSafety(unittest.TestCase):
@classmethod
def setUp(cls):
cls.safety = libpandasafety_py.libpandasafety
- cls.safety.nooutput_init(0)
+ cls.safety.safety_set_mode(10, 0)
cls.safety.init_tests_subaru()
+ def _send_msg(self, bus, addr, length):
+ to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
+ to_send[0].RIR = addr << 21
+ to_send[0].RDTR = length
+ to_send[0].RDTR = bus << 4
+ return to_send
+
def _set_prev_torque(self, t):
self.safety.set_subaru_desired_torque_last(t)
self.safety.set_subaru_rt_torque_last(t)
@@ -60,7 +67,7 @@ class TestSubaruSafety(unittest.TestCase):
to_push[0].RIR = 0x240 << 21
to_push[0].RDHR = 1 << 9
- self.safety.subaru_rx_hook(to_push)
+ self.safety.safety_rx_hook(to_push)
self.assertTrue(self.safety.get_controls_allowed())
def test_disable_control_allowed_from_cruise(self):
@@ -69,7 +76,7 @@ class TestSubaruSafety(unittest.TestCase):
to_push[0].RDHR = 0
self.safety.set_controls_allowed(1)
- self.safety.subaru_rx_hook(to_push)
+ self.safety.safety_rx_hook(to_push)
self.assertFalse(self.safety.get_controls_allowed())
def test_steer_safety_check(self):
@@ -78,9 +85,9 @@ class TestSubaruSafety(unittest.TestCase):
self.safety.set_controls_allowed(enabled)
self._set_prev_torque(t)
if abs(t) > MAX_STEER or (not enabled and abs(t) > 0):
- self.assertFalse(self.safety.subaru_tx_hook(self._torque_msg(t)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(t)))
else:
- self.assertTrue(self.safety.subaru_tx_hook(self._torque_msg(t)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(t)))
def test_manually_enable_controls_allowed(self):
self.safety.set_controls_allowed(1)
@@ -93,15 +100,15 @@ class TestSubaruSafety(unittest.TestCase):
self.safety.set_controls_allowed(True)
self._set_prev_torque(0)
- self.assertTrue(self.safety.subaru_tx_hook(self._torque_msg(MAX_RATE_UP)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(MAX_RATE_UP)))
self._set_prev_torque(0)
- self.assertTrue(self.safety.subaru_tx_hook(self._torque_msg(-MAX_RATE_UP)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(-MAX_RATE_UP)))
self._set_prev_torque(0)
- self.assertFalse(self.safety.subaru_tx_hook(self._torque_msg(MAX_RATE_UP + 1)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(MAX_RATE_UP + 1)))
self.safety.set_controls_allowed(True)
self._set_prev_torque(0)
- self.assertFalse(self.safety.subaru_tx_hook(self._torque_msg(-MAX_RATE_UP - 1)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(-MAX_RATE_UP - 1)))
def test_non_realtime_limit_down(self):
self.safety.set_subaru_torque_driver(0, 0)
@@ -115,10 +122,10 @@ class TestSubaruSafety(unittest.TestCase):
t *= -sign
self.safety.set_subaru_torque_driver(t, t)
self._set_prev_torque(MAX_STEER * sign)
- self.assertTrue(self.safety.subaru_tx_hook(self._torque_msg(MAX_STEER * sign)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(MAX_STEER * sign)))
self.safety.set_subaru_torque_driver(DRIVER_TORQUE_ALLOWANCE + 1, DRIVER_TORQUE_ALLOWANCE + 1)
- self.assertFalse(self.safety.subaru_tx_hook(self._torque_msg(-MAX_STEER)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(-MAX_STEER)))
# spot check some individual cases
for sign in [-1, 1]:
@@ -127,20 +134,20 @@ class TestSubaruSafety(unittest.TestCase):
delta = 1 * sign
self._set_prev_torque(torque_desired)
self.safety.set_subaru_torque_driver(-driver_torque, -driver_torque)
- self.assertTrue(self.safety.subaru_tx_hook(self._torque_msg(torque_desired)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(torque_desired)))
self._set_prev_torque(torque_desired + delta)
self.safety.set_subaru_torque_driver(-driver_torque, -driver_torque)
- self.assertFalse(self.safety.subaru_tx_hook(self._torque_msg(torque_desired + delta)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(torque_desired + delta)))
self._set_prev_torque(MAX_STEER * sign)
self.safety.set_subaru_torque_driver(-MAX_STEER * sign, -MAX_STEER * sign)
- self.assertTrue(self.safety.subaru_tx_hook(self._torque_msg((MAX_STEER - MAX_RATE_DOWN) * sign)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg((MAX_STEER - MAX_RATE_DOWN) * sign)))
self._set_prev_torque(MAX_STEER * sign)
self.safety.set_subaru_torque_driver(-MAX_STEER * sign, -MAX_STEER * sign)
- self.assertTrue(self.safety.subaru_tx_hook(self._torque_msg(0)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(0)))
self._set_prev_torque(MAX_STEER * sign)
self.safety.set_subaru_torque_driver(-MAX_STEER * sign, -MAX_STEER * sign)
- self.assertFalse(self.safety.subaru_tx_hook(self._torque_msg((MAX_STEER - MAX_RATE_DOWN + 1) * sign)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg((MAX_STEER - MAX_RATE_DOWN + 1) * sign)))
def test_realtime_limits(self):
@@ -152,18 +159,35 @@ class TestSubaruSafety(unittest.TestCase):
self.safety.set_subaru_torque_driver(0, 0)
for t in np.arange(0, MAX_RT_DELTA, 1):
t *= sign
- self.assertTrue(self.safety.subaru_tx_hook(self._torque_msg(t)))
- self.assertFalse(self.safety.subaru_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA + 1))))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(t)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA + 1))))
self._set_prev_torque(0)
for t in np.arange(0, MAX_RT_DELTA, 1):
t *= sign
- self.assertTrue(self.safety.subaru_tx_hook(self._torque_msg(t)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(t)))
# Increase timer to update rt_torque_last
self.safety.set_timer(RT_INTERVAL + 1)
- self.assertTrue(self.safety.subaru_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA - 1))))
- self.assertTrue(self.safety.subaru_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA + 1))))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA - 1))))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA + 1))))
+
+
+ def test_fwd_hook(self):
+ buss = range(0x0, 0x3)
+ msgs = range(0x1, 0x800)
+ blocked_msgs = [290, 356, 545, 802]
+ for b in buss:
+ for m in msgs:
+ if b == 0:
+ fwd_bus = 2
+ elif b == 1:
+ fwd_bus = -1
+ elif b == 2:
+ fwd_bus = -1 if m in blocked_msgs else 0
+
+ # assume len 8
+ self.assertEqual(fwd_bus, self.safety.safety_fwd_hook(b, self._send_msg(b, m, 8)))
if __name__ == "__main__":
diff --git a/panda/tests/safety/test_toyota.py b/panda/tests/safety/test_toyota.py
index 9badaec0f..7dd1601d7 100644
--- a/panda/tests/safety/test_toyota.py
+++ b/panda/tests/safety/test_toyota.py
@@ -15,12 +15,6 @@ RT_INTERVAL = 250000
MAX_TORQUE_ERROR = 350
-IPAS_OVERRIDE_THRESHOLD = 200
-
-ANGLE_DELTA_BP = [0., 5., 15.]
-ANGLE_DELTA_V = [5., .8, .15] # windup limit
-ANGLE_DELTA_VU = [5., 3.5, 0.4] # unwind limit
-
def twos_comp(val, bits):
if val >= 0:
return val
@@ -37,9 +31,16 @@ class TestToyotaSafety(unittest.TestCase):
@classmethod
def setUp(cls):
cls.safety = libpandasafety_py.libpandasafety
- cls.safety.toyota_init(100)
+ cls.safety.safety_set_mode(2, 100)
cls.safety.init_tests_toyota()
+ def _send_msg(self, bus, addr, length):
+ to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
+ to_send[0].RIR = addr << 21
+ to_send[0].RDTR = length
+ to_send[0].RDTR = bus << 4
+ return to_send
+
def _set_prev_torque(self, t):
self.safety.set_toyota_desired_torque_last(t)
self.safety.set_toyota_rt_torque_last(t)
@@ -53,30 +54,6 @@ class TestToyotaSafety(unittest.TestCase):
to_send[0].RDHR = t | ((t & 0xFF) << 16)
return to_send
- def _torque_driver_msg(self, torque):
- to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
- to_send[0].RIR = 0x260 << 21
-
- t = twos_comp(torque, 16)
- to_send[0].RDLR = t | ((t & 0xFF) << 16)
- return to_send
-
- def _torque_driver_msg_array(self, torque):
- for i in range(6):
- self.safety.toyota_ipas_rx_hook(self._torque_driver_msg(torque))
-
- def _angle_meas_msg(self, angle):
- to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
- to_send[0].RIR = 0x25 << 21
-
- t = twos_comp(angle, 12)
- to_send[0].RDLR = ((t & 0xF00) >> 8) | ((t & 0xFF) << 8)
- return to_send
-
- def _angle_meas_msg_array(self, angle):
- for i in range(6):
- self.safety.toyota_ipas_rx_hook(self._angle_meas_msg(angle))
-
def _torque_msg(self, torque):
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
to_send[0].RIR = 0x2E4 << 21
@@ -85,32 +62,6 @@ class TestToyotaSafety(unittest.TestCase):
to_send[0].RDLR = t | ((t & 0xFF) << 16)
return to_send
- def _ipas_state_msg(self, state):
- to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
- to_send[0].RIR = 0x262 << 21
-
- to_send[0].RDLR = state & 0xF
- return to_send
-
- def _ipas_control_msg(self, angle, state):
- # note: we command 2/3 of the angle due to CAN conversion
- to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
- to_send[0].RIR = 0x266 << 21
-
- t = twos_comp(angle, 12)
- to_send[0].RDLR = ((t & 0xF00) >> 8) | ((t & 0xFF) << 8)
- to_send[0].RDLR |= ((state & 0xf) << 4)
-
- return to_send
-
- def _speed_msg(self, speed):
- to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
- to_send[0].RIR = 0xb4 << 21
- speed = int(speed * 100 * 3.6)
-
- to_send[0].RDHR = ((speed & 0xFF) << 16) | (speed & 0xFF00)
- return to_send
-
def _accel_msg(self, accel):
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
to_send[0].RIR = 0x343 << 21
@@ -121,8 +72,8 @@ class TestToyotaSafety(unittest.TestCase):
def _send_gas_msg(self, gas):
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
- to_send[0].RIR = 0x200 << 21
- to_send[0].RDLR = gas
+ to_send[0].RIR = 0x2C1 << 21
+ to_send[0].RDHR = (gas & 0xFF) << 16
return to_send
@@ -134,10 +85,10 @@ class TestToyotaSafety(unittest.TestCase):
return to_send
- def _pcm_cruise_msg(self, cruise_on, gas_pressed):
+ def _pcm_cruise_msg(self, cruise_on):
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
to_send[0].RIR = 0x1D2 << 21
- to_send[0].RDLR = (cruise_on << 5) | ((not gas_pressed) << 4 )
+ to_send[0].RDLR = cruise_on << 5
return to_send
@@ -149,37 +100,35 @@ class TestToyotaSafety(unittest.TestCase):
self.assertTrue(self.safety.get_controls_allowed())
def test_enable_control_allowed_from_cruise(self):
- self.safety.toyota_rx_hook(self._pcm_cruise_msg(False, False))
+ self.safety.safety_rx_hook(self._pcm_cruise_msg(False))
self.assertFalse(self.safety.get_controls_allowed())
- self.safety.toyota_rx_hook(self._pcm_cruise_msg(True, False))
+ self.safety.safety_rx_hook(self._pcm_cruise_msg(True))
self.assertTrue(self.safety.get_controls_allowed())
def test_disable_control_allowed_from_cruise(self):
self.safety.set_controls_allowed(1)
- self.safety.toyota_rx_hook(self._pcm_cruise_msg(False, False))
+ self.safety.safety_rx_hook(self._pcm_cruise_msg(False))
self.assertFalse(self.safety.get_controls_allowed())
def test_prev_gas(self):
- self.safety.toyota_rx_hook(self._pcm_cruise_msg(False, False))
- self.assertFalse(self.safety.get_toyota_gas_prev())
- self.safety.toyota_rx_hook(self._pcm_cruise_msg(False, True))
- self.assertTrue(self.safety.get_toyota_gas_prev())
+ for g in range(0, 256):
+ self.safety.safety_rx_hook(self._send_gas_msg(g))
+ self.assertEqual(g, self.safety.get_toyota_gas_prev())
def test_prev_gas_interceptor(self):
- self.safety.toyota_rx_hook(self._send_interceptor_msg(0x0, 0x201))
+ self.safety.safety_rx_hook(self._send_interceptor_msg(0x0, 0x201))
self.assertFalse(self.safety.get_gas_interceptor_prev())
- self.safety.toyota_rx_hook(self._send_interceptor_msg(0x1000, 0x201))
+ self.safety.safety_rx_hook(self._send_interceptor_msg(0x1000, 0x201))
self.assertTrue(self.safety.get_gas_interceptor_prev())
- self.safety.toyota_rx_hook(self._send_interceptor_msg(0x0, 0x201))
+ self.safety.safety_rx_hook(self._send_interceptor_msg(0x0, 0x201))
self.safety.set_gas_interceptor_detected(False)
def test_disengage_on_gas(self):
for long_controls_allowed in [0, 1]:
self.safety.set_long_controls_allowed(long_controls_allowed)
- self.safety.toyota_rx_hook(self._pcm_cruise_msg(False, False))
- self.safety.toyota_rx_hook(self._pcm_cruise_msg(True, False))
- self.assertTrue(self.safety.get_controls_allowed())
- self.safety.toyota_rx_hook(self._pcm_cruise_msg(True, True))
+ self.safety.safety_rx_hook(self._send_gas_msg(0))
+ self.safety.set_controls_allowed(True)
+ self.safety.safety_rx_hook(self._send_gas_msg(1))
if long_controls_allowed:
self.assertFalse(self.safety.get_controls_allowed())
else:
@@ -187,32 +136,33 @@ class TestToyotaSafety(unittest.TestCase):
self.safety.set_long_controls_allowed(True)
def test_allow_engage_with_gas_pressed(self):
- self.safety.toyota_rx_hook(self._pcm_cruise_msg(False, True))
- self.safety.toyota_rx_hook(self._pcm_cruise_msg(True, True))
+ self.safety.safety_rx_hook(self._send_gas_msg(1))
+ self.safety.set_controls_allowed(True)
+ self.safety.safety_rx_hook(self._send_gas_msg(1))
self.assertTrue(self.safety.get_controls_allowed())
- self.safety.toyota_rx_hook(self._pcm_cruise_msg(True, True))
+ self.safety.safety_rx_hook(self._send_gas_msg(1))
self.assertTrue(self.safety.get_controls_allowed())
def test_disengage_on_gas_interceptor(self):
for long_controls_allowed in [0, 1]:
self.safety.set_long_controls_allowed(long_controls_allowed)
- self.safety.toyota_rx_hook(self._send_interceptor_msg(0, 0x201))
- self.safety.set_controls_allowed(1)
- self.safety.toyota_rx_hook(self._send_interceptor_msg(0x1000, 0x201))
+ self.safety.safety_rx_hook(self._send_interceptor_msg(0, 0x201))
+ self.safety.set_controls_allowed(True)
+ self.safety.safety_rx_hook(self._send_interceptor_msg(0x1000, 0x201))
if long_controls_allowed:
self.assertFalse(self.safety.get_controls_allowed())
else:
self.assertTrue(self.safety.get_controls_allowed())
- self.safety.toyota_rx_hook(self._send_interceptor_msg(0, 0x201))
+ self.safety.safety_rx_hook(self._send_interceptor_msg(0, 0x201))
self.safety.set_gas_interceptor_detected(False)
self.safety.set_long_controls_allowed(True)
def test_allow_engage_with_gas_interceptor_pressed(self):
- self.safety.toyota_rx_hook(self._send_interceptor_msg(0x1000, 0x201))
+ self.safety.safety_rx_hook(self._send_interceptor_msg(0x1000, 0x201))
self.safety.set_controls_allowed(1)
- self.safety.toyota_rx_hook(self._send_interceptor_msg(0x1000, 0x201))
+ self.safety.safety_rx_hook(self._send_interceptor_msg(0x1000, 0x201))
self.assertTrue(self.safety.get_controls_allowed())
- self.safety.toyota_rx_hook(self._send_interceptor_msg(0, 0x201))
+ self.safety.safety_rx_hook(self._send_interceptor_msg(0, 0x201))
self.safety.set_gas_interceptor_detected(False)
def test_accel_actuation_limits(self):
@@ -225,7 +175,7 @@ class TestToyotaSafety(unittest.TestCase):
send = MIN_ACCEL <= accel <= MAX_ACCEL
else:
send = accel == 0
- self.assertEqual(send, self.safety.toyota_tx_hook(self._accel_msg(accel)))
+ self.assertEqual(send, self.safety.safety_tx_hook(self._accel_msg(accel)))
self.safety.set_long_controls_allowed(True)
def test_torque_absolute_limits(self):
@@ -241,16 +191,16 @@ class TestToyotaSafety(unittest.TestCase):
else:
send = torque == 0
- self.assertEqual(send, self.safety.toyota_tx_hook(self._torque_msg(torque)))
+ self.assertEqual(send, self.safety.safety_tx_hook(self._torque_msg(torque)))
def test_non_realtime_limit_up(self):
self.safety.set_controls_allowed(True)
self._set_prev_torque(0)
- self.assertTrue(self.safety.toyota_tx_hook(self._torque_msg(MAX_RATE_UP)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(MAX_RATE_UP)))
self._set_prev_torque(0)
- self.assertFalse(self.safety.toyota_tx_hook(self._torque_msg(MAX_RATE_UP + 1)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(MAX_RATE_UP + 1)))
def test_non_realtime_limit_down(self):
self.safety.set_controls_allowed(True)
@@ -258,12 +208,12 @@ class TestToyotaSafety(unittest.TestCase):
self.safety.set_toyota_rt_torque_last(1000)
self.safety.set_toyota_torque_meas(500, 500)
self.safety.set_toyota_desired_torque_last(1000)
- self.assertTrue(self.safety.toyota_tx_hook(self._torque_msg(1000 - MAX_RATE_DOWN)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(1000 - MAX_RATE_DOWN)))
self.safety.set_toyota_rt_torque_last(1000)
self.safety.set_toyota_torque_meas(500, 500)
self.safety.set_toyota_desired_torque_last(1000)
- self.assertFalse(self.safety.toyota_tx_hook(self._torque_msg(1000 - MAX_RATE_DOWN + 1)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(1000 - MAX_RATE_DOWN + 1)))
def test_exceed_torque_sensor(self):
self.safety.set_controls_allowed(True)
@@ -272,9 +222,9 @@ class TestToyotaSafety(unittest.TestCase):
self._set_prev_torque(0)
for t in np.arange(0, MAX_TORQUE_ERROR + 10, 10):
t *= sign
- self.assertTrue(self.safety.toyota_tx_hook(self._torque_msg(t)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(t)))
- self.assertFalse(self.safety.toyota_tx_hook(self._torque_msg(sign * (MAX_TORQUE_ERROR + 10))))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(sign * (MAX_TORQUE_ERROR + 10))))
def test_realtime_limit_up(self):
self.safety.set_controls_allowed(True)
@@ -285,211 +235,77 @@ class TestToyotaSafety(unittest.TestCase):
for t in np.arange(0, 380, 10):
t *= sign
self.safety.set_toyota_torque_meas(t, t)
- self.assertTrue(self.safety.toyota_tx_hook(self._torque_msg(t)))
- self.assertFalse(self.safety.toyota_tx_hook(self._torque_msg(sign * 380)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(t)))
+ self.assertFalse(self.safety.safety_tx_hook(self._torque_msg(sign * 380)))
self._set_prev_torque(0)
for t in np.arange(0, 370, 10):
t *= sign
self.safety.set_toyota_torque_meas(t, t)
- self.assertTrue(self.safety.toyota_tx_hook(self._torque_msg(t)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(t)))
# Increase timer to update rt_torque_last
self.safety.set_timer(RT_INTERVAL + 1)
- self.assertTrue(self.safety.toyota_tx_hook(self._torque_msg(sign * 370)))
- self.assertTrue(self.safety.toyota_tx_hook(self._torque_msg(sign * 380)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(sign * 370)))
+ self.assertTrue(self.safety.safety_tx_hook(self._torque_msg(sign * 380)))
def test_torque_measurements(self):
- self.safety.toyota_rx_hook(self._torque_meas_msg(50))
- self.safety.toyota_rx_hook(self._torque_meas_msg(-50))
- self.safety.toyota_rx_hook(self._torque_meas_msg(0))
- self.safety.toyota_rx_hook(self._torque_meas_msg(0))
- self.safety.toyota_rx_hook(self._torque_meas_msg(0))
- self.safety.toyota_rx_hook(self._torque_meas_msg(0))
+ self.safety.safety_rx_hook(self._torque_meas_msg(50))
+ self.safety.safety_rx_hook(self._torque_meas_msg(-50))
+ self.safety.safety_rx_hook(self._torque_meas_msg(0))
+ self.safety.safety_rx_hook(self._torque_meas_msg(0))
+ self.safety.safety_rx_hook(self._torque_meas_msg(0))
+ self.safety.safety_rx_hook(self._torque_meas_msg(0))
self.assertEqual(-51, self.safety.get_toyota_torque_meas_min())
self.assertEqual(51, self.safety.get_toyota_torque_meas_max())
- self.safety.toyota_rx_hook(self._torque_meas_msg(0))
+ self.safety.safety_rx_hook(self._torque_meas_msg(0))
self.assertEqual(1, self.safety.get_toyota_torque_meas_max())
self.assertEqual(-51, self.safety.get_toyota_torque_meas_min())
- self.safety.toyota_rx_hook(self._torque_meas_msg(0))
+ self.safety.safety_rx_hook(self._torque_meas_msg(0))
self.assertEqual(1, self.safety.get_toyota_torque_meas_max())
self.assertEqual(-1, self.safety.get_toyota_torque_meas_min())
- def test_ipas_override(self):
-
- ## angle control is not active
- self.safety.set_controls_allowed(1)
-
- # 3 consecutive msgs where driver exceeds threshold but angle_control isn't active
- self.safety.set_controls_allowed(1)
- self._torque_driver_msg_array(IPAS_OVERRIDE_THRESHOLD + 1)
- self.assertTrue(self.safety.get_controls_allowed())
-
- self._torque_driver_msg_array(-IPAS_OVERRIDE_THRESHOLD - 1)
- self.assertTrue(self.safety.get_controls_allowed())
-
- # ipas state is override
- self.safety.toyota_ipas_rx_hook(self._ipas_state_msg(5))
- self.assertTrue(self.safety.get_controls_allowed())
-
- ## now angle control is active
- self.safety.toyota_ipas_tx_hook(self._ipas_control_msg(0, 0))
- self.safety.toyota_ipas_rx_hook(self._ipas_state_msg(0))
-
- # 3 consecutive msgs where driver does exceed threshold
- self.safety.set_controls_allowed(1)
- self._torque_driver_msg_array(IPAS_OVERRIDE_THRESHOLD + 1)
- self.assertFalse(self.safety.get_controls_allowed())
-
- self.safety.set_controls_allowed(1)
- self._torque_driver_msg_array(-IPAS_OVERRIDE_THRESHOLD - 1)
- self.assertFalse(self.safety.get_controls_allowed())
-
- # ipas state is override and torque isn't overriding any more
- self.safety.set_controls_allowed(1)
- self._torque_driver_msg_array(0)
- self.safety.toyota_ipas_rx_hook(self._ipas_state_msg(5))
- self.assertFalse(self.safety.get_controls_allowed())
-
- # 3 consecutive msgs where driver does not exceed threshold and
- # ipas state is not override
- self.safety.set_controls_allowed(1)
- self.safety.toyota_ipas_rx_hook(self._ipas_state_msg(0))
- self.assertTrue(self.safety.get_controls_allowed())
-
- self._torque_driver_msg_array(IPAS_OVERRIDE_THRESHOLD)
- self.assertTrue(self.safety.get_controls_allowed())
-
- self._torque_driver_msg_array(-IPAS_OVERRIDE_THRESHOLD)
- self.assertTrue(self.safety.get_controls_allowed())
-
- # reset no angle control at the end of the test
- self.safety.reset_angle_control()
-
- def test_angle_cmd_when_disabled(self):
-
- self.safety.set_controls_allowed(0)
-
- # test angle cmd too far from actual
- angle_refs = [-10, 10]
- deltas = range(-2, 3)
- expected_results = [False, True, True, True, False]
-
- for a in angle_refs:
- self._angle_meas_msg_array(a)
- for i, d in enumerate(deltas):
- self.assertEqual(expected_results[i], self.safety.toyota_ipas_tx_hook(self._ipas_control_msg(a + d, 1)))
-
- # test ipas state cmd enabled
- self._angle_meas_msg_array(0)
- self.assertEqual(0, self.safety.toyota_ipas_tx_hook(self._ipas_control_msg(0, 3)))
-
- # reset no angle control at the end of the test
- self.safety.reset_angle_control()
-
- def test_angle_cmd_when_enabled(self):
-
- # ipas angle cmd should pass through when controls are enabled
-
- self.safety.set_controls_allowed(1)
- self._angle_meas_msg_array(0)
- self.safety.toyota_ipas_rx_hook(self._speed_msg(0.1))
-
- self.assertEqual(1, self.safety.toyota_ipas_tx_hook(self._ipas_control_msg(0, 1)))
- self.assertEqual(1, self.safety.toyota_ipas_tx_hook(self._ipas_control_msg(4, 1)))
- self.assertEqual(1, self.safety.toyota_ipas_tx_hook(self._ipas_control_msg(0, 3)))
- self.assertEqual(1, self.safety.toyota_ipas_tx_hook(self._ipas_control_msg(-4, 3)))
- self.assertEqual(1, self.safety.toyota_ipas_tx_hook(self._ipas_control_msg(-8, 3)))
-
- # reset no angle control at the end of the test
- self.safety.reset_angle_control()
-
-
- def test_angle_cmd_rate_when_disabled(self):
-
- # as long as the command is close to the measured, no rate limit is enforced when
- # controls are disabled
- self.safety.set_controls_allowed(0)
- self.safety.toyota_ipas_rx_hook(self._angle_meas_msg(0))
- self.assertEqual(1, self.safety.toyota_ipas_tx_hook(self._ipas_control_msg(0, 1)))
- self.safety.toyota_ipas_rx_hook(self._angle_meas_msg(100))
- self.assertEqual(1, self.safety.toyota_ipas_tx_hook(self._ipas_control_msg(100, 1)))
- self.safety.toyota_ipas_rx_hook(self._angle_meas_msg(-100))
- self.assertEqual(1, self.safety.toyota_ipas_tx_hook(self._ipas_control_msg(-100, 1)))
-
- # reset no angle control at the end of the test
- self.safety.reset_angle_control()
-
- def test_angle_cmd_rate_when_enabled(self):
-
- # when controls are allowed, angle cmd rate limit is enforced
- # test 1: no limitations if we stay within limits
- speeds = [0., 1., 5., 10., 15., 100.]
- angles = [-300, -100, -10, 0, 10, 100, 300]
- for a in angles:
- for s in speeds:
-
- # first test against false positives
- self._angle_meas_msg_array(a)
- self.safety.toyota_ipas_tx_hook(self._ipas_control_msg(a, 1))
- self.safety.set_controls_allowed(1)
- self.safety.toyota_ipas_rx_hook(self._speed_msg(s))
- max_delta_up = int(np.interp(s, ANGLE_DELTA_BP, ANGLE_DELTA_V) * 2 / 3. + 1.)
- max_delta_down = int(np.interp(s, ANGLE_DELTA_BP, ANGLE_DELTA_VU) * 2 / 3. + 1.)
- self.assertEqual(True, self.safety.toyota_ipas_tx_hook(self._ipas_control_msg(a + sign(a) * max_delta_up, 1)))
- self.assertTrue(self.safety.get_controls_allowed())
- self.assertEqual(True, self.safety.toyota_ipas_tx_hook(self._ipas_control_msg(a, 1)))
- self.assertTrue(self.safety.get_controls_allowed())
- self.assertEqual(True, self.safety.toyota_ipas_tx_hook(self._ipas_control_msg(a - sign(a) * max_delta_down, 1)))
- self.assertTrue(self.safety.get_controls_allowed())
-
- # now inject too high rates
- self.assertEqual(False, self.safety.toyota_ipas_tx_hook(self._ipas_control_msg(a + sign(a) *
- (max_delta_up + 1), 1)))
- self.assertFalse(self.safety.get_controls_allowed())
- self.safety.set_controls_allowed(1)
- self.assertEqual(True, self.safety.toyota_ipas_tx_hook(self._ipas_control_msg(a + sign(a) * max_delta_up, 1)))
- self.assertTrue(self.safety.get_controls_allowed())
- self.assertEqual(True, self.safety.toyota_ipas_tx_hook(self._ipas_control_msg(a, 1)))
- self.assertTrue(self.safety.get_controls_allowed())
- self.assertEqual(False, self.safety.toyota_ipas_tx_hook(self._ipas_control_msg(a - sign(a) *
- (max_delta_down + 1), 1)))
- self.assertFalse(self.safety.get_controls_allowed())
-
- # reset no angle control at the end of the test
- self.safety.reset_angle_control()
-
- def test_angle_measured_rate(self):
-
- speeds = [0., 1., 5., 10., 15., 100.]
- angles = [-300, -100, -10, 0, 10, 100, 300]
- angles = [10]
- for a in angles:
- for s in speeds:
- self._angle_meas_msg_array(a)
- self.safety.toyota_ipas_tx_hook(self._ipas_control_msg(a, 1))
- self.safety.set_controls_allowed(1)
- self.safety.toyota_ipas_rx_hook(self._speed_msg(s))
- max_delta_up = int(np.interp(s, ANGLE_DELTA_BP, ANGLE_DELTA_V) * 2 / 3. + 1.)
- max_delta_down = int(np.interp(s, ANGLE_DELTA_BP, ANGLE_DELTA_VU) * 2 / 3. + 1.)
- self.safety.toyota_ipas_rx_hook(self._angle_meas_msg(a))
- self.assertTrue(self.safety.get_controls_allowed())
- self.safety.toyota_ipas_rx_hook(self._angle_meas_msg(a + 150))
- self.assertFalse(self.safety.get_controls_allowed())
-
- # reset no angle control at the end of the test
- self.safety.reset_angle_control()
-
def test_gas_interceptor_safety_check(self):
self.safety.set_controls_allowed(0)
- self.assertTrue(self.safety.toyota_tx_hook(self._send_interceptor_msg(0, 0x200)))
- self.assertFalse(self.safety.toyota_tx_hook(self._send_interceptor_msg(0x1000, 0x200)))
+ self.assertTrue(self.safety.safety_tx_hook(self._send_interceptor_msg(0, 0x200)))
+ self.assertFalse(self.safety.safety_tx_hook(self._send_interceptor_msg(0x1000, 0x200)))
self.safety.set_controls_allowed(1)
- self.assertTrue(self.safety.toyota_tx_hook(self._send_interceptor_msg(0x1000, 0x200)))
+ self.assertTrue(self.safety.safety_tx_hook(self._send_interceptor_msg(0x1000, 0x200)))
+
+ def test_fwd_hook(self):
+
+ buss = range(0x0, 0x3)
+ msgs = range(0x1, 0x800)
+ long_controls_allowed = [0, 1]
+ toyota_camera_forwarded = [0, 1]
+
+ for tcf in toyota_camera_forwarded:
+ self.safety.set_toyota_camera_forwarded(tcf)
+ for lca in long_controls_allowed:
+ self.safety.set_long_controls_allowed(lca)
+ blocked_msgs = [0x2E4, 0x412, 0x191]
+ if lca:
+ blocked_msgs += [0x343]
+ for b in buss:
+ for m in msgs:
+ if tcf:
+ if b == 0:
+ fwd_bus = 2
+ elif b == 1:
+ fwd_bus = -1
+ elif b == 2:
+ fwd_bus = -1 if m in blocked_msgs else 0
+ else:
+ fwd_bus = -1
+
+ # assume len 8
+ self.assertEqual(fwd_bus, self.safety.safety_fwd_hook(b, self._send_msg(b, m, 8)))
+
+ self.safety.set_long_controls_allowed(True)
if __name__ == "__main__":
diff --git a/panda/tests/safety/test_toyota_ipas.py b/panda/tests/safety/test_toyota_ipas.py
new file mode 100644
index 000000000..7a382093e
--- /dev/null
+++ b/panda/tests/safety/test_toyota_ipas.py
@@ -0,0 +1,247 @@
+#!/usr/bin/env python2
+import unittest
+import numpy as np
+import libpandasafety_py
+
+IPAS_OVERRIDE_THRESHOLD = 200
+
+ANGLE_DELTA_BP = [0., 5., 15.]
+ANGLE_DELTA_V = [5., .8, .15] # windup limit
+ANGLE_DELTA_VU = [5., 3.5, 0.4] # unwind limit
+
+def twos_comp(val, bits):
+ if val >= 0:
+ return val
+ else:
+ return (2**bits) + val
+
+def sign(a):
+ if a > 0:
+ return 1
+ else:
+ return -1
+
+class TestToyotaSafety(unittest.TestCase):
+ @classmethod
+ def setUp(cls):
+ cls.safety = libpandasafety_py.libpandasafety
+ cls.safety.safety_set_mode(0x1335, 66)
+ cls.safety.init_tests_toyota()
+
+ def _torque_driver_msg(self, torque):
+ to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
+ to_send[0].RIR = 0x260 << 21
+
+ t = twos_comp(torque, 16)
+ to_send[0].RDLR = t | ((t & 0xFF) << 16)
+ return to_send
+
+ def _torque_driver_msg_array(self, torque):
+ for i in range(6):
+ self.safety.safety_rx_hook(self._torque_driver_msg(torque))
+
+ def _angle_meas_msg(self, angle):
+ to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
+ to_send[0].RIR = 0x25 << 21
+
+ t = twos_comp(angle, 12)
+ to_send[0].RDLR = ((t & 0xF00) >> 8) | ((t & 0xFF) << 8)
+ return to_send
+
+ def _angle_meas_msg_array(self, angle):
+ for i in range(6):
+ self.safety.safety_rx_hook(self._angle_meas_msg(angle))
+
+ def _ipas_state_msg(self, state):
+ to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
+ to_send[0].RIR = 0x262 << 21
+
+ to_send[0].RDLR = state & 0xF
+ return to_send
+
+ def _ipas_control_msg(self, angle, state):
+ # note: we command 2/3 of the angle due to CAN conversion
+ to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
+ to_send[0].RIR = 0x266 << 21
+
+ t = twos_comp(angle, 12)
+ to_send[0].RDLR = ((t & 0xF00) >> 8) | ((t & 0xFF) << 8)
+ to_send[0].RDLR |= ((state & 0xf) << 4)
+
+ return to_send
+
+ def _speed_msg(self, speed):
+ to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
+ to_send[0].RIR = 0xb4 << 21
+ speed = int(speed * 100 * 3.6)
+
+ to_send[0].RDHR = ((speed & 0xFF) << 16) | (speed & 0xFF00)
+ return to_send
+
+ def test_ipas_override(self):
+
+ ## angle control is not active
+ self.safety.set_controls_allowed(1)
+
+ # 3 consecutive msgs where driver exceeds threshold but angle_control isn't active
+ self.safety.set_controls_allowed(1)
+ self._torque_driver_msg_array(IPAS_OVERRIDE_THRESHOLD + 1)
+ self.assertTrue(self.safety.get_controls_allowed())
+
+ self._torque_driver_msg_array(-IPAS_OVERRIDE_THRESHOLD - 1)
+ self.assertTrue(self.safety.get_controls_allowed())
+
+ # ipas state is override
+ self.safety.safety_rx_hook(self._ipas_state_msg(5))
+ self.assertTrue(self.safety.get_controls_allowed())
+
+ ## now angle control is active
+ self.safety.safety_tx_hook(self._ipas_control_msg(0, 0))
+ self.safety.safety_rx_hook(self._ipas_state_msg(0))
+
+ # 3 consecutive msgs where driver does exceed threshold
+ self.safety.set_controls_allowed(1)
+ self._torque_driver_msg_array(IPAS_OVERRIDE_THRESHOLD + 1)
+ self.assertFalse(self.safety.get_controls_allowed())
+
+ self.safety.set_controls_allowed(1)
+ self._torque_driver_msg_array(-IPAS_OVERRIDE_THRESHOLD - 1)
+ self.assertFalse(self.safety.get_controls_allowed())
+
+ # ipas state is override and torque isn't overriding any more
+ self.safety.set_controls_allowed(1)
+ self._torque_driver_msg_array(0)
+ self.safety.safety_rx_hook(self._ipas_state_msg(5))
+ self.assertFalse(self.safety.get_controls_allowed())
+
+ # 3 consecutive msgs where driver does not exceed threshold and
+ # ipas state is not override
+ self.safety.set_controls_allowed(1)
+ self.safety.safety_rx_hook(self._ipas_state_msg(0))
+ self.assertTrue(self.safety.get_controls_allowed())
+
+ self._torque_driver_msg_array(IPAS_OVERRIDE_THRESHOLD)
+ self.assertTrue(self.safety.get_controls_allowed())
+
+ self._torque_driver_msg_array(-IPAS_OVERRIDE_THRESHOLD)
+ self.assertTrue(self.safety.get_controls_allowed())
+
+ # reset no angle control at the end of the test
+ self.safety.reset_angle_control()
+
+ def test_angle_cmd_when_disabled(self):
+
+ self.safety.set_controls_allowed(0)
+
+ # test angle cmd too far from actual
+ angle_refs = [-10, 10]
+ deltas = range(-2, 3)
+ expected_results = [False, True, True, True, False]
+
+ for a in angle_refs:
+ self._angle_meas_msg_array(a)
+ for i, d in enumerate(deltas):
+ self.assertEqual(expected_results[i], self.safety.safety_tx_hook(self._ipas_control_msg(a + d, 1)))
+
+ # test ipas state cmd enabled
+ self._angle_meas_msg_array(0)
+ self.assertEqual(0, self.safety.safety_tx_hook(self._ipas_control_msg(0, 3)))
+
+ # reset no angle control at the end of the test
+ self.safety.reset_angle_control()
+
+ def test_angle_cmd_when_enabled(self):
+
+ # ipas angle cmd should pass through when controls are enabled
+
+ self.safety.set_controls_allowed(1)
+ self._angle_meas_msg_array(0)
+ self.safety.safety_rx_hook(self._speed_msg(0.1))
+
+ self.assertEqual(1, self.safety.safety_tx_hook(self._ipas_control_msg(0, 1)))
+ self.assertEqual(1, self.safety.safety_tx_hook(self._ipas_control_msg(4, 1)))
+ self.assertEqual(1, self.safety.safety_tx_hook(self._ipas_control_msg(0, 3)))
+ self.assertEqual(1, self.safety.safety_tx_hook(self._ipas_control_msg(-4, 3)))
+ self.assertEqual(1, self.safety.safety_tx_hook(self._ipas_control_msg(-8, 3)))
+
+ # reset no angle control at the end of the test
+ self.safety.reset_angle_control()
+
+ def test_angle_cmd_rate_when_disabled(self):
+
+ # as long as the command is close to the measured, no rate limit is enforced when
+ # controls are disabled
+ self.safety.set_controls_allowed(0)
+ self.safety.safety_rx_hook(self._angle_meas_msg(0))
+ self.assertEqual(1, self.safety.safety_tx_hook(self._ipas_control_msg(0, 1)))
+ self.safety.safety_rx_hook(self._angle_meas_msg(100))
+ self.assertEqual(1, self.safety.safety_tx_hook(self._ipas_control_msg(100, 1)))
+ self.safety.safety_rx_hook(self._angle_meas_msg(-100))
+ self.assertEqual(1, self.safety.safety_tx_hook(self._ipas_control_msg(-100, 1)))
+
+ # reset no angle control at the end of the test
+ self.safety.reset_angle_control()
+
+ def test_angle_cmd_rate_when_enabled(self):
+
+ # when controls are allowed, angle cmd rate limit is enforced
+ # test 1: no limitations if we stay within limits
+ speeds = [0., 1., 5., 10., 15., 100.]
+ angles = [-300, -100, -10, 0, 10, 100, 300]
+ for a in angles:
+ for s in speeds:
+
+ # first test against false positives
+ self._angle_meas_msg_array(a)
+ self.safety.safety_tx_hook(self._ipas_control_msg(a, 1))
+ self.safety.set_controls_allowed(1)
+ self.safety.safety_rx_hook(self._speed_msg(s))
+ max_delta_up = int(np.interp(s, ANGLE_DELTA_BP, ANGLE_DELTA_V) * 2 / 3. + 1.)
+ max_delta_down = int(np.interp(s, ANGLE_DELTA_BP, ANGLE_DELTA_VU) * 2 / 3. + 1.)
+ self.assertEqual(True, self.safety.safety_tx_hook(self._ipas_control_msg(a + sign(a) * max_delta_up, 1)))
+ self.assertTrue(self.safety.get_controls_allowed())
+ self.assertEqual(True, self.safety.safety_tx_hook(self._ipas_control_msg(a, 1)))
+ self.assertTrue(self.safety.get_controls_allowed())
+ self.assertEqual(True, self.safety.safety_tx_hook(self._ipas_control_msg(a - sign(a) * max_delta_down, 1)))
+ self.assertTrue(self.safety.get_controls_allowed())
+
+ # now inject too high rates
+ self.assertEqual(False, self.safety.safety_tx_hook(self._ipas_control_msg(a + sign(a) *
+ (max_delta_up + 1), 1)))
+ self.assertFalse(self.safety.get_controls_allowed())
+ self.safety.set_controls_allowed(1)
+ self.assertEqual(True, self.safety.safety_tx_hook(self._ipas_control_msg(a + sign(a) * max_delta_up, 1)))
+ self.assertTrue(self.safety.get_controls_allowed())
+ self.assertEqual(True, self.safety.safety_tx_hook(self._ipas_control_msg(a, 1)))
+ self.assertTrue(self.safety.get_controls_allowed())
+ self.assertEqual(False, self.safety.safety_tx_hook(self._ipas_control_msg(a - sign(a) *
+ (max_delta_down + 1), 1)))
+ self.assertFalse(self.safety.get_controls_allowed())
+
+ # reset no angle control at the end of the test
+ self.safety.reset_angle_control()
+
+ def test_angle_measured_rate(self):
+
+ speeds = [0., 1., 5., 10., 15., 100.]
+ angles = [-300, -100, -10, 0, 10, 100, 300]
+ angles = [10]
+ for a in angles:
+ for s in speeds:
+ self._angle_meas_msg_array(a)
+ self.safety.safety_tx_hook(self._ipas_control_msg(a, 1))
+ self.safety.set_controls_allowed(1)
+ self.safety.safety_rx_hook(self._speed_msg(s))
+ max_delta_up = int(np.interp(s, ANGLE_DELTA_BP, ANGLE_DELTA_V) * 2 / 3. + 1.)
+ max_delta_down = int(np.interp(s, ANGLE_DELTA_BP, ANGLE_DELTA_VU) * 2 / 3. + 1.)
+ self.safety.safety_rx_hook(self._angle_meas_msg(a))
+ self.assertTrue(self.safety.get_controls_allowed())
+ self.safety.safety_rx_hook(self._angle_meas_msg(a + 150))
+ self.assertFalse(self.safety.get_controls_allowed())
+
+ # reset no angle control at the end of the test
+ self.safety.reset_angle_control()
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/panda/tests/safety/trim_csv.py b/panda/tests/safety/trim_csv.py
deleted file mode 100755
index 511bd385f..000000000
--- a/panda/tests/safety/trim_csv.py
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/env python2
-
-# This trims CAN message CSV files to just the messages relevant for Panda testing.
-# Usage:
-# cat input.csv | ./trim_csv.py > output.csv
-import fileinput
-
-addr_to_keep = [544, 0x1f4, 0x292] # For Chrysler, update to the addresses that matter for you.
-
-for line in fileinput.input():
- line = line.strip()
- cols = line.split(',')
- if len(cols) != 4:
- continue # malformed, such as at the end or every 60s.
- (_, addr, bus, _) = cols
- if (addr == 'addr'):
- continue
- if (int(bus) == 128): # Keep all messages sent by OpenPilot.
- print line
- elif (int(addr) in addr_to_keep):
- print line
diff --git a/panda/tests/safety_replay/Dockerfile b/panda/tests/safety_replay/Dockerfile
new file mode 100644
index 000000000..bf2b7f2c1
--- /dev/null
+++ b/panda/tests/safety_replay/Dockerfile
@@ -0,0 +1,20 @@
+FROM ubuntu:16.04
+
+RUN apt-get update && apt-get install -y make clang python python-pip git libarchive-dev libusb-1.0-0
+
+COPY tests/safety_replay/requirements.txt requirements.txt
+RUN pip install -r requirements.txt
+COPY tests/safety_replay/install_capnp.sh install_capnp.sh
+RUN ./install_capnp.sh
+
+RUN mkdir /openpilot
+WORKDIR /openpilot
+RUN git clone https://github.com/commaai/cereal.git || true
+WORKDIR /openpilot/cereal
+RUN git checkout f7043fde062cbfd49ec90af669901a9caba52de9
+COPY . /openpilot/panda
+
+WORKDIR /openpilot/panda/tests/safety_replay
+RUN git clone https://github.com/commaai/openpilot-tools.git tools || true
+WORKDIR tools
+RUN git checkout b6461274d684915f39dc45efc5292ea890698da9
diff --git a/pyextra/jsonrpc/backend/__init__.py b/panda/tests/safety_replay/__init__.py
similarity index 100%
rename from pyextra/jsonrpc/backend/__init__.py
rename to panda/tests/safety_replay/__init__.py
diff --git a/panda/tests/safety_replay/helpers.py b/panda/tests/safety_replay/helpers.py
new file mode 100644
index 000000000..05bbe0893
--- /dev/null
+++ b/panda/tests/safety_replay/helpers.py
@@ -0,0 +1,104 @@
+import struct
+import panda.tests.safety.libpandasafety_py as libpandasafety_py
+
+safety_modes = {
+ "NOOUTPUT": 0,
+ "HONDA": 1,
+ "TOYOTA": 2,
+ "GM": 3,
+ "HONDA_BOSCH": 4,
+ "FORD": 5,
+ "CADILLAC": 6,
+ "HYUNDAI": 7,
+ "TESLA": 8,
+ "CHRYSLER": 9,
+ "SUBARU": 10,
+ "GM_ASCM": 0x1334,
+ "TOYOTA_IPAS": 0x1335,
+ "ALLOUTPUT": 0x1337,
+ "ELM327": 0xE327
+}
+
+def to_signed(d, bits):
+ ret = d
+ if d >= (1 << (bits - 1)):
+ ret = d - (1 << bits)
+ return ret
+
+def is_steering_msg(mode, addr):
+ ret = False
+ if mode == safety_modes["HONDA"] or mode == safety_modes["HONDA_BOSCH"]:
+ ret = (addr == 0xE4) or (addr == 0x194) or (addr == 0x33D)
+ elif mode == safety_modes["TOYOTA"]:
+ ret = addr == 0x2E4
+ elif mode == safety_modes["GM"]:
+ ret = addr == 384
+ elif mode == safety_modes["HYUNDAI"]:
+ ret = addr == 832
+ elif mode == safety_modes["CHRYSLER"]:
+ ret = addr == 0x292
+ elif mode == safety_modes["SUBARU"]:
+ ret = addr == 0x122
+ return ret
+
+def get_steer_torque(mode, to_send):
+ ret = 0
+ if mode == safety_modes["HONDA"] or mode == safety_modes["HONDA_BOSCH"]:
+ ret = to_send.RDLR & 0xFFFF0000
+ elif mode == safety_modes["TOYOTA"]:
+ ret = (to_send.RDLR & 0xFF00) | ((to_send.RDLR >> 16) & 0xFF)
+ ret = to_signed(ret, 16)
+ elif mode == safety_modes["GM"]:
+ ret = ((to_send.RDLR & 0x7) << 8) + ((to_send.RDLR & 0xFF00) >> 8)
+ ret = to_signed(ret, 11)
+ elif mode == safety_modes["HYUNDAI"]:
+ ret = ((to_send.RDLR >> 16) & 0x7ff) - 1024
+ elif mode == safety_modes["CHRYSLER"]:
+ ret = ((to_send.RDLR & 0x7) << 8) + ((to_send.RDLR & 0xFF00) >> 8) - 1024
+ elif mode == safety_modes["SUBARU"]:
+ ret = ((to_send.RDLR >> 16) & 0x1FFF)
+ ret = to_signed(ret, 13)
+ return ret
+
+def set_desired_torque_last(safety, mode, torque):
+ if mode == safety_modes["HONDA"] or mode == safety_modes["HONDA_BOSCH"]:
+ pass # honda safety mode doesn't enforce a rate on steering msgs
+ elif mode == safety_modes["TOYOTA"]:
+ safety.set_toyota_desired_torque_last(torque)
+ elif mode == safety_modes["GM"]:
+ safety.set_gm_desired_torque_last(torque)
+ elif mode == safety_modes["HYUNDAI"]:
+ safety.set_hyundai_desired_torque_last(torque)
+ elif mode == safety_modes["CHRYSLER"]:
+ safety.set_chrysler_desired_torque_last(torque)
+ elif mode == safety_modes["SUBARU"]:
+ safety.set_subaru_desired_torque_last(torque)
+
+def package_can_msg(msg):
+ addr_shift = 3 if msg.address >= 0x800 else 21
+ rdlr, rdhr = struct.unpack('II', msg.dat.ljust(8, b'\x00'))
+
+ ret = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
+ ret[0].RIR = msg.address << addr_shift
+ ret[0].RDTR = len(msg.dat) | ((msg.src & 0xF) << 4)
+ ret[0].RDHR = rdhr
+ ret[0].RDLR = rdlr
+
+ return ret
+
+def init_segment(safety, lr, mode):
+ sendcan = (msg for msg in lr if msg.which() == 'sendcan')
+ steering_msgs = (can for msg in sendcan for can in msg.sendcan if is_steering_msg(mode, can.address))
+
+ msg = next(steering_msgs, None)
+ if msg is None:
+ # no steering msgs
+ return
+
+ to_send = package_can_msg(msg)
+ torque = get_steer_torque(mode, to_send)
+ if torque != 0:
+ safety.set_controls_allowed(1)
+ set_desired_torque_last(safety, mode, torque)
+ assert safety.safety_tx_hook(to_send), "failed to initialize panda safety for segment"
+
diff --git a/panda/tests/safety_replay/install_capnp.sh b/panda/tests/safety_replay/install_capnp.sh
new file mode 100755
index 000000000..e13ab48c2
--- /dev/null
+++ b/panda/tests/safety_replay/install_capnp.sh
@@ -0,0 +1,20 @@
+#!/bin/bash -e
+
+apt-get install -y autoconf curl libtool
+curl -O https://capnproto.org/capnproto-c++-0.6.1.tar.gz
+tar xvf capnproto-c++-0.6.1.tar.gz
+cd capnproto-c++-0.6.1
+./configure --prefix=/usr/local CPPFLAGS=-DPIC CFLAGS=-fPIC CXXFLAGS=-fPIC LDFLAGS=-fPIC --disable-shared --enable-static
+make -j4
+make install
+
+cd ..
+git clone https://github.com/commaai/c-capnproto.git
+cd c-capnproto
+git checkout 2e625acacf58a5f5c8828d8453d1f8dacc700a96
+git submodule update --init --recursive
+autoreconf -f -i -s
+CFLAGS="-fPIC" ./configure --prefix=/usr/local
+make -j4
+make install
+
diff --git a/panda/tests/safety_replay/replay_drive.py b/panda/tests/safety_replay/replay_drive.py
new file mode 100755
index 000000000..1b2ba082a
--- /dev/null
+++ b/panda/tests/safety_replay/replay_drive.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python2
+
+import os
+import sys
+import panda.tests.safety.libpandasafety_py as libpandasafety_py
+from panda.tests.safety_replay.helpers import is_steering_msg, get_steer_torque, \
+ set_desired_torque_last, package_can_msg, \
+ init_segment, safety_modes
+from tools.lib.logreader import LogReader
+
+# replay a drive to check for safety violations
+def replay_drive(lr, safety_mode, param):
+ safety = libpandasafety_py.libpandasafety
+
+ err = safety.safety_set_mode(safety_mode, param)
+ assert err == 0, "invalid safety mode: %d" % safety_mode
+
+ if "SEGMENT" in os.environ:
+ init_segment(safety, lr, mode)
+
+ tx_tot, tx_blocked, tx_controls, tx_controls_blocked = 0, 0, 0, 0
+ blocked_addrs = set()
+ start_t = None
+
+ for msg in lr:
+ if start_t is None:
+ start_t = msg.logMonoTime
+ safety.set_timer(((msg.logMonoTime / 1000)) % 0xFFFFFFFF)
+
+ if msg.which() == 'sendcan':
+ for canmsg in msg.sendcan:
+ to_send = package_can_msg(canmsg)
+ sent = safety.safety_tx_hook(to_send)
+ if not sent:
+ tx_blocked += 1
+ tx_controls_blocked += safety.get_controls_allowed()
+ blocked_addrs.add(canmsg.address)
+
+ if "DEBUG" in os.environ:
+ print "blocked %d at %f" % (canmsg.address, (msg.logMonoTime - start_t)/(1e9))
+ tx_controls += safety.get_controls_allowed()
+ tx_tot += 1
+ elif msg.which() == 'can':
+ for canmsg in msg.can:
+ # ignore msgs we sent
+ if canmsg.src >= 128:
+ continue
+ to_push = package_can_msg(canmsg)
+ safety.safety_rx_hook(to_push)
+
+ print "total openpilot msgs:", tx_tot
+ print "total msgs with controls allowed:", tx_controls
+ print "blocked msgs:", tx_blocked
+ print "blocked with controls allowed:", tx_controls_blocked
+ print "blocked addrs:", blocked_addrs
+
+ return tx_controls_blocked == 0
+
+if __name__ == "__main__":
+ if sys.argv[2] in safety_modes:
+ mode = safety_modes[sys.argv[2]]
+ else:
+ mode = int(sys.argv[2])
+ param = 0 if len(sys.argv) < 4 else int(sys.argv[3])
+ lr = LogReader(sys.argv[1])
+
+ print "replaying drive %s with safety mode %d and param %d" % (sys.argv[1], mode, param)
+
+ replay_drive(lr, mode, param)
+
diff --git a/panda/tests/safety_replay/requirements.txt b/panda/tests/safety_replay/requirements.txt
new file mode 100644
index 000000000..4c9d301dc
--- /dev/null
+++ b/panda/tests/safety_replay/requirements.txt
@@ -0,0 +1,8 @@
+aenum
+cffi==1.11.4
+libusb1==1.6.6
+numpy==1.14.5
+requests
+subprocess32
+libarchive
+pycapnp
diff --git a/panda/tests/safety_replay/test_safety_replay.py b/panda/tests/safety_replay/test_safety_replay.py
new file mode 100755
index 000000000..ecc34161f
--- /dev/null
+++ b/panda/tests/safety_replay/test_safety_replay.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python2
+
+import os
+import requests
+
+from helpers import safety_modes
+from replay_drive import replay_drive
+from tools.lib.logreader import LogReader
+
+BASE_URL = "https://commadataci.blob.core.windows.net/openpilotci/"
+
+# (route, safety mode, param)
+logs = [
+ ("b0c9d2329ad1606b|2019-05-30--20-23-57.bz2", "HONDA", 0), # HONDA.CIVIC
+ ("38bfd238edecbcd7|2019-06-07--10-15-25.bz2", "TOYOTA", 66), # TOYOTA.PRIUS
+ ("f89c604cf653e2bf|2018-09-29--13-46-50.bz2", "GM", 0), # GM.VOLT
+ ("0375fdf7b1ce594d|2019-05-21--20-10-33.bz2", "HONDA_BOSCH", 1), # HONDA.ACCORD
+ ("02ec6bea180a4d36|2019-04-17--11-21-35.bz2", "HYUNDAI", 0), # HYUNDAI.SANTA_FE
+ ("03efb1fda29e30fe|2019-02-21--18-03-45.bz2", "CHRYSLER", 0), # CHRYSLER.PACIFICA_2018_HYBRID
+ ("791340bc01ed993d|2019-04-08--10-26-00.bz2", "SUBARU", 0), # SUBARU.IMPREZA
+]
+
+if __name__ == "__main__":
+ for route, _, _ in logs:
+ if not os.path.isfile(route):
+ with open(route, "w") as f:
+ f.write(requests.get(BASE_URL + route).content)
+
+ failed = []
+ for route, mode, param in logs:
+ lr = LogReader(route)
+ m = safety_modes.get(mode, mode)
+
+ print "\nreplaying %s with safety mode %d and param %s" % (route, m, param)
+ if not replay_drive(lr, m, int(param)):
+ failed.append(route)
+
+ for f in failed:
+ print "\n**** failed on %s ****" % f
+ assert len(failed) == 0, "\nfailed on %d logs" % len(failed)
+
diff --git a/phonelibs/android_frameworks_native/get.txt b/phonelibs/android_frameworks_native/get.txt
new file mode 100644
index 000000000..31f42ebe0
--- /dev/null
+++ b/phonelibs/android_frameworks_native/get.txt
@@ -0,0 +1,3 @@
+git clone https://github.com/CyanogenMod/android_frameworks_native.git && cd android_frameworks_native
+git reset --hard b22bca465e55618a949d9cbdea665a1a3a831241
+cp -r include ~/one/phonelibs/android_frameworks_native/
diff --git a/phonelibs/android_frameworks_native/include/android/asset_manager.h b/phonelibs/android_frameworks_native/include/android/asset_manager.h
new file mode 100644
index 000000000..d65483968
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/android/asset_manager.h
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ */
+
+/**
+ * @addtogroup Asset
+ * @{
+ */
+
+/**
+ * @file asset_manager.h
+ */
+
+#ifndef ANDROID_ASSET_MANAGER_H
+#define ANDROID_ASSET_MANAGER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct AAssetManager;
+/**
+ * {@link AAssetManager} provides access to an application's raw assets by
+ * creating {@link AAsset} objects.
+ *
+ * AAssetManager is a wrapper to the low-level native implementation
+ * of the java {@link AAssetManager}, a pointer can be obtained using
+ * AAssetManager_fromJava().
+ *
+ * The asset hierarchy may be examined like a filesystem, using
+ * {@link AAssetDir} objects to peruse a single directory.
+ *
+ * A native {@link AAssetManager} pointer may be shared across multiple threads.
+ */
+typedef struct AAssetManager AAssetManager;
+
+struct AAssetDir;
+/**
+ * {@link AAssetDir} provides access to a chunk of the asset hierarchy as if
+ * it were a single directory. The contents are populated by the
+ * {@link AAssetManager}.
+ *
+ * The list of files will be sorted in ascending order by ASCII value.
+ */
+typedef struct AAssetDir AAssetDir;
+
+struct AAsset;
+/**
+ * {@link AAsset} provides access to a read-only asset.
+ *
+ * {@link AAsset} objects are NOT thread-safe, and should not be shared across
+ * threads.
+ */
+typedef struct AAsset AAsset;
+
+/** Available access modes for opening assets with {@link AAssetManager_open} */
+enum {
+ /** No specific information about how data will be accessed. **/
+ AASSET_MODE_UNKNOWN = 0,
+ /** Read chunks, and seek forward and backward. */
+ AASSET_MODE_RANDOM = 1,
+ /** Read sequentially, with an occasional forward seek. */
+ AASSET_MODE_STREAMING = 2,
+ /** Caller plans to ask for a read-only buffer with all data. */
+ AASSET_MODE_BUFFER = 3
+};
+
+
+/**
+ * Open the named directory within the asset hierarchy. The directory can then
+ * be inspected with the AAssetDir functions. To open the top-level directory,
+ * pass in "" as the dirName.
+ *
+ * The object returned here should be freed by calling AAssetDir_close().
+ */
+AAssetDir* AAssetManager_openDir(AAssetManager* mgr, const char* dirName);
+
+/**
+ * Open an asset.
+ *
+ * The object returned here should be freed by calling AAsset_close().
+ */
+AAsset* AAssetManager_open(AAssetManager* mgr, const char* filename, int mode);
+
+/**
+ * Iterate over the files in an asset directory. A NULL string is returned
+ * when all the file names have been returned.
+ *
+ * The returned file name is suitable for passing to AAssetManager_open().
+ *
+ * The string returned here is owned by the AssetDir implementation and is not
+ * guaranteed to remain valid if any other calls are made on this AAssetDir
+ * instance.
+ */
+const char* AAssetDir_getNextFileName(AAssetDir* assetDir);
+
+/**
+ * Reset the iteration state of AAssetDir_getNextFileName() to the beginning.
+ */
+void AAssetDir_rewind(AAssetDir* assetDir);
+
+/**
+ * Close an opened AAssetDir, freeing any related resources.
+ */
+void AAssetDir_close(AAssetDir* assetDir);
+
+/**
+ * Attempt to read 'count' bytes of data from the current offset.
+ *
+ * Returns the number of bytes read, zero on EOF, or < 0 on error.
+ */
+int AAsset_read(AAsset* asset, void* buf, size_t count);
+
+/**
+ * Seek to the specified offset within the asset data. 'whence' uses the
+ * same constants as lseek()/fseek().
+ *
+ * Returns the new position on success, or (off_t) -1 on error.
+ */
+off_t AAsset_seek(AAsset* asset, off_t offset, int whence);
+
+/**
+ * Seek to the specified offset within the asset data. 'whence' uses the
+ * same constants as lseek()/fseek().
+ *
+ * Uses 64-bit data type for large files as opposed to the 32-bit type used
+ * by AAsset_seek.
+ *
+ * Returns the new position on success, or (off64_t) -1 on error.
+ */
+off64_t AAsset_seek64(AAsset* asset, off64_t offset, int whence);
+
+/**
+ * Close the asset, freeing all associated resources.
+ */
+void AAsset_close(AAsset* asset);
+
+/**
+ * Get a pointer to a buffer holding the entire contents of the assset.
+ *
+ * Returns NULL on failure.
+ */
+const void* AAsset_getBuffer(AAsset* asset);
+
+/**
+ * Report the total size of the asset data.
+ */
+off_t AAsset_getLength(AAsset* asset);
+
+/**
+ * Report the total size of the asset data. Reports the size using a 64-bit
+ * number insted of 32-bit as AAsset_getLength.
+ */
+off64_t AAsset_getLength64(AAsset* asset);
+
+/**
+ * Report the total amount of asset data that can be read from the current position.
+ */
+off_t AAsset_getRemainingLength(AAsset* asset);
+
+/**
+ * Report the total amount of asset data that can be read from the current position.
+ *
+ * Uses a 64-bit number instead of a 32-bit number as AAsset_getRemainingLength does.
+ */
+off64_t AAsset_getRemainingLength64(AAsset* asset);
+
+/**
+ * Open a new file descriptor that can be used to read the asset data. If the
+ * start or length cannot be represented by a 32-bit number, it will be
+ * truncated. If the file is large, use AAsset_openFileDescriptor64 instead.
+ *
+ * Returns < 0 if direct fd access is not possible (for example, if the asset is
+ * compressed).
+ */
+int AAsset_openFileDescriptor(AAsset* asset, off_t* outStart, off_t* outLength);
+
+/**
+ * Open a new file descriptor that can be used to read the asset data.
+ *
+ * Uses a 64-bit number for the offset and length instead of 32-bit instead of
+ * as AAsset_openFileDescriptor does.
+ *
+ * Returns < 0 if direct fd access is not possible (for example, if the asset is
+ * compressed).
+ */
+int AAsset_openFileDescriptor64(AAsset* asset, off64_t* outStart, off64_t* outLength);
+
+/**
+ * Returns whether this asset's internal buffer is allocated in ordinary RAM (i.e. not
+ * mmapped).
+ */
+int AAsset_isAllocated(AAsset* asset);
+
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // ANDROID_ASSET_MANAGER_H
+
+/** @} */
diff --git a/phonelibs/android_frameworks_native/include/android/asset_manager_jni.h b/phonelibs/android_frameworks_native/include/android/asset_manager_jni.h
new file mode 100644
index 000000000..dcee17e10
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/android/asset_manager_jni.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ */
+
+/**
+ * @addtogroup Asset
+ * @{
+ */
+
+/**
+ * @file asset_manager_jni.h
+ */
+
+#ifndef ANDROID_ASSET_MANAGER_JNI_H
+#define ANDROID_ASSET_MANAGER_JNI_H
+
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Given a Dalvik AssetManager object, obtain the corresponding native AAssetManager
+ * object. Note that the caller is responsible for obtaining and holding a VM reference
+ * to the jobject to prevent its being garbage collected while the native object is
+ * in use.
+ */
+AAssetManager* AAssetManager_fromJava(JNIEnv* env, jobject assetManager);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // ANDROID_ASSET_MANAGER_JNI_H
+
+/** @} */
diff --git a/phonelibs/android_frameworks_native/include/android/bitmap.h b/phonelibs/android_frameworks_native/include/android/bitmap.h
new file mode 100644
index 000000000..261e64fac
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/android/bitmap.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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.
+ */
+
+/**
+ * @addtogroup Bitmap
+ * @{
+ */
+
+/**
+ * @file bitmap.h
+ */
+
+#ifndef ANDROID_BITMAP_H
+#define ANDROID_BITMAP_H
+
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** AndroidBitmap functions result code. */
+enum {
+ /** Operation was successful. */
+ ANDROID_BITMAP_RESULT_SUCCESS = 0,
+ /** Bad parameter. */
+ ANDROID_BITMAP_RESULT_BAD_PARAMETER = -1,
+ /** JNI exception occured. */
+ ANDROID_BITMAP_RESULT_JNI_EXCEPTION = -2,
+ /** Allocation failed. */
+ ANDROID_BITMAP_RESULT_ALLOCATION_FAILED = -3,
+};
+
+/** Backward compatibility: this macro used to be misspelled. */
+#define ANDROID_BITMAP_RESUT_SUCCESS ANDROID_BITMAP_RESULT_SUCCESS
+
+/** Bitmap pixel format. */
+enum AndroidBitmapFormat {
+ /** No format. */
+ ANDROID_BITMAP_FORMAT_NONE = 0,
+ /** Red: 8 bits, Green: 8 bits, Blue: 8 bits, Alpha: 8 bits. **/
+ ANDROID_BITMAP_FORMAT_RGBA_8888 = 1,
+ /** Red: 5 bits, Green: 6 bits, Blue: 5 bits. **/
+ ANDROID_BITMAP_FORMAT_RGB_565 = 4,
+ /** Red: 4 bits, Green: 4 bits, Blue: 4 bits, Alpha: 4 bits. **/
+ ANDROID_BITMAP_FORMAT_RGBA_4444 = 7,
+ /** Deprecated. */
+ ANDROID_BITMAP_FORMAT_A_8 = 8,
+};
+
+/** Bitmap info, see AndroidBitmap_getInfo(). */
+typedef struct {
+ /** The bitmap width in pixels. */
+ uint32_t width;
+ /** The bitmap height in pixels. */
+ uint32_t height;
+ /** The number of byte per row. */
+ uint32_t stride;
+ /** The bitmap pixel format. See {@link AndroidBitmapFormat} */
+ int32_t format;
+ /** Unused. */
+ uint32_t flags; // 0 for now
+} AndroidBitmapInfo;
+
+/**
+ * Given a java bitmap object, fill out the AndroidBitmapInfo struct for it.
+ * If the call fails, the info parameter will be ignored.
+ */
+int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap,
+ AndroidBitmapInfo* info);
+
+/**
+ * Given a java bitmap object, attempt to lock the pixel address.
+ * Locking will ensure that the memory for the pixels will not move
+ * until the unlockPixels call, and ensure that, if the pixels had been
+ * previously purged, they will have been restored.
+ *
+ * If this call succeeds, it must be balanced by a call to
+ * AndroidBitmap_unlockPixels, after which time the address of the pixels should
+ * no longer be used.
+ *
+ * If this succeeds, *addrPtr will be set to the pixel address. If the call
+ * fails, addrPtr will be ignored.
+ */
+int AndroidBitmap_lockPixels(JNIEnv* env, jobject jbitmap, void** addrPtr);
+
+/**
+ * Call this to balance a successful call to AndroidBitmap_lockPixels.
+ */
+int AndroidBitmap_unlockPixels(JNIEnv* env, jobject jbitmap);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/** @} */
diff --git a/phonelibs/android_frameworks_native/include/android/configuration.h b/phonelibs/android_frameworks_native/include/android/configuration.h
new file mode 100644
index 000000000..81f71a92c
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/android/configuration.h
@@ -0,0 +1,708 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ */
+
+/**
+ * @addtogroup Configuration
+ * @{
+ */
+
+/**
+ * @file configuration.h
+ */
+
+#ifndef ANDROID_CONFIGURATION_H
+#define ANDROID_CONFIGURATION_H
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct AConfiguration;
+/**
+ * {@link AConfiguration} is an opaque type used to get and set
+ * various subsystem configurations.
+ *
+ * A {@link AConfiguration} pointer can be obtained using:
+ * - AConfiguration_new()
+ * - AConfiguration_fromAssetManager()
+ */
+typedef struct AConfiguration AConfiguration;
+
+
+/**
+ * Define flags and constants for various subsystem configurations.
+ */
+enum {
+ /** Orientation: not specified. */
+ ACONFIGURATION_ORIENTATION_ANY = 0x0000,
+ /**
+ * Orientation: value corresponding to the
+ * port
+ * resource qualifier.
+ */
+ ACONFIGURATION_ORIENTATION_PORT = 0x0001,
+ /**
+ * Orientation: value corresponding to the
+ * land
+ * resource qualifier.
+ */
+ ACONFIGURATION_ORIENTATION_LAND = 0x0002,
+ /** @deprecated Not currently supported or used. */
+ ACONFIGURATION_ORIENTATION_SQUARE = 0x0003,
+
+ /** Touchscreen: not specified. */
+ ACONFIGURATION_TOUCHSCREEN_ANY = 0x0000,
+ /**
+ * Touchscreen: value corresponding to the
+ * notouch
+ * resource qualifier.
+ */
+ ACONFIGURATION_TOUCHSCREEN_NOTOUCH = 0x0001,
+ /** @deprecated Not currently supported or used. */
+ ACONFIGURATION_TOUCHSCREEN_STYLUS = 0x0002,
+ /**
+ * Touchscreen: value corresponding to the
+ * finger
+ * resource qualifier.
+ */
+ ACONFIGURATION_TOUCHSCREEN_FINGER = 0x0003,
+
+ /** Density: default density. */
+ ACONFIGURATION_DENSITY_DEFAULT = 0,
+ /**
+ * Density: value corresponding to the
+ * ldpi
+ * resource qualifier.
+ */
+ ACONFIGURATION_DENSITY_LOW = 120,
+ /**
+ * Density: value corresponding to the
+ * mdpi
+ * resource qualifier.
+ */
+ ACONFIGURATION_DENSITY_MEDIUM = 160,
+ /**
+ * Density: value corresponding to the
+ * tvdpi
+ * resource qualifier.
+ */
+ ACONFIGURATION_DENSITY_TV = 213,
+ /**
+ * Density: value corresponding to the
+ * hdpi
+ * resource qualifier.
+ */
+ ACONFIGURATION_DENSITY_HIGH = 240,
+ /**
+ * Density: value corresponding to the
+ * xhdpi
+ * resource qualifier.
+ */
+ ACONFIGURATION_DENSITY_XHIGH = 320,
+ /**
+ * Density: value corresponding to the
+ * xxhdpi
+ * resource qualifier.
+ */
+ ACONFIGURATION_DENSITY_XXHIGH = 480,
+ /**
+ * Density: value corresponding to the
+ * xxxhdpi
+ * resource qualifier.
+ */
+ ACONFIGURATION_DENSITY_XXXHIGH = 640,
+ /** Density: any density. */
+ ACONFIGURATION_DENSITY_ANY = 0xfffe,
+ /** Density: no density specified. */
+ ACONFIGURATION_DENSITY_NONE = 0xffff,
+
+ /** Keyboard: not specified. */
+ ACONFIGURATION_KEYBOARD_ANY = 0x0000,
+ /**
+ * Keyboard: value corresponding to the
+ * nokeys
+ * resource qualifier.
+ */
+ ACONFIGURATION_KEYBOARD_NOKEYS = 0x0001,
+ /**
+ * Keyboard: value corresponding to the
+ * qwerty
+ * resource qualifier.
+ */
+ ACONFIGURATION_KEYBOARD_QWERTY = 0x0002,
+ /**
+ * Keyboard: value corresponding to the
+ * 12key
+ * resource qualifier.
+ */
+ ACONFIGURATION_KEYBOARD_12KEY = 0x0003,
+
+ /** Navigation: not specified. */
+ ACONFIGURATION_NAVIGATION_ANY = 0x0000,
+ /**
+ * Navigation: value corresponding to the
+ * nonav
+ * resource qualifier.
+ */
+ ACONFIGURATION_NAVIGATION_NONAV = 0x0001,
+ /**
+ * Navigation: value corresponding to the
+ * dpad
+ * resource qualifier.
+ */
+ ACONFIGURATION_NAVIGATION_DPAD = 0x0002,
+ /**
+ * Navigation: value corresponding to the
+ * trackball
+ * resource qualifier.
+ */
+ ACONFIGURATION_NAVIGATION_TRACKBALL = 0x0003,
+ /**
+ * Navigation: value corresponding to the
+ * wheel
+ * resource qualifier.
+ */
+ ACONFIGURATION_NAVIGATION_WHEEL = 0x0004,
+
+ /** Keyboard availability: not specified. */
+ ACONFIGURATION_KEYSHIDDEN_ANY = 0x0000,
+ /**
+ * Keyboard availability: value corresponding to the
+ * keysexposed
+ * resource qualifier.
+ */
+ ACONFIGURATION_KEYSHIDDEN_NO = 0x0001,
+ /**
+ * Keyboard availability: value corresponding to the
+ * keyshidden
+ * resource qualifier.
+ */
+ ACONFIGURATION_KEYSHIDDEN_YES = 0x0002,
+ /**
+ * Keyboard availability: value corresponding to the
+ * keyssoft
+ * resource qualifier.
+ */
+ ACONFIGURATION_KEYSHIDDEN_SOFT = 0x0003,
+
+ /** Navigation availability: not specified. */
+ ACONFIGURATION_NAVHIDDEN_ANY = 0x0000,
+ /**
+ * Navigation availability: value corresponding to the
+ * navexposed
+ * resource qualifier.
+ */
+ ACONFIGURATION_NAVHIDDEN_NO = 0x0001,
+ /**
+ * Navigation availability: value corresponding to the
+ * navhidden
+ * resource qualifier.
+ */
+ ACONFIGURATION_NAVHIDDEN_YES = 0x0002,
+
+ /** Screen size: not specified. */
+ ACONFIGURATION_SCREENSIZE_ANY = 0x00,
+ /**
+ * Screen size: value indicating the screen is at least
+ * approximately 320x426 dp units, corresponding to the
+ * small
+ * resource qualifier.
+ */
+ ACONFIGURATION_SCREENSIZE_SMALL = 0x01,
+ /**
+ * Screen size: value indicating the screen is at least
+ * approximately 320x470 dp units, corresponding to the
+ * normal
+ * resource qualifier.
+ */
+ ACONFIGURATION_SCREENSIZE_NORMAL = 0x02,
+ /**
+ * Screen size: value indicating the screen is at least
+ * approximately 480x640 dp units, corresponding to the
+ * large
+ * resource qualifier.
+ */
+ ACONFIGURATION_SCREENSIZE_LARGE = 0x03,
+ /**
+ * Screen size: value indicating the screen is at least
+ * approximately 720x960 dp units, corresponding to the
+ * xlarge
+ * resource qualifier.
+ */
+ ACONFIGURATION_SCREENSIZE_XLARGE = 0x04,
+
+ /** Screen layout: not specified. */
+ ACONFIGURATION_SCREENLONG_ANY = 0x00,
+ /**
+ * Screen layout: value that corresponds to the
+ * notlong
+ * resource qualifier.
+ */
+ ACONFIGURATION_SCREENLONG_NO = 0x1,
+ /**
+ * Screen layout: value that corresponds to the
+ * long
+ * resource qualifier.
+ */
+ ACONFIGURATION_SCREENLONG_YES = 0x2,
+
+ ACONFIGURATION_SCREENROUND_ANY = 0x00,
+ ACONFIGURATION_SCREENROUND_NO = 0x1,
+ ACONFIGURATION_SCREENROUND_YES = 0x2,
+
+ /** UI mode: not specified. */
+ ACONFIGURATION_UI_MODE_TYPE_ANY = 0x00,
+ /**
+ * UI mode: value that corresponds to
+ * no
+ * UI mode type resource qualifier specified.
+ */
+ ACONFIGURATION_UI_MODE_TYPE_NORMAL = 0x01,
+ /**
+ * UI mode: value that corresponds to
+ * desk resource qualifier specified.
+ */
+ ACONFIGURATION_UI_MODE_TYPE_DESK = 0x02,
+ /**
+ * UI mode: value that corresponds to
+ * car resource qualifier specified.
+ */
+ ACONFIGURATION_UI_MODE_TYPE_CAR = 0x03,
+ /**
+ * UI mode: value that corresponds to
+ * television resource qualifier specified.
+ */
+ ACONFIGURATION_UI_MODE_TYPE_TELEVISION = 0x04,
+ /**
+ * UI mode: value that corresponds to
+ * appliance resource qualifier specified.
+ */
+ ACONFIGURATION_UI_MODE_TYPE_APPLIANCE = 0x05,
+ /**
+ * UI mode: value that corresponds to
+ * watch resource qualifier specified.
+ */
+ ACONFIGURATION_UI_MODE_TYPE_WATCH = 0x06,
+
+ /** UI night mode: not specified.*/
+ ACONFIGURATION_UI_MODE_NIGHT_ANY = 0x00,
+ /**
+ * UI night mode: value that corresponds to
+ * notnight resource qualifier specified.
+ */
+ ACONFIGURATION_UI_MODE_NIGHT_NO = 0x1,
+ /**
+ * UI night mode: value that corresponds to
+ * night resource qualifier specified.
+ */
+ ACONFIGURATION_UI_MODE_NIGHT_YES = 0x2,
+
+ /** Screen width DPI: not specified. */
+ ACONFIGURATION_SCREEN_WIDTH_DP_ANY = 0x0000,
+
+ /** Screen height DPI: not specified. */
+ ACONFIGURATION_SCREEN_HEIGHT_DP_ANY = 0x0000,
+
+ /** Smallest screen width DPI: not specified.*/
+ ACONFIGURATION_SMALLEST_SCREEN_WIDTH_DP_ANY = 0x0000,
+
+ /** Layout direction: not specified. */
+ ACONFIGURATION_LAYOUTDIR_ANY = 0x00,
+ /**
+ * Layout direction: value that corresponds to
+ * ldltr resource qualifier specified.
+ */
+ ACONFIGURATION_LAYOUTDIR_LTR = 0x01,
+ /**
+ * Layout direction: value that corresponds to
+ * ldrtl resource qualifier specified.
+ */
+ ACONFIGURATION_LAYOUTDIR_RTL = 0x02,
+
+ /**
+ * Bit mask for
+ * mcc
+ * configuration.
+ */
+ ACONFIGURATION_MCC = 0x0001,
+ /**
+ * Bit mask for
+ * mnc
+ * configuration.
+ */
+ ACONFIGURATION_MNC = 0x0002,
+ /**
+ * Bit mask for
+ * locale
+ * configuration.
+ */
+ ACONFIGURATION_LOCALE = 0x0004,
+ /**
+ * Bit mask for
+ * touchscreen
+ * configuration.
+ */
+ ACONFIGURATION_TOUCHSCREEN = 0x0008,
+ /**
+ * Bit mask for
+ * keyboard
+ * configuration.
+ */
+ ACONFIGURATION_KEYBOARD = 0x0010,
+ /**
+ * Bit mask for
+ * keyboardHidden
+ * configuration.
+ */
+ ACONFIGURATION_KEYBOARD_HIDDEN = 0x0020,
+ /**
+ * Bit mask for
+ * navigation
+ * configuration.
+ */
+ ACONFIGURATION_NAVIGATION = 0x0040,
+ /**
+ * Bit mask for
+ * orientation
+ * configuration.
+ */
+ ACONFIGURATION_ORIENTATION = 0x0080,
+ /**
+ * Bit mask for
+ * density
+ * configuration.
+ */
+ ACONFIGURATION_DENSITY = 0x0100,
+ /**
+ * Bit mask for
+ * screen size
+ * configuration.
+ */
+ ACONFIGURATION_SCREEN_SIZE = 0x0200,
+ /**
+ * Bit mask for
+ * platform version
+ * configuration.
+ */
+ ACONFIGURATION_VERSION = 0x0400,
+ /**
+ * Bit mask for screen layout configuration.
+ */
+ ACONFIGURATION_SCREEN_LAYOUT = 0x0800,
+ /**
+ * Bit mask for
+ * ui mode
+ * configuration.
+ */
+ ACONFIGURATION_UI_MODE = 0x1000,
+ /**
+ * Bit mask for
+ * smallest screen width
+ * configuration.
+ */
+ ACONFIGURATION_SMALLEST_SCREEN_SIZE = 0x2000,
+ /**
+ * Bit mask for
+ * layout direction
+ * configuration.
+ */
+ ACONFIGURATION_LAYOUTDIR = 0x4000,
+ ACONFIGURATION_SCREEN_ROUND = 0x8000,
+ /**
+ * Constant used to to represent MNC (Mobile Network Code) zero.
+ * 0 cannot be used, since it is used to represent an undefined MNC.
+ */
+ ACONFIGURATION_MNC_ZERO = 0xffff,
+};
+
+/**
+ * Create a new AConfiguration, initialized with no values set.
+ */
+AConfiguration* AConfiguration_new();
+
+/**
+ * Free an AConfiguration that was previously created with
+ * AConfiguration_new().
+ */
+void AConfiguration_delete(AConfiguration* config);
+
+/**
+ * Create and return a new AConfiguration based on the current configuration in
+ * use in the given {@link AAssetManager}.
+ */
+void AConfiguration_fromAssetManager(AConfiguration* out, AAssetManager* am);
+
+/**
+ * Copy the contents of 'src' to 'dest'.
+ */
+void AConfiguration_copy(AConfiguration* dest, AConfiguration* src);
+
+/**
+ * Return the current MCC set in the configuration. 0 if not set.
+ */
+int32_t AConfiguration_getMcc(AConfiguration* config);
+
+/**
+ * Set the current MCC in the configuration. 0 to clear.
+ */
+void AConfiguration_setMcc(AConfiguration* config, int32_t mcc);
+
+/**
+ * Return the current MNC set in the configuration. 0 if not set.
+ */
+int32_t AConfiguration_getMnc(AConfiguration* config);
+
+/**
+ * Set the current MNC in the configuration. 0 to clear.
+ */
+void AConfiguration_setMnc(AConfiguration* config, int32_t mnc);
+
+/**
+ * Return the current language code set in the configuration. The output will
+ * be filled with an array of two characters. They are not 0-terminated. If
+ * a language is not set, they will be 0.
+ */
+void AConfiguration_getLanguage(AConfiguration* config, char* outLanguage);
+
+/**
+ * Set the current language code in the configuration, from the first two
+ * characters in the string.
+ */
+void AConfiguration_setLanguage(AConfiguration* config, const char* language);
+
+/**
+ * Return the current country code set in the configuration. The output will
+ * be filled with an array of two characters. They are not 0-terminated. If
+ * a country is not set, they will be 0.
+ */
+void AConfiguration_getCountry(AConfiguration* config, char* outCountry);
+
+/**
+ * Set the current country code in the configuration, from the first two
+ * characters in the string.
+ */
+void AConfiguration_setCountry(AConfiguration* config, const char* country);
+
+/**
+ * Return the current ACONFIGURATION_ORIENTATION_* set in the configuration.
+ */
+int32_t AConfiguration_getOrientation(AConfiguration* config);
+
+/**
+ * Set the current orientation in the configuration.
+ */
+void AConfiguration_setOrientation(AConfiguration* config, int32_t orientation);
+
+/**
+ * Return the current ACONFIGURATION_TOUCHSCREEN_* set in the configuration.
+ */
+int32_t AConfiguration_getTouchscreen(AConfiguration* config);
+
+/**
+ * Set the current touchscreen in the configuration.
+ */
+void AConfiguration_setTouchscreen(AConfiguration* config, int32_t touchscreen);
+
+/**
+ * Return the current ACONFIGURATION_DENSITY_* set in the configuration.
+ */
+int32_t AConfiguration_getDensity(AConfiguration* config);
+
+/**
+ * Set the current density in the configuration.
+ */
+void AConfiguration_setDensity(AConfiguration* config, int32_t density);
+
+/**
+ * Return the current ACONFIGURATION_KEYBOARD_* set in the configuration.
+ */
+int32_t AConfiguration_getKeyboard(AConfiguration* config);
+
+/**
+ * Set the current keyboard in the configuration.
+ */
+void AConfiguration_setKeyboard(AConfiguration* config, int32_t keyboard);
+
+/**
+ * Return the current ACONFIGURATION_NAVIGATION_* set in the configuration.
+ */
+int32_t AConfiguration_getNavigation(AConfiguration* config);
+
+/**
+ * Set the current navigation in the configuration.
+ */
+void AConfiguration_setNavigation(AConfiguration* config, int32_t navigation);
+
+/**
+ * Return the current ACONFIGURATION_KEYSHIDDEN_* set in the configuration.
+ */
+int32_t AConfiguration_getKeysHidden(AConfiguration* config);
+
+/**
+ * Set the current keys hidden in the configuration.
+ */
+void AConfiguration_setKeysHidden(AConfiguration* config, int32_t keysHidden);
+
+/**
+ * Return the current ACONFIGURATION_NAVHIDDEN_* set in the configuration.
+ */
+int32_t AConfiguration_getNavHidden(AConfiguration* config);
+
+/**
+ * Set the current nav hidden in the configuration.
+ */
+void AConfiguration_setNavHidden(AConfiguration* config, int32_t navHidden);
+
+/**
+ * Return the current SDK (API) version set in the configuration.
+ */
+int32_t AConfiguration_getSdkVersion(AConfiguration* config);
+
+/**
+ * Set the current SDK version in the configuration.
+ */
+void AConfiguration_setSdkVersion(AConfiguration* config, int32_t sdkVersion);
+
+/**
+ * Return the current ACONFIGURATION_SCREENSIZE_* set in the configuration.
+ */
+int32_t AConfiguration_getScreenSize(AConfiguration* config);
+
+/**
+ * Set the current screen size in the configuration.
+ */
+void AConfiguration_setScreenSize(AConfiguration* config, int32_t screenSize);
+
+/**
+ * Return the current ACONFIGURATION_SCREENLONG_* set in the configuration.
+ */
+int32_t AConfiguration_getScreenLong(AConfiguration* config);
+
+/**
+ * Set the current screen long in the configuration.
+ */
+void AConfiguration_setScreenLong(AConfiguration* config, int32_t screenLong);
+
+/**
+ * Return the current ACONFIGURATION_SCREENROUND_* set in the configuration.
+ */
+int32_t AConfiguration_getScreenRound(AConfiguration* config);
+
+/**
+ * Set the current screen round in the configuration.
+ */
+void AConfiguration_setScreenRound(AConfiguration* config, int32_t screenRound);
+
+/**
+ * Return the current ACONFIGURATION_UI_MODE_TYPE_* set in the configuration.
+ */
+int32_t AConfiguration_getUiModeType(AConfiguration* config);
+
+/**
+ * Set the current UI mode type in the configuration.
+ */
+void AConfiguration_setUiModeType(AConfiguration* config, int32_t uiModeType);
+
+/**
+ * Return the current ACONFIGURATION_UI_MODE_NIGHT_* set in the configuration.
+ */
+int32_t AConfiguration_getUiModeNight(AConfiguration* config);
+
+/**
+ * Set the current UI mode night in the configuration.
+ */
+void AConfiguration_setUiModeNight(AConfiguration* config, int32_t uiModeNight);
+
+/**
+ * Return the current configuration screen width in dp units, or
+ * ACONFIGURATION_SCREEN_WIDTH_DP_ANY if not set.
+ */
+int32_t AConfiguration_getScreenWidthDp(AConfiguration* config);
+
+/**
+ * Set the configuration's current screen width in dp units.
+ */
+void AConfiguration_setScreenWidthDp(AConfiguration* config, int32_t value);
+
+/**
+ * Return the current configuration screen height in dp units, or
+ * ACONFIGURATION_SCREEN_HEIGHT_DP_ANY if not set.
+ */
+int32_t AConfiguration_getScreenHeightDp(AConfiguration* config);
+
+/**
+ * Set the configuration's current screen width in dp units.
+ */
+void AConfiguration_setScreenHeightDp(AConfiguration* config, int32_t value);
+
+/**
+ * Return the configuration's smallest screen width in dp units, or
+ * ACONFIGURATION_SMALLEST_SCREEN_WIDTH_DP_ANY if not set.
+ */
+int32_t AConfiguration_getSmallestScreenWidthDp(AConfiguration* config);
+
+/**
+ * Set the configuration's smallest screen width in dp units.
+ */
+void AConfiguration_setSmallestScreenWidthDp(AConfiguration* config, int32_t value);
+
+/**
+ * Return the configuration's layout direction, or
+ * ACONFIGURATION_LAYOUTDIR_ANY if not set.
+ */
+int32_t AConfiguration_getLayoutDirection(AConfiguration* config);
+
+/**
+ * Set the configuration's layout direction.
+ */
+void AConfiguration_setLayoutDirection(AConfiguration* config, int32_t value);
+
+/**
+ * Perform a diff between two configurations. Returns a bit mask of
+ * ACONFIGURATION_* constants, each bit set meaning that configuration element
+ * is different between them.
+ */
+int32_t AConfiguration_diff(AConfiguration* config1, AConfiguration* config2);
+
+/**
+ * Determine whether 'base' is a valid configuration for use within the
+ * environment 'requested'. Returns 0 if there are any values in 'base'
+ * that conflict with 'requested'. Returns 1 if it does not conflict.
+ */
+int32_t AConfiguration_match(AConfiguration* base, AConfiguration* requested);
+
+/**
+ * Determine whether the configuration in 'test' is better than the existing
+ * configuration in 'base'. If 'requested' is non-NULL, this decision is based
+ * on the overall configuration given there. If it is NULL, this decision is
+ * simply based on which configuration is more specific. Returns non-0 if
+ * 'test' is better than 'base'.
+ *
+ * This assumes you have already filtered the configurations with
+ * AConfiguration_match().
+ */
+int32_t AConfiguration_isBetterThan(AConfiguration* base, AConfiguration* test,
+ AConfiguration* requested);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // ANDROID_CONFIGURATION_H
+
+/** @} */
diff --git a/phonelibs/android_frameworks_native/include/android/input.h b/phonelibs/android_frameworks_native/include/android/input.h
new file mode 100644
index 000000000..46cf89c7e
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/android/input.h
@@ -0,0 +1,1317 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ */
+
+/**
+ * @addtogroup Input
+ * @{
+ */
+
+/**
+ * @file input.h
+ */
+
+#ifndef _ANDROID_INPUT_H
+#define _ANDROID_INPUT_H
+
+/******************************************************************
+ *
+ * IMPORTANT NOTICE:
+ *
+ * This file is part of Android's set of stable system headers
+ * exposed by the Android NDK (Native Development Kit).
+ *
+ * Third-party source AND binary code relies on the definitions
+ * here to be FROZEN ON ALL UPCOMING PLATFORM RELEASES.
+ *
+ * - DO NOT MODIFY ENUMS (EXCEPT IF YOU ADD NEW 32-BIT VALUES)
+ * - DO NOT MODIFY CONSTANTS OR FUNCTIONAL MACROS
+ * - DO NOT CHANGE THE SIGNATURE OF FUNCTIONS IN ANY WAY
+ * - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES
+ */
+
+/*
+ * Structures and functions to receive and process input events in
+ * native code.
+ *
+ * NOTE: These functions MUST be implemented by /system/lib/libui.so
+ */
+
+#include
+#include
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Key states (may be returned by queries about the current state of a
+ * particular key code, scan code or switch).
+ */
+enum {
+ /** The key state is unknown or the requested key itself is not supported. */
+ AKEY_STATE_UNKNOWN = -1,
+
+ /** The key is up. */
+ AKEY_STATE_UP = 0,
+
+ /** The key is down. */
+ AKEY_STATE_DOWN = 1,
+
+ /** The key is down but is a virtual key press that is being emulated by the system. */
+ AKEY_STATE_VIRTUAL = 2
+};
+
+/**
+ * Meta key / modifer state.
+ */
+enum {
+ /** No meta keys are pressed. */
+ AMETA_NONE = 0,
+
+ /** This mask is used to check whether one of the ALT meta keys is pressed. */
+ AMETA_ALT_ON = 0x02,
+
+ /** This mask is used to check whether the left ALT meta key is pressed. */
+ AMETA_ALT_LEFT_ON = 0x10,
+
+ /** This mask is used to check whether the right ALT meta key is pressed. */
+ AMETA_ALT_RIGHT_ON = 0x20,
+
+ /** This mask is used to check whether one of the SHIFT meta keys is pressed. */
+ AMETA_SHIFT_ON = 0x01,
+
+ /** This mask is used to check whether the left SHIFT meta key is pressed. */
+ AMETA_SHIFT_LEFT_ON = 0x40,
+
+ /** This mask is used to check whether the right SHIFT meta key is pressed. */
+ AMETA_SHIFT_RIGHT_ON = 0x80,
+
+ /** This mask is used to check whether the SYM meta key is pressed. */
+ AMETA_SYM_ON = 0x04,
+
+ /** This mask is used to check whether the FUNCTION meta key is pressed. */
+ AMETA_FUNCTION_ON = 0x08,
+
+ /** This mask is used to check whether one of the CTRL meta keys is pressed. */
+ AMETA_CTRL_ON = 0x1000,
+
+ /** This mask is used to check whether the left CTRL meta key is pressed. */
+ AMETA_CTRL_LEFT_ON = 0x2000,
+
+ /** This mask is used to check whether the right CTRL meta key is pressed. */
+ AMETA_CTRL_RIGHT_ON = 0x4000,
+
+ /** This mask is used to check whether one of the META meta keys is pressed. */
+ AMETA_META_ON = 0x10000,
+
+ /** This mask is used to check whether the left META meta key is pressed. */
+ AMETA_META_LEFT_ON = 0x20000,
+
+ /** This mask is used to check whether the right META meta key is pressed. */
+ AMETA_META_RIGHT_ON = 0x40000,
+
+ /** This mask is used to check whether the CAPS LOCK meta key is on. */
+ AMETA_CAPS_LOCK_ON = 0x100000,
+
+ /** This mask is used to check whether the NUM LOCK meta key is on. */
+ AMETA_NUM_LOCK_ON = 0x200000,
+
+ /** This mask is used to check whether the SCROLL LOCK meta key is on. */
+ AMETA_SCROLL_LOCK_ON = 0x400000,
+};
+
+struct AInputEvent;
+/**
+ * Input events.
+ *
+ * Input events are opaque structures. Use the provided accessors functions to
+ * read their properties.
+ */
+typedef struct AInputEvent AInputEvent;
+
+/**
+ * Input event types.
+ */
+enum {
+ /** Indicates that the input event is a key event. */
+ AINPUT_EVENT_TYPE_KEY = 1,
+
+ /** Indicates that the input event is a motion event. */
+ AINPUT_EVENT_TYPE_MOTION = 2
+};
+
+/**
+ * Key event actions.
+ */
+enum {
+ /** The key has been pressed down. */
+ AKEY_EVENT_ACTION_DOWN = 0,
+
+ /** The key has been released. */
+ AKEY_EVENT_ACTION_UP = 1,
+
+ /**
+ * Multiple duplicate key events have occurred in a row, or a
+ * complex string is being delivered. The repeat_count property
+ * of the key event contains the number of times the given key
+ * code should be executed.
+ */
+ AKEY_EVENT_ACTION_MULTIPLE = 2
+};
+
+/**
+ * Key event flags.
+ */
+enum {
+ /** This mask is set if the device woke because of this key event. */
+ AKEY_EVENT_FLAG_WOKE_HERE = 0x1,
+
+ /** This mask is set if the key event was generated by a software keyboard. */
+ AKEY_EVENT_FLAG_SOFT_KEYBOARD = 0x2,
+
+ /** This mask is set if we don't want the key event to cause us to leave touch mode. */
+ AKEY_EVENT_FLAG_KEEP_TOUCH_MODE = 0x4,
+
+ /**
+ * This mask is set if an event was known to come from a trusted
+ * part of the system. That is, the event is known to come from
+ * the user, and could not have been spoofed by a third party
+ * component.
+ */
+ AKEY_EVENT_FLAG_FROM_SYSTEM = 0x8,
+
+ /**
+ * This mask is used for compatibility, to identify enter keys that are
+ * coming from an IME whose enter key has been auto-labelled "next" or
+ * "done". This allows TextView to dispatch these as normal enter keys
+ * for old applications, but still do the appropriate action when
+ * receiving them.
+ */
+ AKEY_EVENT_FLAG_EDITOR_ACTION = 0x10,
+
+ /**
+ * When associated with up key events, this indicates that the key press
+ * has been canceled. Typically this is used with virtual touch screen
+ * keys, where the user can slide from the virtual key area on to the
+ * display: in that case, the application will receive a canceled up
+ * event and should not perform the action normally associated with the
+ * key. Note that for this to work, the application can not perform an
+ * action for a key until it receives an up or the long press timeout has
+ * expired.
+ */
+ AKEY_EVENT_FLAG_CANCELED = 0x20,
+
+ /**
+ * This key event was generated by a virtual (on-screen) hard key area.
+ * Typically this is an area of the touchscreen, outside of the regular
+ * display, dedicated to "hardware" buttons.
+ */
+ AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY = 0x40,
+
+ /**
+ * This flag is set for the first key repeat that occurs after the
+ * long press timeout.
+ */
+ AKEY_EVENT_FLAG_LONG_PRESS = 0x80,
+
+ /**
+ * Set when a key event has AKEY_EVENT_FLAG_CANCELED set because a long
+ * press action was executed while it was down.
+ */
+ AKEY_EVENT_FLAG_CANCELED_LONG_PRESS = 0x100,
+
+ /**
+ * Set for AKEY_EVENT_ACTION_UP when this event's key code is still being
+ * tracked from its initial down. That is, somebody requested that tracking
+ * started on the key down and a long press has not caused
+ * the tracking to be canceled.
+ */
+ AKEY_EVENT_FLAG_TRACKING = 0x200,
+
+ /**
+ * Set when a key event has been synthesized to implement default behavior
+ * for an event that the application did not handle.
+ * Fallback key events are generated by unhandled trackball motions
+ * (to emulate a directional keypad) and by certain unhandled key presses
+ * that are declared in the key map (such as special function numeric keypad
+ * keys when numlock is off).
+ */
+ AKEY_EVENT_FLAG_FALLBACK = 0x400,
+};
+
+/**
+ * Bit shift for the action bits holding the pointer index as
+ * defined by AMOTION_EVENT_ACTION_POINTER_INDEX_MASK.
+ */
+#define AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT 8
+
+/** Motion event actions */
+enum {
+ /** Bit mask of the parts of the action code that are the action itself. */
+ AMOTION_EVENT_ACTION_MASK = 0xff,
+
+ /**
+ * Bits in the action code that represent a pointer index, used with
+ * AMOTION_EVENT_ACTION_POINTER_DOWN and AMOTION_EVENT_ACTION_POINTER_UP. Shifting
+ * down by AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT provides the actual pointer
+ * index where the data for the pointer going up or down can be found.
+ */
+ AMOTION_EVENT_ACTION_POINTER_INDEX_MASK = 0xff00,
+
+ /** A pressed gesture has started, the motion contains the initial starting location. */
+ AMOTION_EVENT_ACTION_DOWN = 0,
+
+ /**
+ * A pressed gesture has finished, the motion contains the final release location
+ * as well as any intermediate points since the last down or move event.
+ */
+ AMOTION_EVENT_ACTION_UP = 1,
+
+ /**
+ * A change has happened during a press gesture (between AMOTION_EVENT_ACTION_DOWN and
+ * AMOTION_EVENT_ACTION_UP). The motion contains the most recent point, as well as
+ * any intermediate points since the last down or move event.
+ */
+ AMOTION_EVENT_ACTION_MOVE = 2,
+
+ /**
+ * The current gesture has been aborted.
+ * You will not receive any more points in it. You should treat this as
+ * an up event, but not perform any action that you normally would.
+ */
+ AMOTION_EVENT_ACTION_CANCEL = 3,
+
+ /**
+ * A movement has happened outside of the normal bounds of the UI element.
+ * This does not provide a full gesture, but only the initial location of the movement/touch.
+ */
+ AMOTION_EVENT_ACTION_OUTSIDE = 4,
+
+ /**
+ * A non-primary pointer has gone down.
+ * The bits in AMOTION_EVENT_ACTION_POINTER_INDEX_MASK indicate which pointer changed.
+ */
+ AMOTION_EVENT_ACTION_POINTER_DOWN = 5,
+
+ /**
+ * A non-primary pointer has gone up.
+ * The bits in AMOTION_EVENT_ACTION_POINTER_INDEX_MASK indicate which pointer changed.
+ */
+ AMOTION_EVENT_ACTION_POINTER_UP = 6,
+
+ /**
+ * A change happened but the pointer is not down (unlike AMOTION_EVENT_ACTION_MOVE).
+ * The motion contains the most recent point, as well as any intermediate points since
+ * the last hover move event.
+ */
+ AMOTION_EVENT_ACTION_HOVER_MOVE = 7,
+
+ /**
+ * The motion event contains relative vertical and/or horizontal scroll offsets.
+ * Use getAxisValue to retrieve the information from AMOTION_EVENT_AXIS_VSCROLL
+ * and AMOTION_EVENT_AXIS_HSCROLL.
+ * The pointer may or may not be down when this event is dispatched.
+ * This action is always delivered to the winder under the pointer, which
+ * may not be the window currently touched.
+ */
+ AMOTION_EVENT_ACTION_SCROLL = 8,
+
+ /** The pointer is not down but has entered the boundaries of a window or view. */
+ AMOTION_EVENT_ACTION_HOVER_ENTER = 9,
+
+ /** The pointer is not down but has exited the boundaries of a window or view. */
+ AMOTION_EVENT_ACTION_HOVER_EXIT = 10,
+
+ /* One or more buttons have been pressed. */
+ AMOTION_EVENT_ACTION_BUTTON_PRESS = 11,
+
+ /* One or more buttons have been released. */
+ AMOTION_EVENT_ACTION_BUTTON_RELEASE = 12,
+};
+
+/**
+ * Motion event flags.
+ */
+enum {
+ /**
+ * This flag indicates that the window that received this motion event is partly
+ * or wholly obscured by another visible window above it. This flag is set to true
+ * even if the event did not directly pass through the obscured area.
+ * A security sensitive application can check this flag to identify situations in which
+ * a malicious application may have covered up part of its content for the purpose
+ * of misleading the user or hijacking touches. An appropriate response might be
+ * to drop the suspect touches or to take additional precautions to confirm the user's
+ * actual intent.
+ */
+ AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED = 0x1,
+};
+
+/**
+ * Motion event edge touch flags.
+ */
+enum {
+ /** No edges intersected. */
+ AMOTION_EVENT_EDGE_FLAG_NONE = 0,
+
+ /** Flag indicating the motion event intersected the top edge of the screen. */
+ AMOTION_EVENT_EDGE_FLAG_TOP = 0x01,
+
+ /** Flag indicating the motion event intersected the bottom edge of the screen. */
+ AMOTION_EVENT_EDGE_FLAG_BOTTOM = 0x02,
+
+ /** Flag indicating the motion event intersected the left edge of the screen. */
+ AMOTION_EVENT_EDGE_FLAG_LEFT = 0x04,
+
+ /** Flag indicating the motion event intersected the right edge of the screen. */
+ AMOTION_EVENT_EDGE_FLAG_RIGHT = 0x08
+};
+
+/**
+ * Constants that identify each individual axis of a motion event.
+ * @anchor AMOTION_EVENT_AXIS
+ */
+enum {
+ /**
+ * Axis constant: X axis of a motion event.
+ *
+ * - For a touch screen, reports the absolute X screen position of the center of
+ * the touch contact area. The units are display pixels.
+ * - For a touch pad, reports the absolute X surface position of the center of the touch
+ * contact area. The units are device-dependent.
+ * - For a mouse, reports the absolute X screen position of the mouse pointer.
+ * The units are display pixels.
+ * - For a trackball, reports the relative horizontal displacement of the trackball.
+ * The value is normalized to a range from -1.0 (left) to 1.0 (right).
+ * - For a joystick, reports the absolute X position of the joystick.
+ * The value is normalized to a range from -1.0 (left) to 1.0 (right).
+ */
+ AMOTION_EVENT_AXIS_X = 0,
+ /**
+ * Axis constant: Y axis of a motion event.
+ *
+ * - For a touch screen, reports the absolute Y screen position of the center of
+ * the touch contact area. The units are display pixels.
+ * - For a touch pad, reports the absolute Y surface position of the center of the touch
+ * contact area. The units are device-dependent.
+ * - For a mouse, reports the absolute Y screen position of the mouse pointer.
+ * The units are display pixels.
+ * - For a trackball, reports the relative vertical displacement of the trackball.
+ * The value is normalized to a range from -1.0 (up) to 1.0 (down).
+ * - For a joystick, reports the absolute Y position of the joystick.
+ * The value is normalized to a range from -1.0 (up or far) to 1.0 (down or near).
+ */
+ AMOTION_EVENT_AXIS_Y = 1,
+ /**
+ * Axis constant: Pressure axis of a motion event.
+ *
+ * - For a touch screen or touch pad, reports the approximate pressure applied to the surface
+ * by a finger or other tool. The value is normalized to a range from
+ * 0 (no pressure at all) to 1 (normal pressure), although values higher than 1
+ * may be generated depending on the calibration of the input device.
+ * - For a trackball, the value is set to 1 if the trackball button is pressed
+ * or 0 otherwise.
+ * - For a mouse, the value is set to 1 if the primary mouse button is pressed
+ * or 0 otherwise.
+ */
+ AMOTION_EVENT_AXIS_PRESSURE = 2,
+ /**
+ * Axis constant: Size axis of a motion event.
+ *
+ * - For a touch screen or touch pad, reports the approximate size of the contact area in
+ * relation to the maximum detectable size for the device. The value is normalized
+ * to a range from 0 (smallest detectable size) to 1 (largest detectable size),
+ * although it is not a linear scale. This value is of limited use.
+ * To obtain calibrated size information, see
+ * {@link AMOTION_EVENT_AXIS_TOUCH_MAJOR} or {@link AMOTION_EVENT_AXIS_TOOL_MAJOR}.
+ */
+ AMOTION_EVENT_AXIS_SIZE = 3,
+ /**
+ * Axis constant: TouchMajor axis of a motion event.
+ *
+ * - For a touch screen, reports the length of the major axis of an ellipse that
+ * represents the touch area at the point of contact.
+ * The units are display pixels.
+ * - For a touch pad, reports the length of the major axis of an ellipse that
+ * represents the touch area at the point of contact.
+ * The units are device-dependent.
+ */
+ AMOTION_EVENT_AXIS_TOUCH_MAJOR = 4,
+ /**
+ * Axis constant: TouchMinor axis of a motion event.
+ *
+ * - For a touch screen, reports the length of the minor axis of an ellipse that
+ * represents the touch area at the point of contact.
+ * The units are display pixels.
+ * - For a touch pad, reports the length of the minor axis of an ellipse that
+ * represents the touch area at the point of contact.
+ * The units are device-dependent.
+ *
+ * When the touch is circular, the major and minor axis lengths will be equal to one another.
+ */
+ AMOTION_EVENT_AXIS_TOUCH_MINOR = 5,
+ /**
+ * Axis constant: ToolMajor axis of a motion event.
+ *
+ * - For a touch screen, reports the length of the major axis of an ellipse that
+ * represents the size of the approaching finger or tool used to make contact.
+ * - For a touch pad, reports the length of the major axis of an ellipse that
+ * represents the size of the approaching finger or tool used to make contact.
+ * The units are device-dependent.
+ *
+ * When the touch is circular, the major and minor axis lengths will be equal to one another.
+ *
+ * The tool size may be larger than the touch size since the tool may not be fully
+ * in contact with the touch sensor.
+ */
+ AMOTION_EVENT_AXIS_TOOL_MAJOR = 6,
+ /**
+ * Axis constant: ToolMinor axis of a motion event.
+ *
+ * - For a touch screen, reports the length of the minor axis of an ellipse that
+ * represents the size of the approaching finger or tool used to make contact.
+ * - For a touch pad, reports the length of the minor axis of an ellipse that
+ * represents the size of the approaching finger or tool used to make contact.
+ * The units are device-dependent.
+ *
+ * When the touch is circular, the major and minor axis lengths will be equal to one another.
+ *
+ * The tool size may be larger than the touch size since the tool may not be fully
+ * in contact with the touch sensor.
+ */
+ AMOTION_EVENT_AXIS_TOOL_MINOR = 7,
+ /**
+ * Axis constant: Orientation axis of a motion event.
+ *
+ * - For a touch screen or touch pad, reports the orientation of the finger
+ * or tool in radians relative to the vertical plane of the device.
+ * An angle of 0 radians indicates that the major axis of contact is oriented
+ * upwards, is perfectly circular or is of unknown orientation. A positive angle
+ * indicates that the major axis of contact is oriented to the right. A negative angle
+ * indicates that the major axis of contact is oriented to the left.
+ * The full range is from -PI/2 radians (finger pointing fully left) to PI/2 radians
+ * (finger pointing fully right).
+ * - For a stylus, the orientation indicates the direction in which the stylus
+ * is pointing in relation to the vertical axis of the current orientation of the screen.
+ * The range is from -PI radians to PI radians, where 0 is pointing up,
+ * -PI/2 radians is pointing left, -PI or PI radians is pointing down, and PI/2 radians
+ * is pointing right. See also {@link AMOTION_EVENT_AXIS_TILT}.
+ */
+ AMOTION_EVENT_AXIS_ORIENTATION = 8,
+ /**
+ * Axis constant: Vertical Scroll axis of a motion event.
+ *
+ * - For a mouse, reports the relative movement of the vertical scroll wheel.
+ * The value is normalized to a range from -1.0 (down) to 1.0 (up).
+ *
+ * This axis should be used to scroll views vertically.
+ */
+ AMOTION_EVENT_AXIS_VSCROLL = 9,
+ /**
+ * Axis constant: Horizontal Scroll axis of a motion event.
+ *
+ * - For a mouse, reports the relative movement of the horizontal scroll wheel.
+ * The value is normalized to a range from -1.0 (left) to 1.0 (right).
+ *
+ * This axis should be used to scroll views horizontally.
+ */
+ AMOTION_EVENT_AXIS_HSCROLL = 10,
+ /**
+ * Axis constant: Z axis of a motion event.
+ *
+ * - For a joystick, reports the absolute Z position of the joystick.
+ * The value is normalized to a range from -1.0 (high) to 1.0 (low).
+ * On game pads with two analog joysticks, this axis is often reinterpreted
+ * to report the absolute X position of the second joystick instead.
+ */
+ AMOTION_EVENT_AXIS_Z = 11,
+ /**
+ * Axis constant: X Rotation axis of a motion event.
+ *
+ * - For a joystick, reports the absolute rotation angle about the X axis.
+ * The value is normalized to a range from -1.0 (counter-clockwise) to 1.0 (clockwise).
+ */
+ AMOTION_EVENT_AXIS_RX = 12,
+ /**
+ * Axis constant: Y Rotation axis of a motion event.
+ *
+ * - For a joystick, reports the absolute rotation angle about the Y axis.
+ * The value is normalized to a range from -1.0 (counter-clockwise) to 1.0 (clockwise).
+ */
+ AMOTION_EVENT_AXIS_RY = 13,
+ /**
+ * Axis constant: Z Rotation axis of a motion event.
+ *
+ * - For a joystick, reports the absolute rotation angle about the Z axis.
+ * The value is normalized to a range from -1.0 (counter-clockwise) to 1.0 (clockwise).
+ * On game pads with two analog joysticks, this axis is often reinterpreted
+ * to report the absolute Y position of the second joystick instead.
+ */
+ AMOTION_EVENT_AXIS_RZ = 14,
+ /**
+ * Axis constant: Hat X axis of a motion event.
+ *
+ * - For a joystick, reports the absolute X position of the directional hat control.
+ * The value is normalized to a range from -1.0 (left) to 1.0 (right).
+ */
+ AMOTION_EVENT_AXIS_HAT_X = 15,
+ /**
+ * Axis constant: Hat Y axis of a motion event.
+ *
+ * - For a joystick, reports the absolute Y position of the directional hat control.
+ * The value is normalized to a range from -1.0 (up) to 1.0 (down).
+ */
+ AMOTION_EVENT_AXIS_HAT_Y = 16,
+ /**
+ * Axis constant: Left Trigger axis of a motion event.
+ *
+ * - For a joystick, reports the absolute position of the left trigger control.
+ * The value is normalized to a range from 0.0 (released) to 1.0 (fully pressed).
+ */
+ AMOTION_EVENT_AXIS_LTRIGGER = 17,
+ /**
+ * Axis constant: Right Trigger axis of a motion event.
+ *
+ * - For a joystick, reports the absolute position of the right trigger control.
+ * The value is normalized to a range from 0.0 (released) to 1.0 (fully pressed).
+ */
+ AMOTION_EVENT_AXIS_RTRIGGER = 18,
+ /**
+ * Axis constant: Throttle axis of a motion event.
+ *
+ * - For a joystick, reports the absolute position of the throttle control.
+ * The value is normalized to a range from 0.0 (fully open) to 1.0 (fully closed).
+ */
+ AMOTION_EVENT_AXIS_THROTTLE = 19,
+ /**
+ * Axis constant: Rudder axis of a motion event.
+ *
+ * - For a joystick, reports the absolute position of the rudder control.
+ * The value is normalized to a range from -1.0 (turn left) to 1.0 (turn right).
+ */
+ AMOTION_EVENT_AXIS_RUDDER = 20,
+ /**
+ * Axis constant: Wheel axis of a motion event.
+ *
+ * - For a joystick, reports the absolute position of the steering wheel control.
+ * The value is normalized to a range from -1.0 (turn left) to 1.0 (turn right).
+ */
+ AMOTION_EVENT_AXIS_WHEEL = 21,
+ /**
+ * Axis constant: Gas axis of a motion event.
+ *
+ * - For a joystick, reports the absolute position of the gas (accelerator) control.
+ * The value is normalized to a range from 0.0 (no acceleration)
+ * to 1.0 (maximum acceleration).
+ */
+ AMOTION_EVENT_AXIS_GAS = 22,
+ /**
+ * Axis constant: Brake axis of a motion event.
+ *
+ * - For a joystick, reports the absolute position of the brake control.
+ * The value is normalized to a range from 0.0 (no braking) to 1.0 (maximum braking).
+ */
+ AMOTION_EVENT_AXIS_BRAKE = 23,
+ /**
+ * Axis constant: Distance axis of a motion event.
+ *
+ * - For a stylus, reports the distance of the stylus from the screen.
+ * A value of 0.0 indicates direct contact and larger values indicate increasing
+ * distance from the surface.
+ */
+ AMOTION_EVENT_AXIS_DISTANCE = 24,
+ /**
+ * Axis constant: Tilt axis of a motion event.
+ *
+ * - For a stylus, reports the tilt angle of the stylus in radians where
+ * 0 radians indicates that the stylus is being held perpendicular to the
+ * surface, and PI/2 radians indicates that the stylus is being held flat
+ * against the surface.
+ */
+ AMOTION_EVENT_AXIS_TILT = 25,
+ /**
+ * Axis constant: Generic 1 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ AMOTION_EVENT_AXIS_GENERIC_1 = 32,
+ /**
+ * Axis constant: Generic 2 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ AMOTION_EVENT_AXIS_GENERIC_2 = 33,
+ /**
+ * Axis constant: Generic 3 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ AMOTION_EVENT_AXIS_GENERIC_3 = 34,
+ /**
+ * Axis constant: Generic 4 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ AMOTION_EVENT_AXIS_GENERIC_4 = 35,
+ /**
+ * Axis constant: Generic 5 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ AMOTION_EVENT_AXIS_GENERIC_5 = 36,
+ /**
+ * Axis constant: Generic 6 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ AMOTION_EVENT_AXIS_GENERIC_6 = 37,
+ /**
+ * Axis constant: Generic 7 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ AMOTION_EVENT_AXIS_GENERIC_7 = 38,
+ /**
+ * Axis constant: Generic 8 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ AMOTION_EVENT_AXIS_GENERIC_8 = 39,
+ /**
+ * Axis constant: Generic 9 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ AMOTION_EVENT_AXIS_GENERIC_9 = 40,
+ /**
+ * Axis constant: Generic 10 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ AMOTION_EVENT_AXIS_GENERIC_10 = 41,
+ /**
+ * Axis constant: Generic 11 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ AMOTION_EVENT_AXIS_GENERIC_11 = 42,
+ /**
+ * Axis constant: Generic 12 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ AMOTION_EVENT_AXIS_GENERIC_12 = 43,
+ /**
+ * Axis constant: Generic 13 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ AMOTION_EVENT_AXIS_GENERIC_13 = 44,
+ /**
+ * Axis constant: Generic 14 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ AMOTION_EVENT_AXIS_GENERIC_14 = 45,
+ /**
+ * Axis constant: Generic 15 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ AMOTION_EVENT_AXIS_GENERIC_15 = 46,
+ /**
+ * Axis constant: Generic 16 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
+ AMOTION_EVENT_AXIS_GENERIC_16 = 47,
+
+ // NOTE: If you add a new axis here you must also add it to several other files.
+ // Refer to frameworks/base/core/java/android/view/MotionEvent.java for the full list.
+};
+
+/**
+ * Constants that identify buttons that are associated with motion events.
+ * Refer to the documentation on the MotionEvent class for descriptions of each button.
+ */
+enum {
+ /** primary */
+ AMOTION_EVENT_BUTTON_PRIMARY = 1 << 0,
+ /** secondary */
+ AMOTION_EVENT_BUTTON_SECONDARY = 1 << 1,
+ /** tertiary */
+ AMOTION_EVENT_BUTTON_TERTIARY = 1 << 2,
+ /** back */
+ AMOTION_EVENT_BUTTON_BACK = 1 << 3,
+ /** forward */
+ AMOTION_EVENT_BUTTON_FORWARD = 1 << 4,
+ AMOTION_EVENT_BUTTON_STYLUS_PRIMARY = 1 << 5,
+ AMOTION_EVENT_BUTTON_STYLUS_SECONDARY = 1 << 6,
+};
+
+/**
+ * Constants that identify tool types.
+ * Refer to the documentation on the MotionEvent class for descriptions of each tool type.
+ */
+enum {
+ /** unknown */
+ AMOTION_EVENT_TOOL_TYPE_UNKNOWN = 0,
+ /** finger */
+ AMOTION_EVENT_TOOL_TYPE_FINGER = 1,
+ /** stylus */
+ AMOTION_EVENT_TOOL_TYPE_STYLUS = 2,
+ /** mouse */
+ AMOTION_EVENT_TOOL_TYPE_MOUSE = 3,
+ /** eraser */
+ AMOTION_EVENT_TOOL_TYPE_ERASER = 4,
+};
+
+/**
+ * Input source masks.
+ *
+ * Refer to the documentation on android.view.InputDevice for more details about input sources
+ * and their correct interpretation.
+ */
+enum {
+ /** mask */
+ AINPUT_SOURCE_CLASS_MASK = 0x000000ff,
+
+ /** none */
+ AINPUT_SOURCE_CLASS_NONE = 0x00000000,
+ /** button */
+ AINPUT_SOURCE_CLASS_BUTTON = 0x00000001,
+ /** pointer */
+ AINPUT_SOURCE_CLASS_POINTER = 0x00000002,
+ /** navigation */
+ AINPUT_SOURCE_CLASS_NAVIGATION = 0x00000004,
+ /** position */
+ AINPUT_SOURCE_CLASS_POSITION = 0x00000008,
+ /** joystick */
+ AINPUT_SOURCE_CLASS_JOYSTICK = 0x00000010,
+};
+
+/**
+ * Input sources.
+ */
+enum {
+ /** unknown */
+ AINPUT_SOURCE_UNKNOWN = 0x00000000,
+
+ /** keyboard */
+ AINPUT_SOURCE_KEYBOARD = 0x00000100 | AINPUT_SOURCE_CLASS_BUTTON,
+ /** dpad */
+ AINPUT_SOURCE_DPAD = 0x00000200 | AINPUT_SOURCE_CLASS_BUTTON,
+ /** gamepad */
+ AINPUT_SOURCE_GAMEPAD = 0x00000400 | AINPUT_SOURCE_CLASS_BUTTON,
+ /** touchscreen */
+ AINPUT_SOURCE_TOUCHSCREEN = 0x00001000 | AINPUT_SOURCE_CLASS_POINTER,
+ /** mouse */
+ AINPUT_SOURCE_MOUSE = 0x00002000 | AINPUT_SOURCE_CLASS_POINTER,
+ /** stylus */
+ AINPUT_SOURCE_STYLUS = 0x00004000 | AINPUT_SOURCE_CLASS_POINTER,
+ /** bluetooth stylus */
+ AINPUT_SOURCE_BLUETOOTH_STYLUS = 0x00008000 | AINPUT_SOURCE_STYLUS,
+ /** trackball */
+ AINPUT_SOURCE_TRACKBALL = 0x00010000 | AINPUT_SOURCE_CLASS_NAVIGATION,
+ /** touchpad */
+ AINPUT_SOURCE_TOUCHPAD = 0x00100000 | AINPUT_SOURCE_CLASS_POSITION,
+ /** navigation */
+ AINPUT_SOURCE_TOUCH_NAVIGATION = 0x00200000 | AINPUT_SOURCE_CLASS_NONE,
+ /** gesture sensor (?) */
+ AINPUT_SOURCE_GESTURE_SENSOR = 0x00400000 | AINPUT_SOURCE_CLASS_NONE,
+ /** joystick */
+ AINPUT_SOURCE_JOYSTICK = 0x01000000 | AINPUT_SOURCE_CLASS_JOYSTICK,
+
+ /** any */
+ AINPUT_SOURCE_ANY = 0xffffff00,
+};
+
+/**
+ * Keyboard types.
+ *
+ * Refer to the documentation on android.view.InputDevice for more details.
+ */
+enum {
+ /** none */
+ AINPUT_KEYBOARD_TYPE_NONE = 0,
+ /** non alphabetic */
+ AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC = 1,
+ /** alphabetic */
+ AINPUT_KEYBOARD_TYPE_ALPHABETIC = 2,
+};
+
+/**
+ * Constants used to retrieve information about the range of motion for a particular
+ * coordinate of a motion event.
+ *
+ * Refer to the documentation on android.view.InputDevice for more details about input sources
+ * and their correct interpretation.
+ *
+ * @deprecated These constants are deprecated. Use {@link AMOTION_EVENT_AXIS AMOTION_EVENT_AXIS_*} constants instead.
+ */
+enum {
+ /** x */
+ AINPUT_MOTION_RANGE_X = AMOTION_EVENT_AXIS_X,
+ /** y */
+ AINPUT_MOTION_RANGE_Y = AMOTION_EVENT_AXIS_Y,
+ /** pressure */
+ AINPUT_MOTION_RANGE_PRESSURE = AMOTION_EVENT_AXIS_PRESSURE,
+ /** size */
+ AINPUT_MOTION_RANGE_SIZE = AMOTION_EVENT_AXIS_SIZE,
+ /** touch major */
+ AINPUT_MOTION_RANGE_TOUCH_MAJOR = AMOTION_EVENT_AXIS_TOUCH_MAJOR,
+ /** touch minor */
+ AINPUT_MOTION_RANGE_TOUCH_MINOR = AMOTION_EVENT_AXIS_TOUCH_MINOR,
+ /** tool major */
+ AINPUT_MOTION_RANGE_TOOL_MAJOR = AMOTION_EVENT_AXIS_TOOL_MAJOR,
+ /** tool minor */
+ AINPUT_MOTION_RANGE_TOOL_MINOR = AMOTION_EVENT_AXIS_TOOL_MINOR,
+ /** orientation */
+ AINPUT_MOTION_RANGE_ORIENTATION = AMOTION_EVENT_AXIS_ORIENTATION,
+};
+
+
+/**
+ * Input event accessors.
+ *
+ * Note that most functions can only be used on input events that are of a given type.
+ * Calling these functions on input events of other types will yield undefined behavior.
+ */
+
+/*** Accessors for all input events. ***/
+
+/** Get the input event type. */
+int32_t AInputEvent_getType(const AInputEvent* event);
+
+/** Get the id for the device that an input event came from.
+ *
+ * Input events can be generated by multiple different input devices.
+ * Use the input device id to obtain information about the input
+ * device that was responsible for generating a particular event.
+ *
+ * An input device id of 0 indicates that the event didn't come from a physical device;
+ * other numbers are arbitrary and you shouldn't depend on the values.
+ * Use the provided input device query API to obtain information about input devices.
+ */
+int32_t AInputEvent_getDeviceId(const AInputEvent* event);
+
+/** Get the input event source. */
+int32_t AInputEvent_getSource(const AInputEvent* event);
+
+/*** Accessors for key events only. ***/
+
+/** Get the key event action. */
+int32_t AKeyEvent_getAction(const AInputEvent* key_event);
+
+/** Get the key event flags. */
+int32_t AKeyEvent_getFlags(const AInputEvent* key_event);
+
+/**
+ * Get the key code of the key event.
+ * This is the physical key that was pressed, not the Unicode character.
+ */
+int32_t AKeyEvent_getKeyCode(const AInputEvent* key_event);
+
+/**
+ * Get the hardware key id of this key event.
+ * These values are not reliable and vary from device to device.
+ */
+int32_t AKeyEvent_getScanCode(const AInputEvent* key_event);
+
+/** Get the meta key state. */
+int32_t AKeyEvent_getMetaState(const AInputEvent* key_event);
+
+/**
+ * Get the repeat count of the event.
+ * For both key up an key down events, this is the number of times the key has
+ * repeated with the first down starting at 0 and counting up from there. For
+ * multiple key events, this is the number of down/up pairs that have occurred.
+ */
+int32_t AKeyEvent_getRepeatCount(const AInputEvent* key_event);
+
+/**
+ * Get the time of the most recent key down event, in the
+ * java.lang.System.nanoTime() time base. If this is a down event,
+ * this will be the same as eventTime.
+ * Note that when chording keys, this value is the down time of the most recently
+ * pressed key, which may not be the same physical key of this event.
+ */
+int64_t AKeyEvent_getDownTime(const AInputEvent* key_event);
+
+/**
+ * Get the time this event occurred, in the
+ * java.lang.System.nanoTime() time base.
+ */
+int64_t AKeyEvent_getEventTime(const AInputEvent* key_event);
+
+/*** Accessors for motion events only. ***/
+
+/** Get the combined motion event action code and pointer index. */
+int32_t AMotionEvent_getAction(const AInputEvent* motion_event);
+
+/** Get the motion event flags. */
+int32_t AMotionEvent_getFlags(const AInputEvent* motion_event);
+
+/**
+ * Get the state of any meta / modifier keys that were in effect when the
+ * event was generated.
+ */
+int32_t AMotionEvent_getMetaState(const AInputEvent* motion_event);
+
+/** Get the button state of all buttons that are pressed. */
+int32_t AMotionEvent_getButtonState(const AInputEvent* motion_event);
+
+/**
+ * Get a bitfield indicating which edges, if any, were touched by this motion event.
+ * For touch events, clients can use this to determine if the user's finger was
+ * touching the edge of the display.
+ */
+int32_t AMotionEvent_getEdgeFlags(const AInputEvent* motion_event);
+
+/**
+ * Get the time when the user originally pressed down to start a stream of
+ * position events, in the java.lang.System.nanoTime() time base.
+ */
+int64_t AMotionEvent_getDownTime(const AInputEvent* motion_event);
+
+/**
+ * Get the time when this specific event was generated,
+ * in the java.lang.System.nanoTime() time base.
+ */
+int64_t AMotionEvent_getEventTime(const AInputEvent* motion_event);
+
+/**
+ * Get the X coordinate offset.
+ * For touch events on the screen, this is the delta that was added to the raw
+ * screen coordinates to adjust for the absolute position of the containing windows
+ * and views.
+ */
+float AMotionEvent_getXOffset(const AInputEvent* motion_event);
+
+/**
+ * Get the Y coordinate offset.
+ * For touch events on the screen, this is the delta that was added to the raw
+ * screen coordinates to adjust for the absolute position of the containing windows
+ * and views.
+ */
+float AMotionEvent_getYOffset(const AInputEvent* motion_event);
+
+/**
+ * Get the precision of the X coordinates being reported.
+ * You can multiply this number with an X coordinate sample to find the
+ * actual hardware value of the X coordinate.
+ */
+float AMotionEvent_getXPrecision(const AInputEvent* motion_event);
+
+/**
+ * Get the precision of the Y coordinates being reported.
+ * You can multiply this number with a Y coordinate sample to find the
+ * actual hardware value of the Y coordinate.
+ */
+float AMotionEvent_getYPrecision(const AInputEvent* motion_event);
+
+/**
+ * Get the number of pointers of data contained in this event.
+ * Always >= 1.
+ */
+size_t AMotionEvent_getPointerCount(const AInputEvent* motion_event);
+
+/**
+ * Get the pointer identifier associated with a particular pointer
+ * data index in this event. The identifier tells you the actual pointer
+ * number associated with the data, accounting for individual pointers
+ * going up and down since the start of the current gesture.
+ */
+int32_t AMotionEvent_getPointerId(const AInputEvent* motion_event, size_t pointer_index);
+
+/**
+ * Get the tool type of a pointer for the given pointer index.
+ * The tool type indicates the type of tool used to make contact such as a
+ * finger or stylus, if known.
+ */
+int32_t AMotionEvent_getToolType(const AInputEvent* motion_event, size_t pointer_index);
+
+/**
+ * Get the original raw X coordinate of this event.
+ * For touch events on the screen, this is the original location of the event
+ * on the screen, before it had been adjusted for the containing window
+ * and views.
+ */
+float AMotionEvent_getRawX(const AInputEvent* motion_event, size_t pointer_index);
+
+/**
+ * Get the original raw X coordinate of this event.
+ * For touch events on the screen, this is the original location of the event
+ * on the screen, before it had been adjusted for the containing window
+ * and views.
+ */
+float AMotionEvent_getRawY(const AInputEvent* motion_event, size_t pointer_index);
+
+/**
+ * Get the current X coordinate of this event for the given pointer index.
+ * Whole numbers are pixels; the value may have a fraction for input devices
+ * that are sub-pixel precise.
+ */
+float AMotionEvent_getX(const AInputEvent* motion_event, size_t pointer_index);
+
+/**
+ * Get the current Y coordinate of this event for the given pointer index.
+ * Whole numbers are pixels; the value may have a fraction for input devices
+ * that are sub-pixel precise.
+ */
+float AMotionEvent_getY(const AInputEvent* motion_event, size_t pointer_index);
+
+/**
+ * Get the current pressure of this event for the given pointer index.
+ * The pressure generally ranges from 0 (no pressure at all) to 1 (normal pressure),
+ * although values higher than 1 may be generated depending on the calibration of
+ * the input device.
+ */
+float AMotionEvent_getPressure(const AInputEvent* motion_event, size_t pointer_index);
+
+/**
+ * Get the current scaled value of the approximate size for the given pointer index.
+ * This represents some approximation of the area of the screen being
+ * pressed; the actual value in pixels corresponding to the
+ * touch is normalized with the device specific range of values
+ * and scaled to a value between 0 and 1. The value of size can be used to
+ * determine fat touch events.
+ */
+float AMotionEvent_getSize(const AInputEvent* motion_event, size_t pointer_index);
+
+/**
+ * Get the current length of the major axis of an ellipse that describes the touch area
+ * at the point of contact for the given pointer index.
+ */
+float AMotionEvent_getTouchMajor(const AInputEvent* motion_event, size_t pointer_index);
+
+/**
+ * Get the current length of the minor axis of an ellipse that describes the touch area
+ * at the point of contact for the given pointer index.
+ */
+float AMotionEvent_getTouchMinor(const AInputEvent* motion_event, size_t pointer_index);
+
+/**
+ * Get the current length of the major axis of an ellipse that describes the size
+ * of the approaching tool for the given pointer index.
+ * The tool area represents the estimated size of the finger or pen that is
+ * touching the device independent of its actual touch area at the point of contact.
+ */
+float AMotionEvent_getToolMajor(const AInputEvent* motion_event, size_t pointer_index);
+
+/**
+ * Get the current length of the minor axis of an ellipse that describes the size
+ * of the approaching tool for the given pointer index.
+ * The tool area represents the estimated size of the finger or pen that is
+ * touching the device independent of its actual touch area at the point of contact.
+ */
+float AMotionEvent_getToolMinor(const AInputEvent* motion_event, size_t pointer_index);
+
+/**
+ * Get the current orientation of the touch area and tool area in radians clockwise from
+ * vertical for the given pointer index.
+ * An angle of 0 degrees indicates that the major axis of contact is oriented
+ * upwards, is perfectly circular or is of unknown orientation. A positive angle
+ * indicates that the major axis of contact is oriented to the right. A negative angle
+ * indicates that the major axis of contact is oriented to the left.
+ * The full range is from -PI/2 radians (finger pointing fully left) to PI/2 radians
+ * (finger pointing fully right).
+ */
+float AMotionEvent_getOrientation(const AInputEvent* motion_event, size_t pointer_index);
+
+/** Get the value of the request axis for the given pointer index. */
+float AMotionEvent_getAxisValue(const AInputEvent* motion_event,
+ int32_t axis, size_t pointer_index);
+
+/**
+ * Get the number of historical points in this event. These are movements that
+ * have occurred between this event and the previous event. This only applies
+ * to AMOTION_EVENT_ACTION_MOVE events -- all other actions will have a size of 0.
+ * Historical samples are indexed from oldest to newest.
+ */
+size_t AMotionEvent_getHistorySize(const AInputEvent* motion_event);
+
+/**
+ * Get the time that a historical movement occurred between this event and
+ * the previous event, in the java.lang.System.nanoTime() time base.
+ */
+int64_t AMotionEvent_getHistoricalEventTime(const AInputEvent* motion_event,
+ size_t history_index);
+
+/**
+ * Get the historical raw X coordinate of this event for the given pointer index that
+ * occurred between this event and the previous motion event.
+ * For touch events on the screen, this is the original location of the event
+ * on the screen, before it had been adjusted for the containing window
+ * and views.
+ * Whole numbers are pixels; the value may have a fraction for input devices
+ * that are sub-pixel precise.
+ */
+float AMotionEvent_getHistoricalRawX(const AInputEvent* motion_event, size_t pointer_index,
+ size_t history_index);
+
+/**
+ * Get the historical raw Y coordinate of this event for the given pointer index that
+ * occurred between this event and the previous motion event.
+ * For touch events on the screen, this is the original location of the event
+ * on the screen, before it had been adjusted for the containing window
+ * and views.
+ * Whole numbers are pixels; the value may have a fraction for input devices
+ * that are sub-pixel precise.
+ */
+float AMotionEvent_getHistoricalRawY(const AInputEvent* motion_event, size_t pointer_index,
+ size_t history_index);
+
+/**
+ * Get the historical X coordinate of this event for the given pointer index that
+ * occurred between this event and the previous motion event.
+ * Whole numbers are pixels; the value may have a fraction for input devices
+ * that are sub-pixel precise.
+ */
+float AMotionEvent_getHistoricalX(const AInputEvent* motion_event, size_t pointer_index,
+ size_t history_index);
+
+/**
+ * Get the historical Y coordinate of this event for the given pointer index that
+ * occurred between this event and the previous motion event.
+ * Whole numbers are pixels; the value may have a fraction for input devices
+ * that are sub-pixel precise.
+ */
+float AMotionEvent_getHistoricalY(const AInputEvent* motion_event, size_t pointer_index,
+ size_t history_index);
+
+/**
+ * Get the historical pressure of this event for the given pointer index that
+ * occurred between this event and the previous motion event.
+ * The pressure generally ranges from 0 (no pressure at all) to 1 (normal pressure),
+ * although values higher than 1 may be generated depending on the calibration of
+ * the input device.
+ */
+float AMotionEvent_getHistoricalPressure(const AInputEvent* motion_event, size_t pointer_index,
+ size_t history_index);
+
+/**
+ * Get the current scaled value of the approximate size for the given pointer index that
+ * occurred between this event and the previous motion event.
+ * This represents some approximation of the area of the screen being
+ * pressed; the actual value in pixels corresponding to the
+ * touch is normalized with the device specific range of values
+ * and scaled to a value between 0 and 1. The value of size can be used to
+ * determine fat touch events.
+ */
+float AMotionEvent_getHistoricalSize(const AInputEvent* motion_event, size_t pointer_index,
+ size_t history_index);
+
+/**
+ * Get the historical length of the major axis of an ellipse that describes the touch area
+ * at the point of contact for the given pointer index that
+ * occurred between this event and the previous motion event.
+ */
+float AMotionEvent_getHistoricalTouchMajor(const AInputEvent* motion_event, size_t pointer_index,
+ size_t history_index);
+
+/**
+ * Get the historical length of the minor axis of an ellipse that describes the touch area
+ * at the point of contact for the given pointer index that
+ * occurred between this event and the previous motion event.
+ */
+float AMotionEvent_getHistoricalTouchMinor(const AInputEvent* motion_event, size_t pointer_index,
+ size_t history_index);
+
+/**
+ * Get the historical length of the major axis of an ellipse that describes the size
+ * of the approaching tool for the given pointer index that
+ * occurred between this event and the previous motion event.
+ * The tool area represents the estimated size of the finger or pen that is
+ * touching the device independent of its actual touch area at the point of contact.
+ */
+float AMotionEvent_getHistoricalToolMajor(const AInputEvent* motion_event, size_t pointer_index,
+ size_t history_index);
+
+/**
+ * Get the historical length of the minor axis of an ellipse that describes the size
+ * of the approaching tool for the given pointer index that
+ * occurred between this event and the previous motion event.
+ * The tool area represents the estimated size of the finger or pen that is
+ * touching the device independent of its actual touch area at the point of contact.
+ */
+float AMotionEvent_getHistoricalToolMinor(const AInputEvent* motion_event, size_t pointer_index,
+ size_t history_index);
+
+/**
+ * Get the historical orientation of the touch area and tool area in radians clockwise from
+ * vertical for the given pointer index that
+ * occurred between this event and the previous motion event.
+ * An angle of 0 degrees indicates that the major axis of contact is oriented
+ * upwards, is perfectly circular or is of unknown orientation. A positive angle
+ * indicates that the major axis of contact is oriented to the right. A negative angle
+ * indicates that the major axis of contact is oriented to the left.
+ * The full range is from -PI/2 radians (finger pointing fully left) to PI/2 radians
+ * (finger pointing fully right).
+ */
+float AMotionEvent_getHistoricalOrientation(const AInputEvent* motion_event, size_t pointer_index,
+ size_t history_index);
+
+/**
+ * Get the historical value of the request axis for the given pointer index
+ * that occurred between this event and the previous motion event.
+ */
+float AMotionEvent_getHistoricalAxisValue(const AInputEvent* motion_event,
+ int32_t axis, size_t pointer_index, size_t history_index);
+
+
+struct AInputQueue;
+/**
+ * Input queue
+ *
+ * An input queue is the facility through which you retrieve input
+ * events.
+ */
+typedef struct AInputQueue AInputQueue;
+
+/**
+ * Add this input queue to a looper for processing. See
+ * ALooper_addFd() for information on the ident, callback, and data params.
+ */
+void AInputQueue_attachLooper(AInputQueue* queue, ALooper* looper,
+ int ident, ALooper_callbackFunc callback, void* data);
+
+/**
+ * Remove the input queue from the looper it is currently attached to.
+ */
+void AInputQueue_detachLooper(AInputQueue* queue);
+
+/**
+ * Returns true if there are one or more events available in the
+ * input queue. Returns 1 if the queue has events; 0 if
+ * it does not have events; and a negative value if there is an error.
+ */
+int32_t AInputQueue_hasEvents(AInputQueue* queue);
+
+/**
+ * Returns the next available event from the queue. Returns a negative
+ * value if no events are available or an error has occurred.
+ */
+int32_t AInputQueue_getEvent(AInputQueue* queue, AInputEvent** outEvent);
+
+/**
+ * Sends the key for standard pre-dispatching -- that is, possibly deliver
+ * it to the current IME to be consumed before the app. Returns 0 if it
+ * was not pre-dispatched, meaning you can process it right now. If non-zero
+ * is returned, you must abandon the current event processing and allow the
+ * event to appear again in the event queue (if it does not get consumed during
+ * pre-dispatching).
+ */
+int32_t AInputQueue_preDispatchEvent(AInputQueue* queue, AInputEvent* event);
+
+/**
+ * Report that dispatching has finished with the given event.
+ * This must be called after receiving an event with AInputQueue_get_event().
+ */
+void AInputQueue_finishEvent(AInputQueue* queue, AInputEvent* event, int handled);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _ANDROID_INPUT_H
+
+/** @} */
diff --git a/phonelibs/android_frameworks_native/include/android/keycodes.h b/phonelibs/android_frameworks_native/include/android/keycodes.h
new file mode 100644
index 000000000..421abe547
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/android/keycodes.h
@@ -0,0 +1,752 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ */
+
+/**
+ * @addtogroup Input
+ * @{
+ */
+
+/**
+ * @file keycodes.h
+ */
+
+#ifndef _ANDROID_KEYCODES_H
+#define _ANDROID_KEYCODES_H
+
+/******************************************************************
+ *
+ * IMPORTANT NOTICE:
+ *
+ * This file is part of Android's set of stable system headers
+ * exposed by the Android NDK (Native Development Kit).
+ *
+ * Third-party source AND binary code relies on the definitions
+ * here to be FROZEN ON ALL UPCOMING PLATFORM RELEASES.
+ *
+ * - DO NOT MODIFY ENUMS (EXCEPT IF YOU ADD NEW 32-BIT VALUES)
+ * - DO NOT MODIFY CONSTANTS OR FUNCTIONAL MACROS
+ * - DO NOT CHANGE THE SIGNATURE OF FUNCTIONS IN ANY WAY
+ * - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES
+ */
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Key codes.
+ */
+enum {
+ /** Unknown key code. */
+ AKEYCODE_UNKNOWN = 0,
+ /** Soft Left key.
+ * Usually situated below the display on phones and used as a multi-function
+ * feature key for selecting a software defined function shown on the bottom left
+ * of the display. */
+ AKEYCODE_SOFT_LEFT = 1,
+ /** Soft Right key.
+ * Usually situated below the display on phones and used as a multi-function
+ * feature key for selecting a software defined function shown on the bottom right
+ * of the display. */
+ AKEYCODE_SOFT_RIGHT = 2,
+ /** Home key.
+ * This key is handled by the framework and is never delivered to applications. */
+ AKEYCODE_HOME = 3,
+ /** Back key. */
+ AKEYCODE_BACK = 4,
+ /** Call key. */
+ AKEYCODE_CALL = 5,
+ /** End Call key. */
+ AKEYCODE_ENDCALL = 6,
+ /** '0' key. */
+ AKEYCODE_0 = 7,
+ /** '1' key. */
+ AKEYCODE_1 = 8,
+ /** '2' key. */
+ AKEYCODE_2 = 9,
+ /** '3' key. */
+ AKEYCODE_3 = 10,
+ /** '4' key. */
+ AKEYCODE_4 = 11,
+ /** '5' key. */
+ AKEYCODE_5 = 12,
+ /** '6' key. */
+ AKEYCODE_6 = 13,
+ /** '7' key. */
+ AKEYCODE_7 = 14,
+ /** '8' key. */
+ AKEYCODE_8 = 15,
+ /** '9' key. */
+ AKEYCODE_9 = 16,
+ /** '*' key. */
+ AKEYCODE_STAR = 17,
+ /** '#' key. */
+ AKEYCODE_POUND = 18,
+ /** Directional Pad Up key.
+ * May also be synthesized from trackball motions. */
+ AKEYCODE_DPAD_UP = 19,
+ /** Directional Pad Down key.
+ * May also be synthesized from trackball motions. */
+ AKEYCODE_DPAD_DOWN = 20,
+ /** Directional Pad Left key.
+ * May also be synthesized from trackball motions. */
+ AKEYCODE_DPAD_LEFT = 21,
+ /** Directional Pad Right key.
+ * May also be synthesized from trackball motions. */
+ AKEYCODE_DPAD_RIGHT = 22,
+ /** Directional Pad Center key.
+ * May also be synthesized from trackball motions. */
+ AKEYCODE_DPAD_CENTER = 23,
+ /** Volume Up key.
+ * Adjusts the speaker volume up. */
+ AKEYCODE_VOLUME_UP = 24,
+ /** Volume Down key.
+ * Adjusts the speaker volume down. */
+ AKEYCODE_VOLUME_DOWN = 25,
+ /** Power key. */
+ AKEYCODE_POWER = 26,
+ /** Camera key.
+ * Used to launch a camera application or take pictures. */
+ AKEYCODE_CAMERA = 27,
+ /** Clear key. */
+ AKEYCODE_CLEAR = 28,
+ /** 'A' key. */
+ AKEYCODE_A = 29,
+ /** 'B' key. */
+ AKEYCODE_B = 30,
+ /** 'C' key. */
+ AKEYCODE_C = 31,
+ /** 'D' key. */
+ AKEYCODE_D = 32,
+ /** 'E' key. */
+ AKEYCODE_E = 33,
+ /** 'F' key. */
+ AKEYCODE_F = 34,
+ /** 'G' key. */
+ AKEYCODE_G = 35,
+ /** 'H' key. */
+ AKEYCODE_H = 36,
+ /** 'I' key. */
+ AKEYCODE_I = 37,
+ /** 'J' key. */
+ AKEYCODE_J = 38,
+ /** 'K' key. */
+ AKEYCODE_K = 39,
+ /** 'L' key. */
+ AKEYCODE_L = 40,
+ /** 'M' key. */
+ AKEYCODE_M = 41,
+ /** 'N' key. */
+ AKEYCODE_N = 42,
+ /** 'O' key. */
+ AKEYCODE_O = 43,
+ /** 'P' key. */
+ AKEYCODE_P = 44,
+ /** 'Q' key. */
+ AKEYCODE_Q = 45,
+ /** 'R' key. */
+ AKEYCODE_R = 46,
+ /** 'S' key. */
+ AKEYCODE_S = 47,
+ /** 'T' key. */
+ AKEYCODE_T = 48,
+ /** 'U' key. */
+ AKEYCODE_U = 49,
+ /** 'V' key. */
+ AKEYCODE_V = 50,
+ /** 'W' key. */
+ AKEYCODE_W = 51,
+ /** 'X' key. */
+ AKEYCODE_X = 52,
+ /** 'Y' key. */
+ AKEYCODE_Y = 53,
+ /** 'Z' key. */
+ AKEYCODE_Z = 54,
+ /** ',' key. */
+ AKEYCODE_COMMA = 55,
+ /** '.' key. */
+ AKEYCODE_PERIOD = 56,
+ /** Left Alt modifier key. */
+ AKEYCODE_ALT_LEFT = 57,
+ /** Right Alt modifier key. */
+ AKEYCODE_ALT_RIGHT = 58,
+ /** Left Shift modifier key. */
+ AKEYCODE_SHIFT_LEFT = 59,
+ /** Right Shift modifier key. */
+ AKEYCODE_SHIFT_RIGHT = 60,
+ /** Tab key. */
+ AKEYCODE_TAB = 61,
+ /** Space key. */
+ AKEYCODE_SPACE = 62,
+ /** Symbol modifier key.
+ * Used to enter alternate symbols. */
+ AKEYCODE_SYM = 63,
+ /** Explorer special function key.
+ * Used to launch a browser application. */
+ AKEYCODE_EXPLORER = 64,
+ /** Envelope special function key.
+ * Used to launch a mail application. */
+ AKEYCODE_ENVELOPE = 65,
+ /** Enter key. */
+ AKEYCODE_ENTER = 66,
+ /** Backspace key.
+ * Deletes characters before the insertion point, unlike {@link AKEYCODE_FORWARD_DEL}. */
+ AKEYCODE_DEL = 67,
+ /** '`' (backtick) key. */
+ AKEYCODE_GRAVE = 68,
+ /** '-'. */
+ AKEYCODE_MINUS = 69,
+ /** '=' key. */
+ AKEYCODE_EQUALS = 70,
+ /** '[' key. */
+ AKEYCODE_LEFT_BRACKET = 71,
+ /** ']' key. */
+ AKEYCODE_RIGHT_BRACKET = 72,
+ /** '\' key. */
+ AKEYCODE_BACKSLASH = 73,
+ /** ';' key. */
+ AKEYCODE_SEMICOLON = 74,
+ /** ''' (apostrophe) key. */
+ AKEYCODE_APOSTROPHE = 75,
+ /** '/' key. */
+ AKEYCODE_SLASH = 76,
+ /** '@' key. */
+ AKEYCODE_AT = 77,
+ /** Number modifier key.
+ * Used to enter numeric symbols.
+ * This key is not {@link AKEYCODE_NUM_LOCK}; it is more like {@link AKEYCODE_ALT_LEFT}. */
+ AKEYCODE_NUM = 78,
+ /** Headset Hook key.
+ * Used to hang up calls and stop media. */
+ AKEYCODE_HEADSETHOOK = 79,
+ /** Camera Focus key.
+ * Used to focus the camera. */
+ AKEYCODE_FOCUS = 80,
+ /** '+' key. */
+ AKEYCODE_PLUS = 81,
+ /** Menu key. */
+ AKEYCODE_MENU = 82,
+ /** Notification key. */
+ AKEYCODE_NOTIFICATION = 83,
+ /** Search key. */
+ AKEYCODE_SEARCH = 84,
+ /** Play/Pause media key. */
+ AKEYCODE_MEDIA_PLAY_PAUSE= 85,
+ /** Stop media key. */
+ AKEYCODE_MEDIA_STOP = 86,
+ /** Play Next media key. */
+ AKEYCODE_MEDIA_NEXT = 87,
+ /** Play Previous media key. */
+ AKEYCODE_MEDIA_PREVIOUS = 88,
+ /** Rewind media key. */
+ AKEYCODE_MEDIA_REWIND = 89,
+ /** Fast Forward media key. */
+ AKEYCODE_MEDIA_FAST_FORWARD = 90,
+ /** Mute key.
+ * Mutes the microphone, unlike {@link AKEYCODE_VOLUME_MUTE}. */
+ AKEYCODE_MUTE = 91,
+ /** Page Up key. */
+ AKEYCODE_PAGE_UP = 92,
+ /** Page Down key. */
+ AKEYCODE_PAGE_DOWN = 93,
+ /** Picture Symbols modifier key.
+ * Used to switch symbol sets (Emoji, Kao-moji). */
+ AKEYCODE_PICTSYMBOLS = 94,
+ /** Switch Charset modifier key.
+ * Used to switch character sets (Kanji, Katakana). */
+ AKEYCODE_SWITCH_CHARSET = 95,
+ /** A Button key.
+ * On a game controller, the A button should be either the button labeled A
+ * or the first button on the bottom row of controller buttons. */
+ AKEYCODE_BUTTON_A = 96,
+ /** B Button key.
+ * On a game controller, the B button should be either the button labeled B
+ * or the second button on the bottom row of controller buttons. */
+ AKEYCODE_BUTTON_B = 97,
+ /** C Button key.
+ * On a game controller, the C button should be either the button labeled C
+ * or the third button on the bottom row of controller buttons. */
+ AKEYCODE_BUTTON_C = 98,
+ /** X Button key.
+ * On a game controller, the X button should be either the button labeled X
+ * or the first button on the upper row of controller buttons. */
+ AKEYCODE_BUTTON_X = 99,
+ /** Y Button key.
+ * On a game controller, the Y button should be either the button labeled Y
+ * or the second button on the upper row of controller buttons. */
+ AKEYCODE_BUTTON_Y = 100,
+ /** Z Button key.
+ * On a game controller, the Z button should be either the button labeled Z
+ * or the third button on the upper row of controller buttons. */
+ AKEYCODE_BUTTON_Z = 101,
+ /** L1 Button key.
+ * On a game controller, the L1 button should be either the button labeled L1 (or L)
+ * or the top left trigger button. */
+ AKEYCODE_BUTTON_L1 = 102,
+ /** R1 Button key.
+ * On a game controller, the R1 button should be either the button labeled R1 (or R)
+ * or the top right trigger button. */
+ AKEYCODE_BUTTON_R1 = 103,
+ /** L2 Button key.
+ * On a game controller, the L2 button should be either the button labeled L2
+ * or the bottom left trigger button. */
+ AKEYCODE_BUTTON_L2 = 104,
+ /** R2 Button key.
+ * On a game controller, the R2 button should be either the button labeled R2
+ * or the bottom right trigger button. */
+ AKEYCODE_BUTTON_R2 = 105,
+ /** Left Thumb Button key.
+ * On a game controller, the left thumb button indicates that the left (or only)
+ * joystick is pressed. */
+ AKEYCODE_BUTTON_THUMBL = 106,
+ /** Right Thumb Button key.
+ * On a game controller, the right thumb button indicates that the right
+ * joystick is pressed. */
+ AKEYCODE_BUTTON_THUMBR = 107,
+ /** Start Button key.
+ * On a game controller, the button labeled Start. */
+ AKEYCODE_BUTTON_START = 108,
+ /** Select Button key.
+ * On a game controller, the button labeled Select. */
+ AKEYCODE_BUTTON_SELECT = 109,
+ /** Mode Button key.
+ * On a game controller, the button labeled Mode. */
+ AKEYCODE_BUTTON_MODE = 110,
+ /** Escape key. */
+ AKEYCODE_ESCAPE = 111,
+ /** Forward Delete key.
+ * Deletes characters ahead of the insertion point, unlike {@link AKEYCODE_DEL}. */
+ AKEYCODE_FORWARD_DEL = 112,
+ /** Left Control modifier key. */
+ AKEYCODE_CTRL_LEFT = 113,
+ /** Right Control modifier key. */
+ AKEYCODE_CTRL_RIGHT = 114,
+ /** Caps Lock key. */
+ AKEYCODE_CAPS_LOCK = 115,
+ /** Scroll Lock key. */
+ AKEYCODE_SCROLL_LOCK = 116,
+ /** Left Meta modifier key. */
+ AKEYCODE_META_LEFT = 117,
+ /** Right Meta modifier key. */
+ AKEYCODE_META_RIGHT = 118,
+ /** Function modifier key. */
+ AKEYCODE_FUNCTION = 119,
+ /** System Request / Print Screen key. */
+ AKEYCODE_SYSRQ = 120,
+ /** Break / Pause key. */
+ AKEYCODE_BREAK = 121,
+ /** Home Movement key.
+ * Used for scrolling or moving the cursor around to the start of a line
+ * or to the top of a list. */
+ AKEYCODE_MOVE_HOME = 122,
+ /** End Movement key.
+ * Used for scrolling or moving the cursor around to the end of a line
+ * or to the bottom of a list. */
+ AKEYCODE_MOVE_END = 123,
+ /** Insert key.
+ * Toggles insert / overwrite edit mode. */
+ AKEYCODE_INSERT = 124,
+ /** Forward key.
+ * Navigates forward in the history stack. Complement of {@link AKEYCODE_BACK}. */
+ AKEYCODE_FORWARD = 125,
+ /** Play media key. */
+ AKEYCODE_MEDIA_PLAY = 126,
+ /** Pause media key. */
+ AKEYCODE_MEDIA_PAUSE = 127,
+ /** Close media key.
+ * May be used to close a CD tray, for example. */
+ AKEYCODE_MEDIA_CLOSE = 128,
+ /** Eject media key.
+ * May be used to eject a CD tray, for example. */
+ AKEYCODE_MEDIA_EJECT = 129,
+ /** Record media key. */
+ AKEYCODE_MEDIA_RECORD = 130,
+ /** F1 key. */
+ AKEYCODE_F1 = 131,
+ /** F2 key. */
+ AKEYCODE_F2 = 132,
+ /** F3 key. */
+ AKEYCODE_F3 = 133,
+ /** F4 key. */
+ AKEYCODE_F4 = 134,
+ /** F5 key. */
+ AKEYCODE_F5 = 135,
+ /** F6 key. */
+ AKEYCODE_F6 = 136,
+ /** F7 key. */
+ AKEYCODE_F7 = 137,
+ /** F8 key. */
+ AKEYCODE_F8 = 138,
+ /** F9 key. */
+ AKEYCODE_F9 = 139,
+ /** F10 key. */
+ AKEYCODE_F10 = 140,
+ /** F11 key. */
+ AKEYCODE_F11 = 141,
+ /** F12 key. */
+ AKEYCODE_F12 = 142,
+ /** Num Lock key.
+ * This is the Num Lock key; it is different from {@link AKEYCODE_NUM}.
+ * This key alters the behavior of other keys on the numeric keypad. */
+ AKEYCODE_NUM_LOCK = 143,
+ /** Numeric keypad '0' key. */
+ AKEYCODE_NUMPAD_0 = 144,
+ /** Numeric keypad '1' key. */
+ AKEYCODE_NUMPAD_1 = 145,
+ /** Numeric keypad '2' key. */
+ AKEYCODE_NUMPAD_2 = 146,
+ /** Numeric keypad '3' key. */
+ AKEYCODE_NUMPAD_3 = 147,
+ /** Numeric keypad '4' key. */
+ AKEYCODE_NUMPAD_4 = 148,
+ /** Numeric keypad '5' key. */
+ AKEYCODE_NUMPAD_5 = 149,
+ /** Numeric keypad '6' key. */
+ AKEYCODE_NUMPAD_6 = 150,
+ /** Numeric keypad '7' key. */
+ AKEYCODE_NUMPAD_7 = 151,
+ /** Numeric keypad '8' key. */
+ AKEYCODE_NUMPAD_8 = 152,
+ /** Numeric keypad '9' key. */
+ AKEYCODE_NUMPAD_9 = 153,
+ /** Numeric keypad '/' key (for division). */
+ AKEYCODE_NUMPAD_DIVIDE = 154,
+ /** Numeric keypad '*' key (for multiplication). */
+ AKEYCODE_NUMPAD_MULTIPLY = 155,
+ /** Numeric keypad '-' key (for subtraction). */
+ AKEYCODE_NUMPAD_SUBTRACT = 156,
+ /** Numeric keypad '+' key (for addition). */
+ AKEYCODE_NUMPAD_ADD = 157,
+ /** Numeric keypad '.' key (for decimals or digit grouping). */
+ AKEYCODE_NUMPAD_DOT = 158,
+ /** Numeric keypad ',' key (for decimals or digit grouping). */
+ AKEYCODE_NUMPAD_COMMA = 159,
+ /** Numeric keypad Enter key. */
+ AKEYCODE_NUMPAD_ENTER = 160,
+ /** Numeric keypad '=' key. */
+ AKEYCODE_NUMPAD_EQUALS = 161,
+ /** Numeric keypad '(' key. */
+ AKEYCODE_NUMPAD_LEFT_PAREN = 162,
+ /** Numeric keypad ')' key. */
+ AKEYCODE_NUMPAD_RIGHT_PAREN = 163,
+ /** Volume Mute key.
+ * Mutes the speaker, unlike {@link AKEYCODE_MUTE}.
+ * This key should normally be implemented as a toggle such that the first press
+ * mutes the speaker and the second press restores the original volume. */
+ AKEYCODE_VOLUME_MUTE = 164,
+ /** Info key.
+ * Common on TV remotes to show additional information related to what is
+ * currently being viewed. */
+ AKEYCODE_INFO = 165,
+ /** Channel up key.
+ * On TV remotes, increments the television channel. */
+ AKEYCODE_CHANNEL_UP = 166,
+ /** Channel down key.
+ * On TV remotes, decrements the television channel. */
+ AKEYCODE_CHANNEL_DOWN = 167,
+ /** Zoom in key. */
+ AKEYCODE_ZOOM_IN = 168,
+ /** Zoom out key. */
+ AKEYCODE_ZOOM_OUT = 169,
+ /** TV key.
+ * On TV remotes, switches to viewing live TV. */
+ AKEYCODE_TV = 170,
+ /** Window key.
+ * On TV remotes, toggles picture-in-picture mode or other windowing functions. */
+ AKEYCODE_WINDOW = 171,
+ /** Guide key.
+ * On TV remotes, shows a programming guide. */
+ AKEYCODE_GUIDE = 172,
+ /** DVR key.
+ * On some TV remotes, switches to a DVR mode for recorded shows. */
+ AKEYCODE_DVR = 173,
+ /** Bookmark key.
+ * On some TV remotes, bookmarks content or web pages. */
+ AKEYCODE_BOOKMARK = 174,
+ /** Toggle captions key.
+ * Switches the mode for closed-captioning text, for example during television shows. */
+ AKEYCODE_CAPTIONS = 175,
+ /** Settings key.
+ * Starts the system settings activity. */
+ AKEYCODE_SETTINGS = 176,
+ /** TV power key.
+ * On TV remotes, toggles the power on a television screen. */
+ AKEYCODE_TV_POWER = 177,
+ /** TV input key.
+ * On TV remotes, switches the input on a television screen. */
+ AKEYCODE_TV_INPUT = 178,
+ /** Set-top-box power key.
+ * On TV remotes, toggles the power on an external Set-top-box. */
+ AKEYCODE_STB_POWER = 179,
+ /** Set-top-box input key.
+ * On TV remotes, switches the input mode on an external Set-top-box. */
+ AKEYCODE_STB_INPUT = 180,
+ /** A/V Receiver power key.
+ * On TV remotes, toggles the power on an external A/V Receiver. */
+ AKEYCODE_AVR_POWER = 181,
+ /** A/V Receiver input key.
+ * On TV remotes, switches the input mode on an external A/V Receiver. */
+ AKEYCODE_AVR_INPUT = 182,
+ /** Red "programmable" key.
+ * On TV remotes, acts as a contextual/programmable key. */
+ AKEYCODE_PROG_RED = 183,
+ /** Green "programmable" key.
+ * On TV remotes, actsas a contextual/programmable key. */
+ AKEYCODE_PROG_GREEN = 184,
+ /** Yellow "programmable" key.
+ * On TV remotes, acts as a contextual/programmable key. */
+ AKEYCODE_PROG_YELLOW = 185,
+ /** Blue "programmable" key.
+ * On TV remotes, acts as a contextual/programmable key. */
+ AKEYCODE_PROG_BLUE = 186,
+ /** App switch key.
+ * Should bring up the application switcher dialog. */
+ AKEYCODE_APP_SWITCH = 187,
+ /** Generic Game Pad Button #1.*/
+ AKEYCODE_BUTTON_1 = 188,
+ /** Generic Game Pad Button #2.*/
+ AKEYCODE_BUTTON_2 = 189,
+ /** Generic Game Pad Button #3.*/
+ AKEYCODE_BUTTON_3 = 190,
+ /** Generic Game Pad Button #4.*/
+ AKEYCODE_BUTTON_4 = 191,
+ /** Generic Game Pad Button #5.*/
+ AKEYCODE_BUTTON_5 = 192,
+ /** Generic Game Pad Button #6.*/
+ AKEYCODE_BUTTON_6 = 193,
+ /** Generic Game Pad Button #7.*/
+ AKEYCODE_BUTTON_7 = 194,
+ /** Generic Game Pad Button #8.*/
+ AKEYCODE_BUTTON_8 = 195,
+ /** Generic Game Pad Button #9.*/
+ AKEYCODE_BUTTON_9 = 196,
+ /** Generic Game Pad Button #10.*/
+ AKEYCODE_BUTTON_10 = 197,
+ /** Generic Game Pad Button #11.*/
+ AKEYCODE_BUTTON_11 = 198,
+ /** Generic Game Pad Button #12.*/
+ AKEYCODE_BUTTON_12 = 199,
+ /** Generic Game Pad Button #13.*/
+ AKEYCODE_BUTTON_13 = 200,
+ /** Generic Game Pad Button #14.*/
+ AKEYCODE_BUTTON_14 = 201,
+ /** Generic Game Pad Button #15.*/
+ AKEYCODE_BUTTON_15 = 202,
+ /** Generic Game Pad Button #16.*/
+ AKEYCODE_BUTTON_16 = 203,
+ /** Language Switch key.
+ * Toggles the current input language such as switching between English and Japanese on
+ * a QWERTY keyboard. On some devices, the same function may be performed by
+ * pressing Shift+Spacebar. */
+ AKEYCODE_LANGUAGE_SWITCH = 204,
+ /** Manner Mode key.
+ * Toggles silent or vibrate mode on and off to make the device behave more politely
+ * in certain settings such as on a crowded train. On some devices, the key may only
+ * operate when long-pressed. */
+ AKEYCODE_MANNER_MODE = 205,
+ /** 3D Mode key.
+ * Toggles the display between 2D and 3D mode. */
+ AKEYCODE_3D_MODE = 206,
+ /** Contacts special function key.
+ * Used to launch an address book application. */
+ AKEYCODE_CONTACTS = 207,
+ /** Calendar special function key.
+ * Used to launch a calendar application. */
+ AKEYCODE_CALENDAR = 208,
+ /** Music special function key.
+ * Used to launch a music player application. */
+ AKEYCODE_MUSIC = 209,
+ /** Calculator special function key.
+ * Used to launch a calculator application. */
+ AKEYCODE_CALCULATOR = 210,
+ /** Japanese full-width / half-width key. */
+ AKEYCODE_ZENKAKU_HANKAKU = 211,
+ /** Japanese alphanumeric key. */
+ AKEYCODE_EISU = 212,
+ /** Japanese non-conversion key. */
+ AKEYCODE_MUHENKAN = 213,
+ /** Japanese conversion key. */
+ AKEYCODE_HENKAN = 214,
+ /** Japanese katakana / hiragana key. */
+ AKEYCODE_KATAKANA_HIRAGANA = 215,
+ /** Japanese Yen key. */
+ AKEYCODE_YEN = 216,
+ /** Japanese Ro key. */
+ AKEYCODE_RO = 217,
+ /** Japanese kana key. */
+ AKEYCODE_KANA = 218,
+ /** Assist key.
+ * Launches the global assist activity. Not delivered to applications. */
+ AKEYCODE_ASSIST = 219,
+ /** Brightness Down key.
+ * Adjusts the screen brightness down. */
+ AKEYCODE_BRIGHTNESS_DOWN = 220,
+ /** Brightness Up key.
+ * Adjusts the screen brightness up. */
+ AKEYCODE_BRIGHTNESS_UP = 221,
+ /** Audio Track key.
+ * Switches the audio tracks. */
+ AKEYCODE_MEDIA_AUDIO_TRACK = 222,
+ /** Sleep key.
+ * Puts the device to sleep. Behaves somewhat like {@link AKEYCODE_POWER} but it
+ * has no effect if the device is already asleep. */
+ AKEYCODE_SLEEP = 223,
+ /** Wakeup key.
+ * Wakes up the device. Behaves somewhat like {@link AKEYCODE_POWER} but it
+ * has no effect if the device is already awake. */
+ AKEYCODE_WAKEUP = 224,
+ /** Pairing key.
+ * Initiates peripheral pairing mode. Useful for pairing remote control
+ * devices or game controllers, especially if no other input mode is
+ * available. */
+ AKEYCODE_PAIRING = 225,
+ /** Media Top Menu key.
+ * Goes to the top of media menu. */
+ AKEYCODE_MEDIA_TOP_MENU = 226,
+ /** '11' key. */
+ AKEYCODE_11 = 227,
+ /** '12' key. */
+ AKEYCODE_12 = 228,
+ /** Last Channel key.
+ * Goes to the last viewed channel. */
+ AKEYCODE_LAST_CHANNEL = 229,
+ /** TV data service key.
+ * Displays data services like weather, sports. */
+ AKEYCODE_TV_DATA_SERVICE = 230,
+ /** Voice Assist key.
+ * Launches the global voice assist activity. Not delivered to applications. */
+ AKEYCODE_VOICE_ASSIST = 231,
+ /** Radio key.
+ * Toggles TV service / Radio service. */
+ AKEYCODE_TV_RADIO_SERVICE = 232,
+ /** Teletext key.
+ * Displays Teletext service. */
+ AKEYCODE_TV_TELETEXT = 233,
+ /** Number entry key.
+ * Initiates to enter multi-digit channel nubmber when each digit key is assigned
+ * for selecting separate channel. Corresponds to Number Entry Mode (0x1D) of CEC
+ * User Control Code. */
+ AKEYCODE_TV_NUMBER_ENTRY = 234,
+ /** Analog Terrestrial key.
+ * Switches to analog terrestrial broadcast service. */
+ AKEYCODE_TV_TERRESTRIAL_ANALOG = 235,
+ /** Digital Terrestrial key.
+ * Switches to digital terrestrial broadcast service. */
+ AKEYCODE_TV_TERRESTRIAL_DIGITAL = 236,
+ /** Satellite key.
+ * Switches to digital satellite broadcast service. */
+ AKEYCODE_TV_SATELLITE = 237,
+ /** BS key.
+ * Switches to BS digital satellite broadcasting service available in Japan. */
+ AKEYCODE_TV_SATELLITE_BS = 238,
+ /** CS key.
+ * Switches to CS digital satellite broadcasting service available in Japan. */
+ AKEYCODE_TV_SATELLITE_CS = 239,
+ /** BS/CS key.
+ * Toggles between BS and CS digital satellite services. */
+ AKEYCODE_TV_SATELLITE_SERVICE = 240,
+ /** Toggle Network key.
+ * Toggles selecting broacast services. */
+ AKEYCODE_TV_NETWORK = 241,
+ /** Antenna/Cable key.
+ * Toggles broadcast input source between antenna and cable. */
+ AKEYCODE_TV_ANTENNA_CABLE = 242,
+ /** HDMI #1 key.
+ * Switches to HDMI input #1. */
+ AKEYCODE_TV_INPUT_HDMI_1 = 243,
+ /** HDMI #2 key.
+ * Switches to HDMI input #2. */
+ AKEYCODE_TV_INPUT_HDMI_2 = 244,
+ /** HDMI #3 key.
+ * Switches to HDMI input #3. */
+ AKEYCODE_TV_INPUT_HDMI_3 = 245,
+ /** HDMI #4 key.
+ * Switches to HDMI input #4. */
+ AKEYCODE_TV_INPUT_HDMI_4 = 246,
+ /** Composite #1 key.
+ * Switches to composite video input #1. */
+ AKEYCODE_TV_INPUT_COMPOSITE_1 = 247,
+ /** Composite #2 key.
+ * Switches to composite video input #2. */
+ AKEYCODE_TV_INPUT_COMPOSITE_2 = 248,
+ /** Component #1 key.
+ * Switches to component video input #1. */
+ AKEYCODE_TV_INPUT_COMPONENT_1 = 249,
+ /** Component #2 key.
+ * Switches to component video input #2. */
+ AKEYCODE_TV_INPUT_COMPONENT_2 = 250,
+ /** VGA #1 key.
+ * Switches to VGA (analog RGB) input #1. */
+ AKEYCODE_TV_INPUT_VGA_1 = 251,
+ /** Audio description key.
+ * Toggles audio description off / on. */
+ AKEYCODE_TV_AUDIO_DESCRIPTION = 252,
+ /** Audio description mixing volume up key.
+ * Louden audio description volume as compared with normal audio volume. */
+ AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP = 253,
+ /** Audio description mixing volume down key.
+ * Lessen audio description volume as compared with normal audio volume. */
+ AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN = 254,
+ /** Zoom mode key.
+ * Changes Zoom mode (Normal, Full, Zoom, Wide-zoom, etc.) */
+ AKEYCODE_TV_ZOOM_MODE = 255,
+ /** Contents menu key.
+ * Goes to the title list. Corresponds to Contents Menu (0x0B) of CEC User Control
+ * Code */
+ AKEYCODE_TV_CONTENTS_MENU = 256,
+ /** Media context menu key.
+ * Goes to the context menu of media contents. Corresponds to Media Context-sensitive
+ * Menu (0x11) of CEC User Control Code. */
+ AKEYCODE_TV_MEDIA_CONTEXT_MENU = 257,
+ /** Timer programming key.
+ * Goes to the timer recording menu. Corresponds to Timer Programming (0x54) of
+ * CEC User Control Code. */
+ AKEYCODE_TV_TIMER_PROGRAMMING = 258,
+ /** Help key. */
+ AKEYCODE_HELP = 259,
+ AKEYCODE_NAVIGATE_PREVIOUS = 260,
+ AKEYCODE_NAVIGATE_NEXT = 261,
+ AKEYCODE_NAVIGATE_IN = 262,
+ AKEYCODE_NAVIGATE_OUT = 263,
+ /** Primary stem key for Wear
+ * Main power/reset button on watch. */
+ AKEYCODE_STEM_PRIMARY = 264,
+ /** Generic stem key 1 for Wear */
+ AKEYCODE_STEM_1 = 265,
+ /** Generic stem key 2 for Wear */
+ AKEYCODE_STEM_2 = 266,
+ /** Generic stem key 3 for Wear */
+ AKEYCODE_STEM_3 = 267,
+ AKEYCODE_MEDIA_SKIP_FORWARD = 272,
+ AKEYCODE_MEDIA_SKIP_BACKWARD = 273,
+ AKEYCODE_MEDIA_STEP_FORWARD = 274,
+ AKEYCODE_MEDIA_STEP_BACKWARD = 275,
+ /** Put device to sleep unless a wakelock is held. */
+ AKEYCODE_SOFT_SLEEP = 276
+
+ // NOTE: If you add a new keycode here you must also add it to several other files.
+ // Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _ANDROID_KEYCODES_H
+
+/** @} */
diff --git a/phonelibs/android_frameworks_native/include/android/looper.h b/phonelibs/android_frameworks_native/include/android/looper.h
new file mode 100644
index 000000000..718f70304
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/android/looper.h
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ */
+
+/**
+ * @addtogroup Looper
+ * @{
+ */
+
+/**
+ * @file looper.h
+ */
+
+#ifndef ANDROID_LOOPER_H
+#define ANDROID_LOOPER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ALooper;
+/**
+ * ALooper
+ *
+ * A looper is the state tracking an event loop for a thread.
+ * Loopers do not define event structures or other such things; rather
+ * they are a lower-level facility to attach one or more discrete objects
+ * listening for an event. An "event" here is simply data available on
+ * a file descriptor: each attached object has an associated file descriptor,
+ * and waiting for "events" means (internally) polling on all of these file
+ * descriptors until one or more of them have data available.
+ *
+ * A thread can have only one ALooper associated with it.
+ */
+typedef struct ALooper ALooper;
+
+/**
+ * Returns the looper associated with the calling thread, or NULL if
+ * there is not one.
+ */
+ALooper* ALooper_forThread();
+
+/** Option for for ALooper_prepare(). */
+enum {
+ /**
+ * This looper will accept calls to ALooper_addFd() that do not
+ * have a callback (that is provide NULL for the callback). In
+ * this case the caller of ALooper_pollOnce() or ALooper_pollAll()
+ * MUST check the return from these functions to discover when
+ * data is available on such fds and process it.
+ */
+ ALOOPER_PREPARE_ALLOW_NON_CALLBACKS = 1<<0
+};
+
+/**
+ * Prepares a looper associated with the calling thread, and returns it.
+ * If the thread already has a looper, it is returned. Otherwise, a new
+ * one is created, associated with the thread, and returned.
+ *
+ * The opts may be ALOOPER_PREPARE_ALLOW_NON_CALLBACKS or 0.
+ */
+ALooper* ALooper_prepare(int opts);
+
+/** Result from ALooper_pollOnce() and ALooper_pollAll(). */
+enum {
+ /**
+ * The poll was awoken using wake() before the timeout expired
+ * and no callbacks were executed and no other file descriptors were ready.
+ */
+ ALOOPER_POLL_WAKE = -1,
+
+ /**
+ * Result from ALooper_pollOnce() and ALooper_pollAll():
+ * One or more callbacks were executed.
+ */
+ ALOOPER_POLL_CALLBACK = -2,
+
+ /**
+ * Result from ALooper_pollOnce() and ALooper_pollAll():
+ * The timeout expired.
+ */
+ ALOOPER_POLL_TIMEOUT = -3,
+
+ /**
+ * Result from ALooper_pollOnce() and ALooper_pollAll():
+ * An error occurred.
+ */
+ ALOOPER_POLL_ERROR = -4,
+};
+
+/**
+ * Acquire a reference on the given ALooper object. This prevents the object
+ * from being deleted until the reference is removed. This is only needed
+ * to safely hand an ALooper from one thread to another.
+ */
+void ALooper_acquire(ALooper* looper);
+
+/**
+ * Remove a reference that was previously acquired with ALooper_acquire().
+ */
+void ALooper_release(ALooper* looper);
+
+/**
+ * Flags for file descriptor events that a looper can monitor.
+ *
+ * These flag bits can be combined to monitor multiple events at once.
+ */
+enum {
+ /**
+ * The file descriptor is available for read operations.
+ */
+ ALOOPER_EVENT_INPUT = 1 << 0,
+
+ /**
+ * The file descriptor is available for write operations.
+ */
+ ALOOPER_EVENT_OUTPUT = 1 << 1,
+
+ /**
+ * The file descriptor has encountered an error condition.
+ *
+ * The looper always sends notifications about errors; it is not necessary
+ * to specify this event flag in the requested event set.
+ */
+ ALOOPER_EVENT_ERROR = 1 << 2,
+
+ /**
+ * The file descriptor was hung up.
+ * For example, indicates that the remote end of a pipe or socket was closed.
+ *
+ * The looper always sends notifications about hangups; it is not necessary
+ * to specify this event flag in the requested event set.
+ */
+ ALOOPER_EVENT_HANGUP = 1 << 3,
+
+ /**
+ * The file descriptor is invalid.
+ * For example, the file descriptor was closed prematurely.
+ *
+ * The looper always sends notifications about invalid file descriptors; it is not necessary
+ * to specify this event flag in the requested event set.
+ */
+ ALOOPER_EVENT_INVALID = 1 << 4,
+};
+
+/**
+ * For callback-based event loops, this is the prototype of the function
+ * that is called when a file descriptor event occurs.
+ * It is given the file descriptor it is associated with,
+ * a bitmask of the poll events that were triggered (typically ALOOPER_EVENT_INPUT),
+ * and the data pointer that was originally supplied.
+ *
+ * Implementations should return 1 to continue receiving callbacks, or 0
+ * to have this file descriptor and callback unregistered from the looper.
+ */
+typedef int (*ALooper_callbackFunc)(int fd, int events, void* data);
+
+/**
+ * Waits for events to be available, with optional timeout in milliseconds.
+ * Invokes callbacks for all file descriptors on which an event occurred.
+ *
+ * If the timeout is zero, returns immediately without blocking.
+ * If the timeout is negative, waits indefinitely until an event appears.
+ *
+ * Returns ALOOPER_POLL_WAKE if the poll was awoken using wake() before
+ * the timeout expired and no callbacks were invoked and no other file
+ * descriptors were ready.
+ *
+ * Returns ALOOPER_POLL_CALLBACK if one or more callbacks were invoked.
+ *
+ * Returns ALOOPER_POLL_TIMEOUT if there was no data before the given
+ * timeout expired.
+ *
+ * Returns ALOOPER_POLL_ERROR if an error occurred.
+ *
+ * Returns a value >= 0 containing an identifier (the same identifier
+ * `ident` passed to ALooper_addFd()) if its file descriptor has data
+ * and it has no callback function (requiring the caller here to
+ * handle it). In this (and only this) case outFd, outEvents and
+ * outData will contain the poll events and data associated with the
+ * fd, otherwise they will be set to NULL.
+ *
+ * This method does not return until it has finished invoking the appropriate callbacks
+ * for all file descriptors that were signalled.
+ */
+int ALooper_pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData);
+
+/**
+ * Like ALooper_pollOnce(), but performs all pending callbacks until all
+ * data has been consumed or a file descriptor is available with no callback.
+ * This function will never return ALOOPER_POLL_CALLBACK.
+ */
+int ALooper_pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData);
+
+/**
+ * Wakes the poll asynchronously.
+ *
+ * This method can be called on any thread.
+ * This method returns immediately.
+ */
+void ALooper_wake(ALooper* looper);
+
+/**
+ * Adds a new file descriptor to be polled by the looper.
+ * If the same file descriptor was previously added, it is replaced.
+ *
+ * "fd" is the file descriptor to be added.
+ * "ident" is an identifier for this event, which is returned from ALooper_pollOnce().
+ * The identifier must be >= 0, or ALOOPER_POLL_CALLBACK if providing a non-NULL callback.
+ * "events" are the poll events to wake up on. Typically this is ALOOPER_EVENT_INPUT.
+ * "callback" is the function to call when there is an event on the file descriptor.
+ * "data" is a private data pointer to supply to the callback.
+ *
+ * There are two main uses of this function:
+ *
+ * (1) If "callback" is non-NULL, then this function will be called when there is
+ * data on the file descriptor. It should execute any events it has pending,
+ * appropriately reading from the file descriptor. The 'ident' is ignored in this case.
+ *
+ * (2) If "callback" is NULL, the 'ident' will be returned by ALooper_pollOnce
+ * when its file descriptor has data available, requiring the caller to take
+ * care of processing it.
+ *
+ * Returns 1 if the file descriptor was added or -1 if an error occurred.
+ *
+ * This method can be called on any thread.
+ * This method may block briefly if it needs to wake the poll.
+ */
+int ALooper_addFd(ALooper* looper, int fd, int ident, int events,
+ ALooper_callbackFunc callback, void* data);
+
+/**
+ * Removes a previously added file descriptor from the looper.
+ *
+ * When this method returns, it is safe to close the file descriptor since the looper
+ * will no longer have a reference to it. However, it is possible for the callback to
+ * already be running or for it to run one last time if the file descriptor was already
+ * signalled. Calling code is responsible for ensuring that this case is safely handled.
+ * For example, if the callback takes care of removing itself during its own execution either
+ * by returning 0 or by calling this method, then it can be guaranteed to not be invoked
+ * again at any later time unless registered anew.
+ *
+ * Returns 1 if the file descriptor was removed, 0 if none was previously registered
+ * or -1 if an error occurred.
+ *
+ * This method can be called on any thread.
+ * This method may block briefly if it needs to wake the poll.
+ */
+int ALooper_removeFd(ALooper* looper, int fd);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // ANDROID_LOOPER_H
+
+/** @} */
diff --git a/phonelibs/android_frameworks_native/include/android/multinetwork.h b/phonelibs/android_frameworks_native/include/android/multinetwork.h
new file mode 100644
index 000000000..6c718c903
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/android/multinetwork.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * 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 ANDROID_MULTINETWORK_H
+#define ANDROID_MULTINETWORK_H
+
+#include
+#include
+#include
+
+__BEGIN_DECLS
+
+/**
+ * The corresponding C type for android.net.Network#getNetworkHandle() return
+ * values. The Java signed long value can be safely cast to a net_handle_t:
+ *
+ * [C] ((net_handle_t) java_long_network_handle)
+ * [C++] static_cast(java_long_network_handle)
+ *
+ * as appropriate.
+ */
+typedef uint64_t net_handle_t;
+
+/**
+ * The value NETWORK_UNSPECIFIED indicates no specific network.
+ *
+ * For some functions (documented below), a previous binding may be cleared
+ * by an invocation with NETWORK_UNSPECIFIED.
+ *
+ * Depending on the context it may indicate an error. It is expressly
+ * not used to indicate some notion of the "current default network".
+ */
+#define NETWORK_UNSPECIFIED ((net_handle_t)0)
+
+
+/**
+ * All functions below that return an int return 0 on success or -1
+ * on failure with an appropriate errno value set.
+ */
+
+
+/**
+ * Set the network to be used by the given socket file descriptor.
+ *
+ * To clear a previous socket binding invoke with NETWORK_UNSPECIFIED.
+ *
+ * This is the equivalent of:
+ *
+ * [ android.net.Network#bindSocket() ]
+ * https://developer.android.com/reference/android/net/Network.html#bindSocket(java.net.Socket)
+ */
+int android_setsocknetwork(net_handle_t network, int fd);
+
+
+/**
+ * Binds the current process to |network|. All sockets created in the future
+ * (and not explicitly bound via android_setsocknetwork()) will be bound to
+ * |network|. All host name resolutions will be limited to |network| as well.
+ * Note that if the network identified by |network| ever disconnects, all
+ * sockets created in this way will cease to work and all host name
+ * resolutions will fail. This is by design so an application doesn't
+ * accidentally use sockets it thinks are still bound to a particular network.
+ *
+ * To clear a previous process binding invoke with NETWORK_UNSPECIFIED.
+ *
+ * This is the equivalent of:
+ *
+ * [ android.net.ConnectivityManager#setProcessDefaultNetwork() ]
+ * https://developer.android.com/reference/android/net/ConnectivityManager.html#setProcessDefaultNetwork(android.net.Network)
+ */
+int android_setprocnetwork(net_handle_t network);
+
+
+/**
+ * Perform hostname resolution via the DNS servers associated with |network|.
+ *
+ * All arguments (apart from |network|) are used identically as those passed
+ * to getaddrinfo(3). Return and error values are identical to those of
+ * getaddrinfo(3), and in particular gai_strerror(3) can be used as expected.
+ * Similar to getaddrinfo(3):
+ * - |hints| may be NULL (in which case man page documented defaults apply)
+ * - either |node| or |service| may be NULL, but not both
+ * - |res| must not be NULL
+ *
+ * This is the equivalent of:
+ *
+ * [ android.net.Network#getAllByName() ]
+ * https://developer.android.com/reference/android/net/Network.html#getAllByName(java.lang.String)
+ */
+int android_getaddrinfofornetwork(net_handle_t network,
+ const char *node, const char *service,
+ const struct addrinfo *hints, struct addrinfo **res);
+
+__END_DECLS
+
+#endif // ANDROID_MULTINETWORK_H
diff --git a/phonelibs/android_frameworks_native/include/android/native_activity.h b/phonelibs/android_frameworks_native/include/android/native_activity.h
new file mode 100644
index 000000000..d3d99cf7a
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/android/native_activity.h
@@ -0,0 +1,340 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ */
+
+/**
+ * @addtogroup NativeActivity Native Activity
+ * @{
+ */
+
+/**
+ * @file native_activity.h
+ */
+
+#ifndef ANDROID_NATIVE_ACTIVITY_H
+#define ANDROID_NATIVE_ACTIVITY_H
+
+#include
+#include
+
+#include
+
+#include
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * {@link ANativeActivityCallbacks}
+ */
+struct ANativeActivityCallbacks;
+
+/**
+ * This structure defines the native side of an android.app.NativeActivity.
+ * It is created by the framework, and handed to the application's native
+ * code as it is being launched.
+ */
+typedef struct ANativeActivity {
+ /**
+ * Pointer to the callback function table of the native application.
+ * You can set the functions here to your own callbacks. The callbacks
+ * pointer itself here should not be changed; it is allocated and managed
+ * for you by the framework.
+ */
+ struct ANativeActivityCallbacks* callbacks;
+
+ /**
+ * The global handle on the process's Java VM.
+ */
+ JavaVM* vm;
+
+ /**
+ * JNI context for the main thread of the app. Note that this field
+ * can ONLY be used from the main thread of the process; that is, the
+ * thread that calls into the ANativeActivityCallbacks.
+ */
+ JNIEnv* env;
+
+ /**
+ * The NativeActivity object handle.
+ *
+ * IMPORTANT NOTE: This member is mis-named. It should really be named
+ * 'activity' instead of 'clazz', since it's a reference to the
+ * NativeActivity instance created by the system for you.
+ *
+ * We unfortunately cannot change this without breaking NDK
+ * source-compatibility.
+ */
+ jobject clazz;
+
+ /**
+ * Path to this application's internal data directory.
+ */
+ const char* internalDataPath;
+
+ /**
+ * Path to this application's external (removable/mountable) data directory.
+ */
+ const char* externalDataPath;
+
+ /**
+ * The platform's SDK version code.
+ */
+ int32_t sdkVersion;
+
+ /**
+ * This is the native instance of the application. It is not used by
+ * the framework, but can be set by the application to its own instance
+ * state.
+ */
+ void* instance;
+
+ /**
+ * Pointer to the Asset Manager instance for the application. The application
+ * uses this to access binary assets bundled inside its own .apk file.
+ */
+ AAssetManager* assetManager;
+
+ /**
+ * Available starting with Honeycomb: path to the directory containing
+ * the application's OBB files (if any). If the app doesn't have any
+ * OBB files, this directory may not exist.
+ */
+ const char* obbPath;
+} ANativeActivity;
+
+/**
+ * These are the callbacks the framework makes into a native application.
+ * All of these callbacks happen on the main thread of the application.
+ * By default, all callbacks are NULL; set to a pointer to your own function
+ * to have it called.
+ */
+typedef struct ANativeActivityCallbacks {
+ /**
+ * NativeActivity has started. See Java documentation for Activity.onStart()
+ * for more information.
+ */
+ void (*onStart)(ANativeActivity* activity);
+
+ /**
+ * NativeActivity has resumed. See Java documentation for Activity.onResume()
+ * for more information.
+ */
+ void (*onResume)(ANativeActivity* activity);
+
+ /**
+ * Framework is asking NativeActivity to save its current instance state.
+ * See Java documentation for Activity.onSaveInstanceState() for more
+ * information. The returned pointer needs to be created with malloc();
+ * the framework will call free() on it for you. You also must fill in
+ * outSize with the number of bytes in the allocation. Note that the
+ * saved state will be persisted, so it can not contain any active
+ * entities (pointers to memory, file descriptors, etc).
+ */
+ void* (*onSaveInstanceState)(ANativeActivity* activity, size_t* outSize);
+
+ /**
+ * NativeActivity has paused. See Java documentation for Activity.onPause()
+ * for more information.
+ */
+ void (*onPause)(ANativeActivity* activity);
+
+ /**
+ * NativeActivity has stopped. See Java documentation for Activity.onStop()
+ * for more information.
+ */
+ void (*onStop)(ANativeActivity* activity);
+
+ /**
+ * NativeActivity is being destroyed. See Java documentation for Activity.onDestroy()
+ * for more information.
+ */
+ void (*onDestroy)(ANativeActivity* activity);
+
+ /**
+ * Focus has changed in this NativeActivity's window. This is often used,
+ * for example, to pause a game when it loses input focus.
+ */
+ void (*onWindowFocusChanged)(ANativeActivity* activity, int hasFocus);
+
+ /**
+ * The drawing window for this native activity has been created. You
+ * can use the given native window object to start drawing.
+ */
+ void (*onNativeWindowCreated)(ANativeActivity* activity, ANativeWindow* window);
+
+ /**
+ * The drawing window for this native activity has been resized. You should
+ * retrieve the new size from the window and ensure that your rendering in
+ * it now matches.
+ */
+ void (*onNativeWindowResized)(ANativeActivity* activity, ANativeWindow* window);
+
+ /**
+ * The drawing window for this native activity needs to be redrawn. To avoid
+ * transient artifacts during screen changes (such resizing after rotation),
+ * applications should not return from this function until they have finished
+ * drawing their window in its current state.
+ */
+ void (*onNativeWindowRedrawNeeded)(ANativeActivity* activity, ANativeWindow* window);
+
+ /**
+ * The drawing window for this native activity is going to be destroyed.
+ * You MUST ensure that you do not touch the window object after returning
+ * from this function: in the common case of drawing to the window from
+ * another thread, that means the implementation of this callback must
+ * properly synchronize with the other thread to stop its drawing before
+ * returning from here.
+ */
+ void (*onNativeWindowDestroyed)(ANativeActivity* activity, ANativeWindow* window);
+
+ /**
+ * The input queue for this native activity's window has been created.
+ * You can use the given input queue to start retrieving input events.
+ */
+ void (*onInputQueueCreated)(ANativeActivity* activity, AInputQueue* queue);
+
+ /**
+ * The input queue for this native activity's window is being destroyed.
+ * You should no longer try to reference this object upon returning from this
+ * function.
+ */
+ void (*onInputQueueDestroyed)(ANativeActivity* activity, AInputQueue* queue);
+
+ /**
+ * The rectangle in the window in which content should be placed has changed.
+ */
+ void (*onContentRectChanged)(ANativeActivity* activity, const ARect* rect);
+
+ /**
+ * The current device AConfiguration has changed. The new configuration can
+ * be retrieved from assetManager.
+ */
+ void (*onConfigurationChanged)(ANativeActivity* activity);
+
+ /**
+ * The system is running low on memory. Use this callback to release
+ * resources you do not need, to help the system avoid killing more
+ * important processes.
+ */
+ void (*onLowMemory)(ANativeActivity* activity);
+} ANativeActivityCallbacks;
+
+/**
+ * This is the function that must be in the native code to instantiate the
+ * application's native activity. It is called with the activity instance (see
+ * above); if the code is being instantiated from a previously saved instance,
+ * the savedState will be non-NULL and point to the saved data. You must make
+ * any copy of this data you need -- it will be released after you return from
+ * this function.
+ */
+typedef void ANativeActivity_createFunc(ANativeActivity* activity,
+ void* savedState, size_t savedStateSize);
+
+/**
+ * The name of the function that NativeInstance looks for when launching its
+ * native code. This is the default function that is used, you can specify
+ * "android.app.func_name" string meta-data in your manifest to use a different
+ * function.
+ */
+extern ANativeActivity_createFunc ANativeActivity_onCreate;
+
+/**
+ * Finish the given activity. Its finish() method will be called, causing it
+ * to be stopped and destroyed. Note that this method can be called from
+ * *any* thread; it will send a message to the main thread of the process
+ * where the Java finish call will take place.
+ */
+void ANativeActivity_finish(ANativeActivity* activity);
+
+/**
+ * Change the window format of the given activity. Calls getWindow().setFormat()
+ * of the given activity. Note that this method can be called from
+ * *any* thread; it will send a message to the main thread of the process
+ * where the Java finish call will take place.
+ */
+void ANativeActivity_setWindowFormat(ANativeActivity* activity, int32_t format);
+
+/**
+ * Change the window flags of the given activity. Calls getWindow().setFlags()
+ * of the given activity. Note that this method can be called from
+ * *any* thread; it will send a message to the main thread of the process
+ * where the Java finish call will take place. See window.h for flag constants.
+ */
+void ANativeActivity_setWindowFlags(ANativeActivity* activity,
+ uint32_t addFlags, uint32_t removeFlags);
+
+/**
+ * Flags for ANativeActivity_showSoftInput; see the Java InputMethodManager
+ * API for documentation.
+ */
+enum {
+ /**
+ * Implicit request to show the input window, not as the result
+ * of a direct request by the user.
+ */
+ ANATIVEACTIVITY_SHOW_SOFT_INPUT_IMPLICIT = 0x0001,
+
+ /**
+ * The user has forced the input method open (such as by
+ * long-pressing menu) so it should not be closed until they
+ * explicitly do so.
+ */
+ ANATIVEACTIVITY_SHOW_SOFT_INPUT_FORCED = 0x0002,
+};
+
+/**
+ * Show the IME while in the given activity. Calls InputMethodManager.showSoftInput()
+ * for the given activity. Note that this method can be called from
+ * *any* thread; it will send a message to the main thread of the process
+ * where the Java finish call will take place.
+ */
+void ANativeActivity_showSoftInput(ANativeActivity* activity, uint32_t flags);
+
+/**
+ * Flags for ANativeActivity_hideSoftInput; see the Java InputMethodManager
+ * API for documentation.
+ */
+enum {
+ /**
+ * The soft input window should only be hidden if it was not
+ * explicitly shown by the user.
+ */
+ ANATIVEACTIVITY_HIDE_SOFT_INPUT_IMPLICIT_ONLY = 0x0001,
+ /**
+ * The soft input window should normally be hidden, unless it was
+ * originally shown with {@link ANATIVEACTIVITY_SHOW_SOFT_INPUT_FORCED}.
+ */
+ ANATIVEACTIVITY_HIDE_SOFT_INPUT_NOT_ALWAYS = 0x0002,
+};
+
+/**
+ * Hide the IME while in the given activity. Calls InputMethodManager.hideSoftInput()
+ * for the given activity. Note that this method can be called from
+ * *any* thread; it will send a message to the main thread of the process
+ * where the Java finish call will take place.
+ */
+void ANativeActivity_hideSoftInput(ANativeActivity* activity, uint32_t flags);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // ANDROID_NATIVE_ACTIVITY_H
+
+/** @} */
diff --git a/phonelibs/android_frameworks_native/include/android/native_window.h b/phonelibs/android_frameworks_native/include/android/native_window.h
new file mode 100644
index 000000000..cf07f1afa
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/android/native_window.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ */
+
+/**
+ * @addtogroup NativeActivity Native Activity
+ * @{
+ */
+
+/**
+ * @file native_window.h
+ */
+
+#ifndef ANDROID_NATIVE_WINDOW_H
+#define ANDROID_NATIVE_WINDOW_H
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Pixel formats that a window can use.
+ */
+enum {
+ /** Red: 8 bits, Green: 8 bits, Blue: 8 bits, Alpha: 8 bits. **/
+ WINDOW_FORMAT_RGBA_8888 = 1,
+ /** Red: 8 bits, Green: 8 bits, Blue: 8 bits, Unused: 8 bits. **/
+ WINDOW_FORMAT_RGBX_8888 = 2,
+ /** Red: 5 bits, Green: 6 bits, Blue: 5 bits. **/
+ WINDOW_FORMAT_RGB_565 = 4,
+};
+
+struct ANativeWindow;
+/**
+ * {@link ANativeWindow} is opaque type that provides access to a native window.
+ *
+ * A pointer can be obtained using ANativeWindow_fromSurface().
+ */
+typedef struct ANativeWindow ANativeWindow;
+
+/**
+ * {@link ANativeWindow} is a struct that represents a windows buffer.
+ *
+ * A pointer can be obtained using ANativeWindow_lock().
+ */
+typedef struct ANativeWindow_Buffer {
+ // The number of pixels that are show horizontally.
+ int32_t width;
+
+ // The number of pixels that are shown vertically.
+ int32_t height;
+
+ // The number of *pixels* that a line in the buffer takes in
+ // memory. This may be >= width.
+ int32_t stride;
+
+ // The format of the buffer. One of WINDOW_FORMAT_*
+ int32_t format;
+
+ // The actual bits.
+ void* bits;
+
+ // Do not touch.
+ uint32_t reserved[6];
+} ANativeWindow_Buffer;
+
+/**
+ * Acquire a reference on the given ANativeWindow object. This prevents the object
+ * from being deleted until the reference is removed.
+ */
+void ANativeWindow_acquire(ANativeWindow* window);
+
+/**
+ * Remove a reference that was previously acquired with ANativeWindow_acquire().
+ */
+void ANativeWindow_release(ANativeWindow* window);
+
+/**
+ * Return the current width in pixels of the window surface. Returns a
+ * negative value on error.
+ */
+int32_t ANativeWindow_getWidth(ANativeWindow* window);
+
+/**
+ * Return the current height in pixels of the window surface. Returns a
+ * negative value on error.
+ */
+int32_t ANativeWindow_getHeight(ANativeWindow* window);
+
+/**
+ * Return the current pixel format of the window surface. Returns a
+ * negative value on error.
+ */
+int32_t ANativeWindow_getFormat(ANativeWindow* window);
+
+/**
+ * Change the format and size of the window buffers.
+ *
+ * The width and height control the number of pixels in the buffers, not the
+ * dimensions of the window on screen. If these are different than the
+ * window's physical size, then it buffer will be scaled to match that size
+ * when compositing it to the screen.
+ *
+ * For all of these parameters, if 0 is supplied then the window's base
+ * value will come back in force.
+ *
+ * width and height must be either both zero or both non-zero.
+ *
+ */
+int32_t ANativeWindow_setBuffersGeometry(ANativeWindow* window,
+ int32_t width, int32_t height, int32_t format);
+
+/**
+ * Lock the window's next drawing surface for writing.
+ * inOutDirtyBounds is used as an in/out parameter, upon entering the
+ * function, it contains the dirty region, that is, the region the caller
+ * intends to redraw. When the function returns, inOutDirtyBounds is updated
+ * with the actual area the caller needs to redraw -- this region is often
+ * extended by ANativeWindow_lock.
+ */
+int32_t ANativeWindow_lock(ANativeWindow* window, ANativeWindow_Buffer* outBuffer,
+ ARect* inOutDirtyBounds);
+
+/**
+ * Unlock the window's drawing surface after previously locking it,
+ * posting the new buffer to the display.
+ */
+int32_t ANativeWindow_unlockAndPost(ANativeWindow* window);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // ANDROID_NATIVE_WINDOW_H
+
+/** @} */
diff --git a/phonelibs/android_frameworks_native/include/android/native_window_jni.h b/phonelibs/android_frameworks_native/include/android/native_window_jni.h
new file mode 100644
index 000000000..60a36c3f2
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/android/native_window_jni.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ */
+
+/**
+ * @addtogroup NativeActivity Native Activity
+ * @{
+ */
+
+/**
+ * @file native_window_jni.h
+ */
+
+#ifndef ANDROID_NATIVE_WINDOW_JNI_H
+#define ANDROID_NATIVE_WINDOW_JNI_H
+
+#include
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Return the ANativeWindow associated with a Java Surface object,
+ * for interacting with it through native code. This acquires a reference
+ * on the ANativeWindow that is returned; be sure to use ANativeWindow_release()
+ * when done with it so that it doesn't leak.
+ */
+ANativeWindow* ANativeWindow_fromSurface(JNIEnv* env, jobject surface);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // ANDROID_NATIVE_WINDOW_H
+
+/** @} */
diff --git a/phonelibs/android_frameworks_native/include/android/obb.h b/phonelibs/android_frameworks_native/include/android/obb.h
new file mode 100644
index 000000000..4c6d9d7ba
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/android/obb.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ */
+
+/**
+ * @addtogroup Storage
+ * @{
+ */
+
+/**
+ * @file obb.h
+ */
+
+#ifndef ANDROID_OBB_H
+#define ANDROID_OBB_H
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct AObbInfo;
+/** {@link AObbInfo} is an opaque type representing information for obb storage. */
+typedef struct AObbInfo AObbInfo;
+
+/** Flag for an obb file, returned by AObbInfo_getFlags(). */
+enum {
+ /** overlay */
+ AOBBINFO_OVERLAY = 0x0001,
+};
+
+/**
+ * Scan an OBB and get information about it.
+ */
+AObbInfo* AObbScanner_getObbInfo(const char* filename);
+
+/**
+ * Destroy the AObbInfo object. You must call this when finished with the object.
+ */
+void AObbInfo_delete(AObbInfo* obbInfo);
+
+/**
+ * Get the package name for the OBB.
+ */
+const char* AObbInfo_getPackageName(AObbInfo* obbInfo);
+
+/**
+ * Get the version of an OBB file.
+ */
+int32_t AObbInfo_getVersion(AObbInfo* obbInfo);
+
+/**
+ * Get the flags of an OBB file.
+ */
+int32_t AObbInfo_getFlags(AObbInfo* obbInfo);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // ANDROID_OBB_H
+
+/** @} */
diff --git a/phonelibs/android_frameworks_native/include/android/rect.h b/phonelibs/android_frameworks_native/include/android/rect.h
new file mode 100644
index 000000000..80741c044
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/android/rect.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ */
+
+/**
+ * @addtogroup NativeActivity Native Activity
+ * @{
+ */
+
+/**
+ * @file rect.h
+ */
+
+#ifndef ANDROID_RECT_H
+#define ANDROID_RECT_H
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * {@link ARect} is a struct that represents a rectangular window area.
+ *
+ * It is used with {@link
+ * ANativeActivityCallbacks::onContentRectChanged} event callback and
+ * ANativeWindow_lock() function.
+ */
+typedef struct ARect {
+#ifdef __cplusplus
+ typedef int32_t value_type;
+#endif
+ /** left position */
+ int32_t left;
+ /** top position */
+ int32_t top;
+ /** left position */
+ int32_t right;
+ /** bottom position */
+ int32_t bottom;
+} ARect;
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // ANDROID_RECT_H
+
+/** @} */
diff --git a/phonelibs/android_frameworks_native/include/android/sensor.h b/phonelibs/android_frameworks_native/include/android/sensor.h
new file mode 100644
index 000000000..73928ea76
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/android/sensor.h
@@ -0,0 +1,475 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ */
+
+/**
+ * @addtogroup Sensor
+ * @{
+ */
+
+/**
+ * @file sensor.h
+ */
+
+#ifndef ANDROID_SENSOR_H
+#define ANDROID_SENSOR_H
+
+/******************************************************************
+ *
+ * IMPORTANT NOTICE:
+ *
+ * This file is part of Android's set of stable system headers
+ * exposed by the Android NDK (Native Development Kit).
+ *
+ * Third-party source AND binary code relies on the definitions
+ * here to be FROZEN ON ALL UPCOMING PLATFORM RELEASES.
+ *
+ * - DO NOT MODIFY ENUMS (EXCEPT IF YOU ADD NEW 32-BIT VALUES)
+ * - DO NOT MODIFY CONSTANTS OR FUNCTIONAL MACROS
+ * - DO NOT CHANGE THE SIGNATURE OF FUNCTIONS IN ANY WAY
+ * - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES
+ */
+
+/**
+ * Structures and functions to receive and process sensor events in
+ * native code.
+ *
+ */
+
+#include
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * Sensor types.
+ * (keep in sync with hardware/sensor.h)
+ */
+enum {
+ /**
+ * {@link ASENSOR_TYPE_ACCELEROMETER}
+ * reporting-mode: continuous
+ *
+ * All values are in SI units (m/s^2) and measure the acceleration of the
+ * device minus the force of gravity.
+ */
+ ASENSOR_TYPE_ACCELEROMETER = 1,
+ /**
+ * {@link ASENSOR_TYPE_MAGNETIC_FIELD}
+ * reporting-mode: continuous
+ *
+ * All values are in micro-Tesla (uT) and measure the geomagnetic
+ * field in the X, Y and Z axis.
+ */
+ ASENSOR_TYPE_MAGNETIC_FIELD = 2,
+ /**
+ * {@link ASENSOR_TYPE_GYROSCOPE}
+ * reporting-mode: continuous
+ *
+ * All values are in radians/second and measure the rate of rotation
+ * around the X, Y and Z axis.
+ */
+ ASENSOR_TYPE_GYROSCOPE = 4,
+ /**
+ * {@link ASENSOR_TYPE_LIGHT}
+ * reporting-mode: on-change
+ *
+ * The light sensor value is returned in SI lux units.
+ */
+ ASENSOR_TYPE_LIGHT = 5,
+ /**
+ * {@link ASENSOR_TYPE_PROXIMITY}
+ * reporting-mode: on-change
+ *
+ * The proximity sensor which turns the screen off and back on during calls is the
+ * wake-up proximity sensor. Implement wake-up proximity sensor before implementing
+ * a non wake-up proximity sensor. For the wake-up proximity sensor set the flag
+ * SENSOR_FLAG_WAKE_UP.
+ * The value corresponds to the distance to the nearest object in centimeters.
+ */
+ ASENSOR_TYPE_PROXIMITY = 8
+};
+
+/**
+ * Sensor accuracy measure.
+ */
+enum {
+ /** no contact */
+ ASENSOR_STATUS_NO_CONTACT = -1,
+ /** unreliable */
+ ASENSOR_STATUS_UNRELIABLE = 0,
+ /** low accuracy */
+ ASENSOR_STATUS_ACCURACY_LOW = 1,
+ /** medium accuracy */
+ ASENSOR_STATUS_ACCURACY_MEDIUM = 2,
+ /** high accuracy */
+ ASENSOR_STATUS_ACCURACY_HIGH = 3
+};
+
+/**
+ * Sensor Reporting Modes.
+ */
+enum {
+ /** continuous reporting */
+ AREPORTING_MODE_CONTINUOUS = 0,
+ /** reporting on change */
+ AREPORTING_MODE_ON_CHANGE = 1,
+ /** on shot reporting */
+ AREPORTING_MODE_ONE_SHOT = 2,
+ /** special trigger reporting */
+ AREPORTING_MODE_SPECIAL_TRIGGER = 3
+};
+
+/*
+ * A few useful constants
+ */
+
+/** Earth's gravity in m/s^2 */
+#define ASENSOR_STANDARD_GRAVITY (9.80665f)
+/** Maximum magnetic field on Earth's surface in uT */
+#define ASENSOR_MAGNETIC_FIELD_EARTH_MAX (60.0f)
+/** Minimum magnetic field on Earth's surface in uT*/
+#define ASENSOR_MAGNETIC_FIELD_EARTH_MIN (30.0f)
+
+/**
+ * A sensor event.
+ */
+
+/* NOTE: Must match hardware/sensors.h */
+typedef struct ASensorVector {
+ union {
+ float v[3];
+ struct {
+ float x;
+ float y;
+ float z;
+ };
+ struct {
+ float azimuth;
+ float pitch;
+ float roll;
+ };
+ };
+ int8_t status;
+ uint8_t reserved[3];
+} ASensorVector;
+
+typedef struct AMetaDataEvent {
+ int32_t what;
+ int32_t sensor;
+} AMetaDataEvent;
+
+typedef struct AUncalibratedEvent {
+ union {
+ float uncalib[3];
+ struct {
+ float x_uncalib;
+ float y_uncalib;
+ float z_uncalib;
+ };
+ };
+ union {
+ float bias[3];
+ struct {
+ float x_bias;
+ float y_bias;
+ float z_bias;
+ };
+ };
+} AUncalibratedEvent;
+
+typedef struct AHeartRateEvent {
+ float bpm;
+ int8_t status;
+} AHeartRateEvent;
+
+/* NOTE: Must match hardware/sensors.h */
+typedef struct ASensorEvent {
+ int32_t version; /* sizeof(struct ASensorEvent) */
+ int32_t sensor;
+ int32_t type;
+ int32_t reserved0;
+ int64_t timestamp;
+ union {
+ union {
+ float data[16];
+ ASensorVector vector;
+ ASensorVector acceleration;
+ ASensorVector magnetic;
+ float temperature;
+ float distance;
+ float light;
+ float pressure;
+ float relative_humidity;
+ AUncalibratedEvent uncalibrated_gyro;
+ AUncalibratedEvent uncalibrated_magnetic;
+ AMetaDataEvent meta_data;
+ AHeartRateEvent heart_rate;
+ };
+ union {
+ uint64_t data[8];
+ uint64_t step_counter;
+ } u64;
+ };
+
+ uint32_t flags;
+ int32_t reserved1[3];
+} ASensorEvent;
+
+struct ASensorManager;
+/**
+ * {@link ASensorManager} is an opaque type to manage sensors and
+ * events queues.
+ *
+ * {@link ASensorManager} is a singleton that can be obtained using
+ * ASensorManager_getInstance().
+ *
+ * This file provides a set of functions that uses {@link
+ * ASensorManager} to access and list hardware sensors, and
+ * create and destroy event queues:
+ * - ASensorManager_getSensorList()
+ * - ASensorManager_getDefaultSensor()
+ * - ASensorManager_getDefaultSensorEx()
+ * - ASensorManager_createEventQueue()
+ * - ASensorManager_destroyEventQueue()
+ */
+typedef struct ASensorManager ASensorManager;
+
+
+struct ASensorEventQueue;
+/**
+ * {@link ASensorEventQueue} is an opaque type that provides access to
+ * {@link ASensorEvent} from hardware sensors.
+ *
+ * A new {@link ASensorEventQueue} can be obtained using ASensorManager_createEventQueue().
+ *
+ * This file provides a set of functions to enable and disable
+ * sensors, check and get events, and set event rates on a {@link
+ * ASensorEventQueue}.
+ * - ASensorEventQueue_enableSensor()
+ * - ASensorEventQueue_disableSensor()
+ * - ASensorEventQueue_hasEvents()
+ * - ASensorEventQueue_getEvents()
+ * - ASensorEventQueue_setEventRate()
+ */
+typedef struct ASensorEventQueue ASensorEventQueue;
+
+struct ASensor;
+/**
+ * {@link ASensor} is an opaque type that provides information about
+ * an hardware sensors.
+ *
+ * A {@link ASensor} pointer can be obtained using
+ * ASensorManager_getDefaultSensor(),
+ * ASensorManager_getDefaultSensorEx() or from a {@link ASensorList}.
+ *
+ * This file provides a set of functions to access properties of a
+ * {@link ASensor}:
+ * - ASensor_getName()
+ * - ASensor_getVendor()
+ * - ASensor_getType()
+ * - ASensor_getResolution()
+ * - ASensor_getMinDelay()
+ * - ASensor_getFifoMaxEventCount()
+ * - ASensor_getFifoReservedEventCount()
+ * - ASensor_getStringType()
+ * - ASensor_getReportingMode()
+ * - ASensor_isWakeUpSensor()
+ */
+typedef struct ASensor ASensor;
+/**
+ * {@link ASensorRef} is a type for constant pointers to {@link ASensor}.
+ *
+ * This is used to define entry in {@link ASensorList} arrays.
+ */
+typedef ASensor const* ASensorRef;
+/**
+ * {@link ASensorList} is an array of reference to {@link ASensor}.
+ *
+ * A {@link ASensorList} can be initialized using ASensorManager_getSensorList().
+ */
+typedef ASensorRef const* ASensorList;
+
+/*****************************************************************************/
+
+/**
+ * Get a reference to the sensor manager. ASensorManager is a singleton
+ * per package as different packages may have access to different sensors.
+ *
+ * Deprecated: Use ASensorManager_getInstanceForPackage(const char*) instead.
+ *
+ * Example:
+ *
+ * ASensorManager* sensorManager = ASensorManager_getInstance();
+ *
+ */
+__attribute__ ((deprecated)) ASensorManager* ASensorManager_getInstance();
+
+/*
+ * Get a reference to the sensor manager. ASensorManager is a singleton
+ * per package as different packages may have access to different sensors.
+ *
+ * Example:
+ *
+ * ASensorManager* sensorManager = ASensorManager_getInstanceForPackage("foo.bar.baz");
+ *
+ */
+ASensorManager* ASensorManager_getInstanceForPackage(const char* packageName);
+
+/**
+ * Returns the list of available sensors.
+ */
+int ASensorManager_getSensorList(ASensorManager* manager, ASensorList* list);
+
+/**
+ * Returns the default sensor for the given type, or NULL if no sensor
+ * of that type exists.
+ */
+ASensor const* ASensorManager_getDefaultSensor(ASensorManager* manager, int type);
+
+/**
+ * Returns the default sensor with the given type and wakeUp properties or NULL if no sensor
+ * of this type and wakeUp properties exists.
+ */
+ASensor const* ASensorManager_getDefaultSensorEx(ASensorManager* manager, int type,
+ bool wakeUp);
+
+/**
+ * Creates a new sensor event queue and associate it with a looper.
+ *
+ * "ident" is a identifier for the events that will be returned when
+ * calling ALooper_pollOnce(). The identifier must be >= 0, or
+ * ALOOPER_POLL_CALLBACK if providing a non-NULL callback.
+ */
+ASensorEventQueue* ASensorManager_createEventQueue(ASensorManager* manager,
+ ALooper* looper, int ident, ALooper_callbackFunc callback, void* data);
+
+/**
+ * Destroys the event queue and free all resources associated to it.
+ */
+int ASensorManager_destroyEventQueue(ASensorManager* manager, ASensorEventQueue* queue);
+
+
+/*****************************************************************************/
+
+/**
+ * Enable the selected sensor. Returns a negative error code on failure.
+ */
+int ASensorEventQueue_enableSensor(ASensorEventQueue* queue, ASensor const* sensor);
+
+/**
+ * Disable the selected sensor. Returns a negative error code on failure.
+ */
+int ASensorEventQueue_disableSensor(ASensorEventQueue* queue, ASensor const* sensor);
+
+/**
+ * Sets the delivery rate of events in microseconds for the given sensor.
+ * Note that this is a hint only, generally event will arrive at a higher
+ * rate. It is an error to set a rate inferior to the value returned by
+ * ASensor_getMinDelay().
+ * Returns a negative error code on failure.
+ */
+int ASensorEventQueue_setEventRate(ASensorEventQueue* queue, ASensor const* sensor, int32_t usec);
+
+/**
+ * Returns true if there are one or more events available in the
+ * sensor queue. Returns 1 if the queue has events; 0 if
+ * it does not have events; and a negative value if there is an error.
+ */
+int ASensorEventQueue_hasEvents(ASensorEventQueue* queue);
+
+/**
+ * Returns the next available events from the queue. Returns a negative
+ * value if no events are available or an error has occurred, otherwise
+ * the number of events returned.
+ *
+ * Examples:
+ * ASensorEvent event;
+ * ssize_t numEvent = ASensorEventQueue_getEvents(queue, &event, 1);
+ *
+ * ASensorEvent eventBuffer[8];
+ * ssize_t numEvent = ASensorEventQueue_getEvents(queue, eventBuffer, 8);
+ *
+ */
+ssize_t ASensorEventQueue_getEvents(ASensorEventQueue* queue,
+ ASensorEvent* events, size_t count);
+
+
+/*****************************************************************************/
+
+/**
+ * Returns this sensor's name (non localized)
+ */
+const char* ASensor_getName(ASensor const* sensor);
+
+/**
+ * Returns this sensor's vendor's name (non localized)
+ */
+const char* ASensor_getVendor(ASensor const* sensor);
+
+/**
+ * Return this sensor's type
+ */
+int ASensor_getType(ASensor const* sensor);
+
+/**
+ * Returns this sensors's resolution
+ */
+float ASensor_getResolution(ASensor const* sensor);
+
+/**
+ * Returns the minimum delay allowed between events in microseconds.
+ * A value of zero means that this sensor doesn't report events at a
+ * constant rate, but rather only when a new data is available.
+ */
+int ASensor_getMinDelay(ASensor const* sensor);
+
+/**
+ * Returns the maximum size of batches for this sensor. Batches will often be
+ * smaller, as the hardware fifo might be used for other sensors.
+ */
+int ASensor_getFifoMaxEventCount(ASensor const* sensor);
+
+/**
+ * Returns the hardware batch fifo size reserved to this sensor.
+ */
+int ASensor_getFifoReservedEventCount(ASensor const* sensor);
+
+/**
+ * Returns this sensor's string type.
+ */
+const char* ASensor_getStringType(ASensor const* sensor);
+
+/**
+ * Returns the reporting mode for this sensor. One of AREPORTING_MODE_* constants.
+ */
+int ASensor_getReportingMode(ASensor const* sensor);
+
+/**
+ * Returns true if this is a wake up sensor, false otherwise.
+ */
+bool ASensor_isWakeUpSensor(ASensor const* sensor);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // ANDROID_SENSOR_H
+
+/** @} */
diff --git a/phonelibs/android_frameworks_native/include/android/storage_manager.h b/phonelibs/android_frameworks_native/include/android/storage_manager.h
new file mode 100644
index 000000000..7f2ee08d6
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/android/storage_manager.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ */
+
+/**
+ * @addtogroup Storage
+ * @{
+ */
+
+/**
+ * @file storage_manager.h
+ */
+
+#ifndef ANDROID_STORAGE_MANAGER_H
+#define ANDROID_STORAGE_MANAGER_H
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct AStorageManager;
+/**
+ * {@link AStorageManager} manages application OBB storage, a pointer
+ * can be obtained with AStorageManager_new().
+ */
+typedef struct AStorageManager AStorageManager;
+
+/**
+ * The different states of a OBB storage passed to AStorageManager_obbCallbackFunc().
+ */
+enum {
+ /**
+ * The OBB container is now mounted and ready for use. Can be returned
+ * as the status for callbacks made during asynchronous OBB actions.
+ */
+ AOBB_STATE_MOUNTED = 1,
+
+ /**
+ * The OBB container is now unmounted and not usable. Can be returned
+ * as the status for callbacks made during asynchronous OBB actions.
+ */
+ AOBB_STATE_UNMOUNTED = 2,
+
+ /**
+ * There was an internal system error encountered while trying to
+ * mount the OBB. Can be returned as the status for callbacks made
+ * during asynchronous OBB actions.
+ */
+ AOBB_STATE_ERROR_INTERNAL = 20,
+
+ /**
+ * The OBB could not be mounted by the system. Can be returned as the
+ * status for callbacks made during asynchronous OBB actions.
+ */
+ AOBB_STATE_ERROR_COULD_NOT_MOUNT = 21,
+
+ /**
+ * The OBB could not be unmounted. This most likely indicates that a
+ * file is in use on the OBB. Can be returned as the status for
+ * callbacks made during asynchronous OBB actions.
+ */
+ AOBB_STATE_ERROR_COULD_NOT_UNMOUNT = 22,
+
+ /**
+ * A call was made to unmount the OBB when it was not mounted. Can be
+ * returned as the status for callbacks made during asynchronous OBB
+ * actions.
+ */
+ AOBB_STATE_ERROR_NOT_MOUNTED = 23,
+
+ /**
+ * The OBB has already been mounted. Can be returned as the status for
+ * callbacks made during asynchronous OBB actions.
+ */
+ AOBB_STATE_ERROR_ALREADY_MOUNTED = 24,
+
+ /**
+ * The current application does not have permission to use this OBB.
+ * This could be because the OBB indicates it's owned by a different
+ * package. Can be returned as the status for callbacks made during
+ * asynchronous OBB actions.
+ */
+ AOBB_STATE_ERROR_PERMISSION_DENIED = 25,
+};
+
+/**
+ * Obtains a new instance of AStorageManager.
+ */
+AStorageManager* AStorageManager_new();
+
+/**
+ * Release AStorageManager instance.
+ */
+void AStorageManager_delete(AStorageManager* mgr);
+
+/**
+ * Callback function for asynchronous calls made on OBB files.
+ *
+ * "state" is one of the following constants:
+ * - {@link AOBB_STATE_MOUNTED}
+ * - {@link AOBB_STATE_UNMOUNTED}
+ * - {@link AOBB_STATE_ERROR_INTERNAL}
+ * - {@link AOBB_STATE_ERROR_COULD_NOT_MOUNT}
+ * - {@link AOBB_STATE_ERROR_COULD_NOT_UNMOUNT}
+ * - {@link AOBB_STATE_ERROR_NOT_MOUNTED}
+ * - {@link AOBB_STATE_ERROR_ALREADY_MOUNTED}
+ * - {@link AOBB_STATE_ERROR_PERMISSION_DENIED}
+ */
+typedef void (*AStorageManager_obbCallbackFunc)(const char* filename, const int32_t state, void* data);
+
+/**
+ * Attempts to mount an OBB file. This is an asynchronous operation.
+ */
+void AStorageManager_mountObb(AStorageManager* mgr, const char* filename, const char* key,
+ AStorageManager_obbCallbackFunc cb, void* data);
+
+/**
+ * Attempts to unmount an OBB file. This is an asynchronous operation.
+ */
+void AStorageManager_unmountObb(AStorageManager* mgr, const char* filename, const int force,
+ AStorageManager_obbCallbackFunc cb, void* data);
+
+/**
+ * Check whether an OBB is mounted.
+ */
+int AStorageManager_isObbMounted(AStorageManager* mgr, const char* filename);
+
+/**
+ * Get the mounted path for an OBB.
+ */
+const char* AStorageManager_getMountedObbPath(AStorageManager* mgr, const char* filename);
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // ANDROID_STORAGE_MANAGER_H
+
+/** @} */
diff --git a/phonelibs/android_frameworks_native/include/android/trace.h b/phonelibs/android_frameworks_native/include/android/trace.h
new file mode 100644
index 000000000..e42e33410
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/android/trace.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * 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 ANDROID_NATIVE_TRACE_H
+#define ANDROID_NATIVE_TRACE_H
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Returns true if tracing is enabled. Use this signal to avoid expensive computation only necessary
+ * when tracing is enabled.
+ */
+bool ATrace_isEnabled();
+
+/**
+ * Writes a tracing message to indicate that the given section of code has begun. This call must be
+ * followed by a corresponding call to endSection() on the same thread.
+ *
+ * Note: At this time the vertical bar character '|' and newline character '\n' are used internally
+ * by the tracing mechanism. If sectionName contains these characters they will be replaced with a
+ * space character in the trace.
+ */
+void ATrace_beginSection(const char* sectionName);
+
+/**
+ * Writes a tracing message to indicate that a given section of code has ended. This call must be
+ * preceeded by a corresponding call to beginSection(char*) on the same thread. Calling this method
+ * will mark the end of the most recently begun section of code, so care must be taken to ensure
+ * that beginSection / endSection pairs are properly nested and called from the same thread.
+ */
+void ATrace_endSection();
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // ANDROID_NATIVE_TRACE_H
diff --git a/phonelibs/android_frameworks_native/include/android/window.h b/phonelibs/android_frameworks_native/include/android/window.h
new file mode 100644
index 000000000..436bf3a83
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/android/window.h
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ */
+
+/**
+ * @addtogroup NativeActivity Native Activity
+ * @{
+ */
+
+/**
+ * @file window.h
+ */
+
+#ifndef ANDROID_WINDOW_H
+#define ANDROID_WINDOW_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Window flags, as per the Java API at android.view.WindowManager.LayoutParams.
+ */
+enum {
+ /**
+ * As long as this window is visible to the user, allow the lock
+ * screen to activate while the screen is on. This can be used
+ * independently, or in combination with {@link
+ * AWINDOW_FLAG_KEEP_SCREEN_ON} and/or {@link
+ * AWINDOW_FLAG_SHOW_WHEN_LOCKED}
+ */
+ AWINDOW_FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001,
+ /** Everything behind this window will be dimmed. */
+ AWINDOW_FLAG_DIM_BEHIND = 0x00000002,
+ /**
+ * Blur everything behind this window.
+ * @deprecated Blurring is no longer supported.
+ */
+ AWINDOW_FLAG_BLUR_BEHIND = 0x00000004,
+ /**
+ * This window won't ever get key input focus, so the
+ * user can not send key or other button events to it. Those will
+ * instead go to whatever focusable window is behind it. This flag
+ * will also enable {@link AWINDOW_FLAG_NOT_TOUCH_MODAL} whether or not that
+ * is explicitly set.
+ *
+ * Setting this flag also implies that the window will not need to
+ * interact with
+ * a soft input method, so it will be Z-ordered and positioned
+ * independently of any active input method (typically this means it
+ * gets Z-ordered on top of the input method, so it can use the full
+ * screen for its content and cover the input method if needed. You
+ * can use {@link AWINDOW_FLAG_ALT_FOCUSABLE_IM} to modify this behavior.
+ */
+ AWINDOW_FLAG_NOT_FOCUSABLE = 0x00000008,
+ /** this window can never receive touch events. */
+ AWINDOW_FLAG_NOT_TOUCHABLE = 0x00000010,
+ /**
+ * Even when this window is focusable (its
+ * {@link AWINDOW_FLAG_NOT_FOCUSABLE} is not set), allow any pointer events
+ * outside of the window to be sent to the windows behind it. Otherwise
+ * it will consume all pointer events itself, regardless of whether they
+ * are inside of the window.
+ */
+ AWINDOW_FLAG_NOT_TOUCH_MODAL = 0x00000020,
+ /**
+ * When set, if the device is asleep when the touch
+ * screen is pressed, you will receive this first touch event. Usually
+ * the first touch event is consumed by the system since the user can
+ * not see what they are pressing on.
+ *
+ * @deprecated This flag has no effect.
+ */
+ AWINDOW_FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040,
+ /**
+ * As long as this window is visible to the user, keep
+ * the device's screen turned on and bright.
+ */
+ AWINDOW_FLAG_KEEP_SCREEN_ON = 0x00000080,
+ /**
+ * Place the window within the entire screen, ignoring
+ * decorations around the border (such as the status bar). The
+ * window must correctly position its contents to take the screen
+ * decoration into account.
+ */
+ AWINDOW_FLAG_LAYOUT_IN_SCREEN = 0x00000100,
+ /** allow window to extend outside of the screen. */
+ AWINDOW_FLAG_LAYOUT_NO_LIMITS = 0x00000200,
+ /**
+ * Hide all screen decorations (such as the status
+ * bar) while this window is displayed. This allows the window to
+ * use the entire display space for itself -- the status bar will
+ * be hidden when an app window with this flag set is on the top
+ * layer. A fullscreen window will ignore a value of {@link
+ * AWINDOW_SOFT_INPUT_ADJUST_RESIZE}; the window will stay
+ * fullscreen and will not resize.
+ */
+ AWINDOW_FLAG_FULLSCREEN = 0x00000400,
+ /**
+ * Override {@link AWINDOW_FLAG_FULLSCREEN} and force the
+ * screen decorations (such as the status bar) to be shown.
+ */
+ AWINDOW_FLAG_FORCE_NOT_FULLSCREEN = 0x00000800,
+ /**
+ * Turn on dithering when compositing this window to
+ * the screen.
+ * @deprecated This flag is no longer used.
+ */
+ AWINDOW_FLAG_DITHER = 0x00001000,
+ /**
+ * Treat the content of the window as secure, preventing
+ * it from appearing in screenshots or from being viewed on non-secure
+ * displays.
+ */
+ AWINDOW_FLAG_SECURE = 0x00002000,
+ /**
+ * A special mode where the layout parameters are used
+ * to perform scaling of the surface when it is composited to the
+ * screen.
+ */
+ AWINDOW_FLAG_SCALED = 0x00004000,
+ /**
+ * Intended for windows that will often be used when the user is
+ * holding the screen against their face, it will aggressively
+ * filter the event stream to prevent unintended presses in this
+ * situation that may not be desired for a particular window, when
+ * such an event stream is detected, the application will receive
+ * a {@link AMOTION_EVENT_ACTION_CANCEL} to indicate this so
+ * applications can handle this accordingly by taking no action on
+ * the event until the finger is released.
+ */
+ AWINDOW_FLAG_IGNORE_CHEEK_PRESSES = 0x00008000,
+ /**
+ * A special option only for use in combination with
+ * {@link AWINDOW_FLAG_LAYOUT_IN_SCREEN}. When requesting layout in the
+ * screen your window may appear on top of or behind screen decorations
+ * such as the status bar. By also including this flag, the window
+ * manager will report the inset rectangle needed to ensure your
+ * content is not covered by screen decorations.
+ */
+ AWINDOW_FLAG_LAYOUT_INSET_DECOR = 0x00010000,
+ /**
+ * Invert the state of {@link AWINDOW_FLAG_NOT_FOCUSABLE} with
+ * respect to how this window interacts with the current method.
+ * That is, if FLAG_NOT_FOCUSABLE is set and this flag is set,
+ * then the window will behave as if it needs to interact with the
+ * input method and thus be placed behind/away from it; if {@link
+ * AWINDOW_FLAG_NOT_FOCUSABLE} is not set and this flag is set,
+ * then the window will behave as if it doesn't need to interact
+ * with the input method and can be placed to use more space and
+ * cover the input method.
+ */
+ AWINDOW_FLAG_ALT_FOCUSABLE_IM = 0x00020000,
+ /**
+ * If you have set {@link AWINDOW_FLAG_NOT_TOUCH_MODAL}, you
+ * can set this flag to receive a single special MotionEvent with
+ * the action
+ * {@link AMOTION_EVENT_ACTION_OUTSIDE} for
+ * touches that occur outside of your window. Note that you will not
+ * receive the full down/move/up gesture, only the location of the
+ * first down as an {@link AMOTION_EVENT_ACTION_OUTSIDE}.
+ */
+ AWINDOW_FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000,
+ /**
+ * Special flag to let windows be shown when the screen
+ * is locked. This will let application windows take precedence over
+ * key guard or any other lock screens. Can be used with
+ * {@link AWINDOW_FLAG_KEEP_SCREEN_ON} to turn screen on and display windows
+ * directly before showing the key guard window. Can be used with
+ * {@link AWINDOW_FLAG_DISMISS_KEYGUARD} to automatically fully dismisss
+ * non-secure keyguards. This flag only applies to the top-most
+ * full-screen window.
+ */
+ AWINDOW_FLAG_SHOW_WHEN_LOCKED = 0x00080000,
+ /**
+ * Ask that the system wallpaper be shown behind
+ * your window. The window surface must be translucent to be able
+ * to actually see the wallpaper behind it; this flag just ensures
+ * that the wallpaper surface will be there if this window actually
+ * has translucent regions.
+ */
+ AWINDOW_FLAG_SHOW_WALLPAPER = 0x00100000,
+ /**
+ * When set as a window is being added or made
+ * visible, once the window has been shown then the system will
+ * poke the power manager's user activity (as if the user had woken
+ * up the device) to turn the screen on.
+ */
+ AWINDOW_FLAG_TURN_SCREEN_ON = 0x00200000,
+ /**
+ * When set the window will cause the keyguard to
+ * be dismissed, only if it is not a secure lock keyguard. Because such
+ * a keyguard is not needed for security, it will never re-appear if
+ * the user navigates to another window (in contrast to
+ * {@link AWINDOW_FLAG_SHOW_WHEN_LOCKED}, which will only temporarily
+ * hide both secure and non-secure keyguards but ensure they reappear
+ * when the user moves to another UI that doesn't hide them).
+ * If the keyguard is currently active and is secure (requires an
+ * unlock pattern) than the user will still need to confirm it before
+ * seeing this window, unless {@link AWINDOW_FLAG_SHOW_WHEN_LOCKED} has
+ * also been set.
+ */
+ AWINDOW_FLAG_DISMISS_KEYGUARD = 0x00400000,
+};
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // ANDROID_WINDOW_H
+
+/** @} */
diff --git a/phonelibs/android_frameworks_native/include/batteryservice/BatteryService.h b/phonelibs/android_frameworks_native/include/batteryservice/BatteryService.h
new file mode 100644
index 000000000..3e6bfb820
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/batteryservice/BatteryService.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2015 The CyanogenMod Project
+ *
+ * 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 ANDROID_BATTERYSERVICE_H
+#define ANDROID_BATTERYSERVICE_H
+
+#include
+#include
+#include
+#include
+
+namespace android {
+
+// must be kept in sync with definitions in BatteryManager.java
+enum {
+ BATTERY_STATUS_UNKNOWN = 1, // equals BatteryManager.BATTERY_STATUS_UNKNOWN constant
+ BATTERY_STATUS_CHARGING = 2, // equals BatteryManager.BATTERY_STATUS_CHARGING constant
+ BATTERY_STATUS_DISCHARGING = 3, // equals BatteryManager.BATTERY_STATUS_DISCHARGING constant
+ BATTERY_STATUS_NOT_CHARGING = 4, // equals BatteryManager.BATTERY_STATUS_NOT_CHARGING constant
+ BATTERY_STATUS_FULL = 5, // equals BatteryManager.BATTERY_STATUS_FULL constant
+};
+
+// must be kept in sync with definitions in BatteryManager.java
+enum {
+ BATTERY_HEALTH_UNKNOWN = 1, // equals BatteryManager.BATTERY_HEALTH_UNKNOWN constant
+ BATTERY_HEALTH_GOOD = 2, // equals BatteryManager.BATTERY_HEALTH_GOOD constant
+ BATTERY_HEALTH_OVERHEAT = 3, // equals BatteryManager.BATTERY_HEALTH_OVERHEAT constant
+ BATTERY_HEALTH_DEAD = 4, // equals BatteryManager.BATTERY_HEALTH_DEAD constant
+ BATTERY_HEALTH_OVER_VOLTAGE = 5, // equals BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE constant
+ BATTERY_HEALTH_UNSPECIFIED_FAILURE = 6, // equals BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE constant
+ BATTERY_HEALTH_COLD = 7, // equals BatteryManager.BATTERY_HEALTH_COLD constant
+};
+
+// must be kept in sync with definitions in BatteryProperty.java
+enum {
+ BATTERY_PROP_CHARGE_COUNTER = 1, // equals BatteryProperty.CHARGE_COUNTER constant
+ BATTERY_PROP_CURRENT_NOW = 2, // equals BatteryProperty.CURRENT_NOW constant
+ BATTERY_PROP_CURRENT_AVG = 3, // equals BatteryProperty.CURRENT_AVG constant
+ BATTERY_PROP_CAPACITY = 4, // equals BatteryProperty.CAPACITY constant
+ BATTERY_PROP_ENERGY_COUNTER = 5, // equals BatteryProperty.ENERGY_COUNTER constant
+};
+
+struct BatteryProperties {
+ bool chargerAcOnline;
+ bool chargerUsbOnline;
+ bool chargerWirelessOnline;
+ int maxChargingCurrent;
+ int batteryStatus;
+ int batteryHealth;
+ bool batteryPresent;
+ int batteryLevel;
+ int batteryVoltage;
+ int batteryTemperature;
+ String8 batteryTechnology;
+
+ bool dockBatterySupported;
+ bool chargerDockAcOnline;
+ int dockBatteryStatus;
+ int dockBatteryHealth;
+ bool dockBatteryPresent;
+ int dockBatteryLevel;
+ int dockBatteryVoltage;
+ int dockBatteryTemperature;
+ String8 dockBatteryTechnology;
+
+ status_t writeToParcel(Parcel* parcel) const;
+ status_t readFromParcel(Parcel* parcel);
+};
+
+struct BatteryProperty {
+ int64_t valueInt64;
+
+ status_t writeToParcel(Parcel* parcel) const;
+ status_t readFromParcel(Parcel* parcel);
+};
+
+}; // namespace android
+
+#endif // ANDROID_BATTERYSERVICE_H
diff --git a/phonelibs/android_frameworks_native/include/batteryservice/IBatteryPropertiesListener.h b/phonelibs/android_frameworks_native/include/batteryservice/IBatteryPropertiesListener.h
new file mode 100644
index 000000000..b02d8e907
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/batteryservice/IBatteryPropertiesListener.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * 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 ANDROID_IBATTERYPROPERTIESLISTENER_H
+#define ANDROID_IBATTERYPROPERTIESLISTENER_H
+
+#include
+#include
+
+#include
+
+namespace android {
+
+// must be kept in sync with interface defined in IBatteryPropertiesListener.aidl
+enum {
+ TRANSACT_BATTERYPROPERTIESCHANGED = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+// ----------------------------------------------------------------------------
+
+class IBatteryPropertiesListener : public IInterface {
+public:
+ DECLARE_META_INTERFACE(BatteryPropertiesListener);
+
+ virtual void batteryPropertiesChanged(struct BatteryProperties props) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IBATTERYPROPERTIESLISTENER_H
diff --git a/phonelibs/android_frameworks_native/include/batteryservice/IBatteryPropertiesRegistrar.h b/phonelibs/android_frameworks_native/include/batteryservice/IBatteryPropertiesRegistrar.h
new file mode 100644
index 000000000..f6a7981d5
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/batteryservice/IBatteryPropertiesRegistrar.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2015 The CyanogenMod Project
+ *
+ * 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 ANDROID_IBATTERYPROPERTIESREGISTRAR_H
+#define ANDROID_IBATTERYPROPERTIESREGISTRAR_H
+
+#include
+#include
+
+namespace android {
+
+// must be kept in sync with interface defined in IBatteryPropertiesRegistrar.aidl
+enum {
+ REGISTER_LISTENER = IBinder::FIRST_CALL_TRANSACTION,
+ UNREGISTER_LISTENER,
+ GET_PROPERTY,
+ GET_DOCK_PROPERTY,
+};
+
+class IBatteryPropertiesRegistrar : public IInterface {
+public:
+ DECLARE_META_INTERFACE(BatteryPropertiesRegistrar);
+
+ virtual void registerListener(const sp& listener) = 0;
+ virtual void unregisterListener(const sp& listener) = 0;
+ virtual status_t getProperty(int id, struct BatteryProperty *val) = 0;
+ virtual status_t getDockProperty(int id, struct BatteryProperty *val) = 0;
+};
+
+class BnBatteryPropertiesRegistrar : public BnInterface {
+public:
+ virtual status_t onTransact(uint32_t code, const Parcel& data,
+ Parcel* reply, uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif // ANDROID_IBATTERYPROPERTIESREGISTRAR_H
diff --git a/phonelibs/android_frameworks_native/include/binder/AppOpsManager.h b/phonelibs/android_frameworks_native/include/binder/AppOpsManager.h
new file mode 100644
index 000000000..1d0e968c4
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/binder/AppOpsManager.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * 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 ANDROID_APP_OPS_MANAGER_H
+#define ANDROID_APP_OPS_MANAGER_H
+
+#include
+
+#include
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+class AppOpsManager
+{
+public:
+ enum {
+ MODE_ALLOWED = IAppOpsService::MODE_ALLOWED,
+ MODE_IGNORED = IAppOpsService::MODE_IGNORED,
+ MODE_ERRORED = IAppOpsService::MODE_ERRORED
+ };
+
+ enum {
+ OP_NONE = -1,
+ OP_COARSE_LOCATION = 0,
+ OP_FINE_LOCATION = 1,
+ OP_GPS = 2,
+ OP_VIBRATE = 3,
+ OP_READ_CONTACTS = 4,
+ OP_WRITE_CONTACTS = 5,
+ OP_READ_CALL_LOG = 6,
+ OP_WRITE_CALL_LOG = 7,
+ OP_READ_CALENDAR = 8,
+ OP_WRITE_CALENDAR = 9,
+ OP_WIFI_SCAN = 10,
+ OP_POST_NOTIFICATION = 11,
+ OP_NEIGHBORING_CELLS = 12,
+ OP_CALL_PHONE = 13,
+ OP_READ_SMS = 14,
+ OP_WRITE_SMS = 15,
+ OP_RECEIVE_SMS = 16,
+ OP_RECEIVE_EMERGECY_SMS = 17,
+ OP_RECEIVE_MMS = 18,
+ OP_RECEIVE_WAP_PUSH = 19,
+ OP_SEND_SMS = 20,
+ OP_READ_ICC_SMS = 21,
+ OP_WRITE_ICC_SMS = 22,
+ OP_WRITE_SETTINGS = 23,
+ OP_SYSTEM_ALERT_WINDOW = 24,
+ OP_ACCESS_NOTIFICATIONS = 25,
+ OP_CAMERA = 26,
+ OP_RECORD_AUDIO = 27,
+ OP_PLAY_AUDIO = 28,
+ OP_READ_CLIPBOARD = 29,
+ OP_WRITE_CLIPBOARD = 30,
+ OP_TAKE_MEDIA_BUTTONS = 31,
+ OP_TAKE_AUDIO_FOCUS = 32,
+ OP_AUDIO_MASTER_VOLUME = 33,
+ OP_AUDIO_VOICE_VOLUME = 34,
+ OP_AUDIO_RING_VOLUME = 35,
+ OP_AUDIO_MEDIA_VOLUME = 36,
+ OP_AUDIO_ALARM_VOLUME = 37,
+ OP_AUDIO_NOTIFICATION_VOLUME = 38,
+ OP_AUDIO_BLUETOOTH_VOLUME = 39,
+ OP_WAKE_LOCK = 40,
+ OP_MONITOR_LOCATION = 41,
+ OP_MONITOR_HIGH_POWER_LOCATION = 42,
+ OP_GET_USAGE_STATS = 43,
+ OP_MUTE_MICROPHONE = 44,
+ OP_TOAST_WINDOW = 45,
+ OP_PROJECT_MEDIA = 46,
+ OP_ACTIVATE_VPN = 47,
+ OP_WRITE_WALLPAPER = 48,
+ OP_ASSIST_STRUCTURE = 49,
+ OP_ASSIST_SCREENSHOT = 50,
+ OP_READ_PHONE_STATE = 51,
+ OP_ADD_VOICEMAIL = 52,
+ OP_USE_SIP = 53,
+ OP_PROCESS_OUTGOING_CALLS = 54,
+ OP_USE_FINGERPRINT = 55,
+ OP_BODY_SENSORS = 56,
+ OP_READ_CELL_BROADCASTS = 57,
+ OP_MOCK_LOCATION = 58,
+ OP_READ_EXTERNAL_STORAGE = 59,
+ OP_WRITE_EXTERNAL_STORAGE = 60,
+ OP_TURN_SCREEN_ON = 61,
+ OP_GET_ACCOUNTS = 62,
+ OP_WIFI_CHANGE = 63,
+ OP_BLUETOOTH_CHANGE = 64,
+ OP_BOOT_COMPLETED = 65,
+ OP_NFC_CHANGE = 66,
+ OP_DATA_CONNECT_CHANGE = 67,
+ OP_SU = 68
+ };
+
+ AppOpsManager();
+
+ int32_t checkOp(int32_t op, int32_t uid, const String16& callingPackage);
+ int32_t noteOp(int32_t op, int32_t uid, const String16& callingPackage);
+ int32_t startOp(int32_t op, int32_t uid, const String16& callingPackage);
+ void finishOp(int32_t op, int32_t uid, const String16& callingPackage);
+ void startWatchingMode(int32_t op, const String16& packageName,
+ const sp& callback);
+ void stopWatchingMode(const sp& callback);
+ int32_t permissionToOpCode(const String16& permission);
+
+private:
+ Mutex mLock;
+ sp mService;
+
+ sp getService();
+};
+
+
+}; // namespace android
+// ---------------------------------------------------------------------------
+#endif // ANDROID_APP_OPS_MANAGER_H
diff --git a/phonelibs/android_frameworks_native/include/binder/Binder.h b/phonelibs/android_frameworks_native/include/binder/Binder.h
new file mode 100644
index 000000000..86628a03d
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/binder/Binder.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * 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 ANDROID_BINDER_H
+#define ANDROID_BINDER_H
+
+#include
+#include
+#include
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+class BBinder : public IBinder
+{
+public:
+ BBinder();
+
+ virtual const String16& getInterfaceDescriptor() const;
+ virtual bool isBinderAlive() const;
+ virtual status_t pingBinder();
+ virtual status_t dump(int fd, const Vector& args);
+
+ virtual status_t transact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+
+ virtual status_t linkToDeath(const sp& recipient,
+ void* cookie = NULL,
+ uint32_t flags = 0);
+
+ virtual status_t unlinkToDeath( const wp& recipient,
+ void* cookie = NULL,
+ uint32_t flags = 0,
+ wp* outRecipient = NULL);
+
+ virtual void attachObject( const void* objectID,
+ void* object,
+ void* cleanupCookie,
+ object_cleanup_func func);
+ virtual void* findObject(const void* objectID) const;
+ virtual void detachObject(const void* objectID);
+
+ virtual BBinder* localBinder();
+
+protected:
+ virtual ~BBinder();
+
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+
+private:
+ BBinder(const BBinder& o);
+ BBinder& operator=(const BBinder& o);
+
+ class Extras;
+
+ atomic_uintptr_t mExtras; // should be atomic
+ void* mReserved0;
+};
+
+// ---------------------------------------------------------------------------
+
+class BpRefBase : public virtual RefBase
+{
+protected:
+ BpRefBase(const sp& o);
+ virtual ~BpRefBase();
+ virtual void onFirstRef();
+ virtual void onLastStrongRef(const void* id);
+ virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
+
+ inline IBinder* remote() { return mRemote; }
+ inline IBinder* remote() const { return mRemote; }
+
+private:
+ BpRefBase(const BpRefBase& o);
+ BpRefBase& operator=(const BpRefBase& o);
+
+ IBinder* const mRemote;
+ RefBase::weakref_type* mRefs;
+ volatile int32_t mState;
+};
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_BINDER_H
diff --git a/phonelibs/android_frameworks_native/include/binder/BinderService.h b/phonelibs/android_frameworks_native/include/binder/BinderService.h
new file mode 100644
index 000000000..ef703bda9
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/binder/BinderService.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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 ANDROID_BINDER_SERVICE_H
+#define ANDROID_BINDER_SERVICE_H
+
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+template
+class BinderService
+{
+public:
+ static status_t publish(bool allowIsolated = false) {
+ sp sm(defaultServiceManager());
+ return sm->addService(
+ String16(SERVICE::getServiceName()),
+ new SERVICE(), allowIsolated);
+ }
+
+ static void publishAndJoinThreadPool(bool allowIsolated = false) {
+ publish(allowIsolated);
+ joinThreadPool();
+ }
+
+ static void instantiate() { publish(); }
+
+ static status_t shutdown() { return NO_ERROR; }
+
+private:
+ static void joinThreadPool() {
+ sp ps(ProcessState::self());
+ ps->startThreadPool();
+ ps->giveThreadPoolName();
+ IPCThreadState::self()->joinThreadPool();
+ }
+};
+
+
+}; // namespace android
+// ---------------------------------------------------------------------------
+#endif // ANDROID_BINDER_SERVICE_H
diff --git a/phonelibs/android_frameworks_native/include/binder/BpBinder.h b/phonelibs/android_frameworks_native/include/binder/BpBinder.h
new file mode 100644
index 000000000..7ef93aa39
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/binder/BpBinder.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2005 The Android Open Source Project
+ *
+ * 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 ANDROID_BPBINDER_H
+#define ANDROID_BPBINDER_H
+
+#include
+#include
+#include
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+class BpBinder : public IBinder
+{
+public:
+ BpBinder(int32_t handle);
+
+ inline int32_t handle() const { return mHandle; }
+
+ virtual const String16& getInterfaceDescriptor() const;
+ virtual bool isBinderAlive() const;
+ virtual status_t pingBinder();
+ virtual status_t dump(int fd, const Vector& args);
+
+ virtual status_t transact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+
+ virtual status_t linkToDeath(const sp& recipient,
+ void* cookie = NULL,
+ uint32_t flags = 0);
+ virtual status_t unlinkToDeath( const wp& recipient,
+ void* cookie = NULL,
+ uint32_t flags = 0,
+ wp* outRecipient = NULL);
+
+ virtual void attachObject( const void* objectID,
+ void* object,
+ void* cleanupCookie,
+ object_cleanup_func func);
+ virtual void* findObject(const void* objectID) const;
+ virtual void detachObject(const void* objectID);
+
+ virtual BpBinder* remoteBinder();
+
+ status_t setConstantData(const void* data, size_t size);
+ void sendObituary();
+
+ class ObjectManager
+ {
+ public:
+ ObjectManager();
+ ~ObjectManager();
+
+ void attach( const void* objectID,
+ void* object,
+ void* cleanupCookie,
+ IBinder::object_cleanup_func func);
+ void* find(const void* objectID) const;
+ void detach(const void* objectID);
+
+ void kill();
+
+ private:
+ ObjectManager(const ObjectManager&);
+ ObjectManager& operator=(const ObjectManager&);
+
+ struct entry_t
+ {
+ void* object;
+ void* cleanupCookie;
+ IBinder::object_cleanup_func func;
+ };
+
+ KeyedVector mObjects;
+ };
+
+protected:
+ virtual ~BpBinder();
+ virtual void onFirstRef();
+ virtual void onLastStrongRef(const void* id);
+ virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
+
+private:
+ const int32_t mHandle;
+
+ struct Obituary {
+ wp recipient;
+ void* cookie;
+ uint32_t flags;
+ };
+
+ void reportOneDeath(const Obituary& obit);
+ bool isDescriptorCached() const;
+
+ mutable Mutex mLock;
+ volatile int32_t mAlive;
+ volatile int32_t mObitsSent;
+ Vector* mObituaries;
+ ObjectManager mObjects;
+ Parcel* mConstantData;
+ mutable String16 mDescriptorCache;
+};
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_BPBINDER_H
diff --git a/phonelibs/android_frameworks_native/include/binder/BufferedTextOutput.h b/phonelibs/android_frameworks_native/include/binder/BufferedTextOutput.h
new file mode 100644
index 000000000..9a7c43bb1
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/binder/BufferedTextOutput.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * 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 ANDROID_BUFFEREDTEXTOUTPUT_H
+#define ANDROID_BUFFEREDTEXTOUTPUT_H
+
+#include
+#include
+#include
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+class BufferedTextOutput : public TextOutput
+{
+public:
+ //** Flags for constructor */
+ enum {
+ MULTITHREADED = 0x0001
+ };
+
+ BufferedTextOutput(uint32_t flags = 0);
+ virtual ~BufferedTextOutput();
+
+ virtual status_t print(const char* txt, size_t len);
+ virtual void moveIndent(int delta);
+
+ virtual void pushBundle();
+ virtual void popBundle();
+
+protected:
+ virtual status_t writeLines(const struct iovec& vec, size_t N) = 0;
+
+private:
+ struct BufferState;
+ struct ThreadState;
+
+ static ThreadState*getThreadState();
+ static void threadDestructor(void *st);
+
+ BufferState*getBuffer() const;
+
+ uint32_t mFlags;
+ const int32_t mSeq;
+ const int32_t mIndex;
+
+ Mutex mLock;
+ BufferState* mGlobalState;
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_BUFFEREDTEXTOUTPUT_H
diff --git a/phonelibs/android_frameworks_native/include/binder/Debug.h b/phonelibs/android_frameworks_native/include/binder/Debug.h
new file mode 100644
index 000000000..f6a335502
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/binder/Debug.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2005 The Android Open Source Project
+ *
+ * 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 ANDROID_BINDER_DEBUG_H
+#define ANDROID_BINDER_DEBUG_H
+
+#include
+#include
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const char* stringForIndent(int32_t indentLevel);
+
+typedef void (*debugPrintFunc)(void* cookie, const char* txt);
+
+void printTypeCode(uint32_t typeCode,
+ debugPrintFunc func = 0, void* cookie = 0);
+
+void printHexData(int32_t indent, const void *buf, size_t length,
+ size_t bytesPerLine=16, int32_t singleLineBytesCutoff=16,
+ size_t alignment=0, bool cArrayStyle=false,
+ debugPrintFunc func = 0, void* cookie = 0);
+
+#ifdef __cplusplus
+}
+#endif
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_BINDER_DEBUG_H
diff --git a/phonelibs/android_frameworks_native/include/binder/IAppOpsCallback.h b/phonelibs/android_frameworks_native/include/binder/IAppOpsCallback.h
new file mode 100644
index 000000000..7f8eb0168
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/binder/IAppOpsCallback.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * 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 ANDROID_IAPP_OPS_CALLBACK_H
+#define ANDROID_IAPP_OPS_CALLBACK_H
+
+#include
+
+namespace android {
+
+// ----------------------------------------------------------------------
+
+class IAppOpsCallback : public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(AppOpsCallback);
+
+ virtual void opChanged(int32_t op, const String16& packageName) = 0;
+
+ enum {
+ OP_CHANGED_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION
+ };
+};
+
+// ----------------------------------------------------------------------
+
+class BnAppOpsCallback : public BnInterface
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IAPP_OPS_CALLBACK_H
+
diff --git a/phonelibs/android_frameworks_native/include/binder/IAppOpsService.h b/phonelibs/android_frameworks_native/include/binder/IAppOpsService.h
new file mode 100644
index 000000000..cd81efa36
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/binder/IAppOpsService.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * 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 ANDROID_IAPP_OPS_SERVICE_H
+#define ANDROID_IAPP_OPS_SERVICE_H
+
+#include
+#include
+
+namespace android {
+
+// ----------------------------------------------------------------------
+
+class IAppOpsService : public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(AppOpsService);
+
+ virtual int32_t checkOperation(int32_t code, int32_t uid, const String16& packageName) = 0;
+ virtual int32_t noteOperation(int32_t code, int32_t uid, const String16& packageName) = 0;
+ virtual int32_t startOperation(const sp& token, int32_t code, int32_t uid,
+ const String16& packageName) = 0;
+ virtual void finishOperation(const sp& token, int32_t code, int32_t uid,
+ const String16& packageName) = 0;
+ virtual void startWatchingMode(int32_t op, const String16& packageName,
+ const sp& callback) = 0;
+ virtual void stopWatchingMode(const sp& callback) = 0;
+ virtual sp getToken(const sp& clientToken) = 0;
+ virtual int32_t permissionToOpCode(const String16& permission) = 0;
+
+ enum {
+ CHECK_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
+ NOTE_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+1,
+ START_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+2,
+ FINISH_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+3,
+ START_WATCHING_MODE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+4,
+ STOP_WATCHING_MODE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+5,
+ GET_TOKEN_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+6,
+ PERMISSION_TO_OP_CODE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+7,
+ };
+
+ enum {
+ MODE_ALLOWED = 0,
+ MODE_IGNORED = 1,
+ MODE_ERRORED = 2
+ };
+};
+
+// ----------------------------------------------------------------------
+
+class BnAppOpsService : public BnInterface
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IAPP_OPS_SERVICE_H
diff --git a/phonelibs/android_frameworks_native/include/binder/IBatteryStats.h b/phonelibs/android_frameworks_native/include/binder/IBatteryStats.h
new file mode 100644
index 000000000..5f3818652
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/binder/IBatteryStats.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * 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 ANDROID_IBATTERYSTATS_H
+#define ANDROID_IBATTERYSTATS_H
+
+#include
+
+namespace android {
+
+// ----------------------------------------------------------------------
+
+class IBatteryStats : public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(BatteryStats);
+
+ virtual void noteStartSensor(int uid, int sensor) = 0;
+ virtual void noteStopSensor(int uid, int sensor) = 0;
+ virtual void noteStartVideo(int uid) = 0;
+ virtual void noteStopVideo(int uid) = 0;
+ virtual void noteStartAudio(int uid) = 0;
+ virtual void noteStopAudio(int uid) = 0;
+ virtual void noteResetVideo() = 0;
+ virtual void noteResetAudio() = 0;
+ virtual void noteFlashlightOn(int uid) = 0;
+ virtual void noteFlashlightOff(int uid) = 0;
+ virtual void noteStartCamera(int uid) = 0;
+ virtual void noteStopCamera(int uid) = 0;
+ virtual void noteResetCamera() = 0;
+ virtual void noteResetFlashlight() = 0;
+
+ enum {
+ NOTE_START_SENSOR_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
+ NOTE_STOP_SENSOR_TRANSACTION,
+ NOTE_START_VIDEO_TRANSACTION,
+ NOTE_STOP_VIDEO_TRANSACTION,
+ NOTE_START_AUDIO_TRANSACTION,
+ NOTE_STOP_AUDIO_TRANSACTION,
+ NOTE_RESET_VIDEO_TRANSACTION,
+ NOTE_RESET_AUDIO_TRANSACTION,
+ NOTE_FLASHLIGHT_ON_TRANSACTION,
+ NOTE_FLASHLIGHT_OFF_TRANSACTION,
+ NOTE_START_CAMERA_TRANSACTION,
+ NOTE_STOP_CAMERA_TRANSACTION,
+ NOTE_RESET_CAMERA_TRANSACTION,
+ NOTE_RESET_FLASHLIGHT_TRANSACTION
+ };
+};
+
+// ----------------------------------------------------------------------
+
+class BnBatteryStats : public BnInterface
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IBATTERYSTATS_H
diff --git a/phonelibs/android_frameworks_native/include/binder/IBinder.h b/phonelibs/android_frameworks_native/include/binder/IBinder.h
new file mode 100644
index 000000000..43b654334
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/binder/IBinder.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * 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 ANDROID_IBINDER_H
+#define ANDROID_IBINDER_H
+
+#include
+#include
+#include
+#include
+
+
+#define B_PACK_CHARS(c1, c2, c3, c4) \
+ ((((c1)<<24)) | (((c2)<<16)) | (((c3)<<8)) | (c4))
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+class BBinder;
+class BpBinder;
+class IInterface;
+class Parcel;
+
+/**
+ * Base class and low-level protocol for a remotable object.
+ * You can derive from this class to create an object for which other
+ * processes can hold references to it. Communication between processes
+ * (method calls, property get and set) is down through a low-level
+ * protocol implemented on top of the transact() API.
+ */
+class IBinder : public virtual RefBase
+{
+public:
+ enum {
+ FIRST_CALL_TRANSACTION = 0x00000001,
+ LAST_CALL_TRANSACTION = 0x00ffffff,
+
+ PING_TRANSACTION = B_PACK_CHARS('_','P','N','G'),
+ DUMP_TRANSACTION = B_PACK_CHARS('_','D','M','P'),
+ INTERFACE_TRANSACTION = B_PACK_CHARS('_', 'N', 'T', 'F'),
+ SYSPROPS_TRANSACTION = B_PACK_CHARS('_', 'S', 'P', 'R'),
+
+ // Corresponds to TF_ONE_WAY -- an asynchronous call.
+ FLAG_ONEWAY = 0x00000001
+ };
+
+ IBinder();
+
+ /**
+ * Check if this IBinder implements the interface named by
+ * @a descriptor. If it does, the base pointer to it is returned,
+ * which you can safely static_cast<> to the concrete C++ interface.
+ */
+ virtual sp queryLocalInterface(const String16& descriptor);
+
+ /**
+ * Return the canonical name of the interface provided by this IBinder
+ * object.
+ */
+ virtual const String16& getInterfaceDescriptor() const = 0;
+
+ virtual bool isBinderAlive() const = 0;
+ virtual status_t pingBinder() = 0;
+ virtual status_t dump(int fd, const Vector& args) = 0;
+
+ virtual status_t transact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0) = 0;
+
+ class DeathRecipient : public virtual RefBase
+ {
+ public:
+ virtual void binderDied(const wp& who) = 0;
+ };
+
+ /**
+ * Register the @a recipient for a notification if this binder
+ * goes away. If this binder object unexpectedly goes away
+ * (typically because its hosting process has been killed),
+ * then DeathRecipient::binderDied() will be called with a reference
+ * to this.
+ *
+ * The @a cookie is optional -- if non-NULL, it should be a
+ * memory address that you own (that is, you know it is unique).
+ *
+ * @note You will only receive death notifications for remote binders,
+ * as local binders by definition can't die without you dying as well.
+ * Trying to use this function on a local binder will result in an
+ * INVALID_OPERATION code being returned and nothing happening.
+ *
+ * @note This link always holds a weak reference to its recipient.
+ *
+ * @note You will only receive a weak reference to the dead
+ * binder. You should not try to promote this to a strong reference.
+ * (Nor should you need to, as there is nothing useful you can
+ * directly do with it now that it has passed on.)
+ */
+ virtual status_t linkToDeath(const sp& recipient,
+ void* cookie = NULL,
+ uint32_t flags = 0) = 0;
+
+ /**
+ * Remove a previously registered death notification.
+ * The @a recipient will no longer be called if this object
+ * dies. The @a cookie is optional. If non-NULL, you can
+ * supply a NULL @a recipient, and the recipient previously
+ * added with that cookie will be unlinked.
+ */
+ virtual status_t unlinkToDeath( const wp& recipient,
+ void* cookie = NULL,
+ uint32_t flags = 0,
+ wp* outRecipient = NULL) = 0;
+
+ virtual bool checkSubclass(const void* subclassID) const;
+
+ typedef void (*object_cleanup_func)(const void* id, void* obj, void* cleanupCookie);
+
+ virtual void attachObject( const void* objectID,
+ void* object,
+ void* cleanupCookie,
+ object_cleanup_func func) = 0;
+ virtual void* findObject(const void* objectID) const = 0;
+ virtual void detachObject(const void* objectID) = 0;
+
+ virtual BBinder* localBinder();
+ virtual BpBinder* remoteBinder();
+
+protected:
+ virtual ~IBinder();
+
+private:
+};
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_IBINDER_H
diff --git a/phonelibs/android_frameworks_native/include/binder/IInterface.h b/phonelibs/android_frameworks_native/include/binder/IInterface.h
new file mode 100644
index 000000000..4ce361380
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/binder/IInterface.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2005 The Android Open Source Project
+ *
+ * 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 ANDROID_IINTERFACE_H
+#define ANDROID_IINTERFACE_H
+
+#include
+
+namespace android {
+
+// ----------------------------------------------------------------------
+
+class IInterface : public virtual RefBase
+{
+public:
+ IInterface();
+ static sp asBinder(const IInterface*);
+ static sp asBinder(const sp&);
+
+protected:
+ virtual ~IInterface();
+ virtual IBinder* onAsBinder() = 0;
+};
+
+// ----------------------------------------------------------------------
+
+template
+inline sp interface_cast(const sp& obj)
+{
+ return INTERFACE::asInterface(obj);
+}
+
+// ----------------------------------------------------------------------
+
+template
+class BnInterface : public INTERFACE, public BBinder
+{
+public:
+ virtual sp queryLocalInterface(const String16& _descriptor);
+ virtual const String16& getInterfaceDescriptor() const;
+
+protected:
+ virtual IBinder* onAsBinder();
+};
+
+// ----------------------------------------------------------------------
+
+template
+class BpInterface : public INTERFACE, public BpRefBase
+{
+public:
+ BpInterface(const sp& remote);
+
+protected:
+ virtual IBinder* onAsBinder();
+};
+
+// ----------------------------------------------------------------------
+
+#define DECLARE_META_INTERFACE(INTERFACE) \
+ static const android::String16 descriptor; \
+ static android::sp asInterface( \
+ const android::sp& obj); \
+ virtual const android::String16& getInterfaceDescriptor() const; \
+ I##INTERFACE(); \
+ virtual ~I##INTERFACE(); \
+
+
+#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
+ const android::String16 I##INTERFACE::descriptor(NAME); \
+ const android::String16& \
+ I##INTERFACE::getInterfaceDescriptor() const { \
+ return I##INTERFACE::descriptor; \
+ } \
+ android::sp I##INTERFACE::asInterface( \
+ const android::sp& obj) \
+ { \
+ android::sp intr; \
+ if (obj != NULL) { \
+ intr = static_cast( \
+ obj->queryLocalInterface( \
+ I##INTERFACE::descriptor).get()); \
+ if (intr == NULL) { \
+ intr = new Bp##INTERFACE(obj); \
+ } \
+ } \
+ return intr; \
+ } \
+ I##INTERFACE::I##INTERFACE() { } \
+ I##INTERFACE::~I##INTERFACE() { } \
+
+
+#define CHECK_INTERFACE(interface, data, reply) \
+ if (!data.checkInterface(this)) { return PERMISSION_DENIED; } \
+
+
+// ----------------------------------------------------------------------
+// No user-serviceable parts after this...
+
+template
+inline sp BnInterface::queryLocalInterface(
+ const String16& _descriptor)
+{
+ if (_descriptor == INTERFACE::descriptor) return this;
+ return NULL;
+}
+
+template
+inline const String16& BnInterface::getInterfaceDescriptor() const
+{
+ return INTERFACE::getInterfaceDescriptor();
+}
+
+template
+IBinder* BnInterface::onAsBinder()
+{
+ return this;
+}
+
+template
+inline BpInterface::BpInterface(const sp& remote)
+ : BpRefBase(remote)
+{
+}
+
+template
+inline IBinder* BpInterface::onAsBinder()
+{
+ return remote();
+}
+
+// ----------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IINTERFACE_H
diff --git a/phonelibs/android_frameworks_native/include/binder/IMemory.h b/phonelibs/android_frameworks_native/include/binder/IMemory.h
new file mode 100644
index 000000000..178ef8593
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/binder/IMemory.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 ANDROID_IMEMORY_H
+#define ANDROID_IMEMORY_H
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class IMemoryHeap : public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(MemoryHeap);
+
+ // flags returned by getFlags()
+ enum {
+ READ_ONLY = 0x00000001,
+#ifdef USE_MEMORY_HEAP_ION
+ USE_ION_FD = 0x00008000
+#else
+ USE_ION_FD = 0x00000008
+#endif
+ };
+
+ virtual int getHeapID() const = 0;
+ virtual void* getBase() const = 0;
+ virtual size_t getSize() const = 0;
+ virtual uint32_t getFlags() const = 0;
+ virtual uint32_t getOffset() const = 0;
+
+ // these are there just for backward source compatibility
+ int32_t heapID() const { return getHeapID(); }
+ void* base() const { return getBase(); }
+ size_t virtualSize() const { return getSize(); }
+};
+
+class BnMemoryHeap : public BnInterface
+{
+public:
+ virtual status_t onTransact(
+ uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+
+ BnMemoryHeap();
+protected:
+ virtual ~BnMemoryHeap();
+};
+
+// ----------------------------------------------------------------------------
+
+class IMemory : public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(Memory);
+
+ virtual sp getMemory(ssize_t* offset=0, size_t* size=0) const = 0;
+
+ // helpers
+ void* fastPointer(const sp& heap, ssize_t offset) const;
+ void* pointer() const;
+ size_t size() const;
+ ssize_t offset() const;
+};
+
+class BnMemory : public BnInterface
+{
+public:
+ virtual status_t onTransact(
+ uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+
+ BnMemory();
+protected:
+ virtual ~BnMemory();
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IMEMORY_H
diff --git a/phonelibs/android_frameworks_native/include/binder/IPCThreadState.h b/phonelibs/android_frameworks_native/include/binder/IPCThreadState.h
new file mode 100644
index 000000000..1853cff23
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/binder/IPCThreadState.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2005 The Android Open Source Project
+ *
+ * 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 ANDROID_IPC_THREAD_STATE_H
+#define ANDROID_IPC_THREAD_STATE_H
+
+#include
+#include
+#include
+#include
+
+#if defined(_WIN32)
+typedef int uid_t;
+#endif
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+class IPCThreadState
+{
+public:
+ static IPCThreadState* self();
+ static IPCThreadState* selfOrNull(); // self(), but won't instantiate
+
+ sp process();
+
+ status_t clearLastError();
+
+ pid_t getCallingPid() const;
+ uid_t getCallingUid() const;
+
+ void setStrictModePolicy(int32_t policy);
+ int32_t getStrictModePolicy() const;
+
+ void setLastTransactionBinderFlags(int32_t flags);
+ int32_t getLastTransactionBinderFlags() const;
+
+ int64_t clearCallingIdentity();
+ void restoreCallingIdentity(int64_t token);
+
+ int setupPolling(int* fd);
+ status_t handlePolledCommands();
+ void flushCommands();
+
+ void joinThreadPool(bool isMain = true);
+
+ // Stop the local process.
+ void stopProcess(bool immediate = true);
+
+ status_t transact(int32_t handle,
+ uint32_t code, const Parcel& data,
+ Parcel* reply, uint32_t flags);
+
+ void incStrongHandle(int32_t handle);
+ void decStrongHandle(int32_t handle);
+ void incWeakHandle(int32_t handle);
+ void decWeakHandle(int32_t handle);
+ status_t attemptIncStrongHandle(int32_t handle);
+ static void expungeHandle(int32_t handle, IBinder* binder);
+ status_t requestDeathNotification( int32_t handle,
+ BpBinder* proxy);
+ status_t clearDeathNotification( int32_t handle,
+ BpBinder* proxy);
+
+ static void shutdown();
+
+ // Call this to disable switching threads to background scheduling when
+ // receiving incoming IPC calls. This is specifically here for the
+ // Android system process, since it expects to have background apps calling
+ // in to it but doesn't want to acquire locks in its services while in
+ // the background.
+ static void disableBackgroundScheduling(bool disable);
+
+ // Call blocks until the number of executing binder threads is less than
+ // the maximum number of binder threads threads allowed for this process.
+ void blockUntilThreadAvailable();
+
+private:
+ IPCThreadState();
+ ~IPCThreadState();
+
+ status_t sendReply(const Parcel& reply, uint32_t flags);
+ status_t waitForResponse(Parcel *reply,
+ status_t *acquireResult=NULL);
+ status_t talkWithDriver(bool doReceive=true);
+ status_t writeTransactionData(int32_t cmd,
+ uint32_t binderFlags,
+ int32_t handle,
+ uint32_t code,
+ const Parcel& data,
+ status_t* statusBuffer);
+ status_t getAndExecuteCommand();
+ status_t executeCommand(int32_t command);
+ void processPendingDerefs();
+
+ void clearCaller();
+
+ static void threadDestructor(void *st);
+ static void freeBuffer(Parcel* parcel,
+ const uint8_t* data, size_t dataSize,
+ const binder_size_t* objects, size_t objectsSize,
+ void* cookie);
+
+ const sp mProcess;
+ const pid_t mMyThreadId;
+ Vector mPendingStrongDerefs;
+ Vector mPendingWeakDerefs;
+
+ Parcel mIn;
+ Parcel mOut;
+ status_t mLastError;
+ pid_t mCallingPid;
+ uid_t mCallingUid;
+ int32_t mStrictModePolicy;
+ int32_t mLastTransactionBinderFlags;
+};
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_IPC_THREAD_STATE_H
diff --git a/phonelibs/android_frameworks_native/include/binder/IPermissionController.h b/phonelibs/android_frameworks_native/include/binder/IPermissionController.h
new file mode 100644
index 000000000..4e5fb3483
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/binder/IPermissionController.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2005 The Android Open Source Project
+ *
+ * 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 ANDROID_IPERMISSION_CONTROLLER_H
+#define ANDROID_IPERMISSION_CONTROLLER_H
+
+#include
+#include
+
+namespace android {
+
+// ----------------------------------------------------------------------
+
+class IPermissionController : public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(PermissionController);
+
+ virtual bool checkPermission(const String16& permission, int32_t pid, int32_t uid) = 0;
+
+ virtual void getPackagesForUid(const uid_t uid, Vector &packages) = 0;
+
+ virtual bool isRuntimePermission(const String16& permission) = 0;
+
+ enum {
+ CHECK_PERMISSION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
+ GET_PACKAGES_FOR_UID_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 1,
+ IS_RUNTIME_PERMISSION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 2
+ };
+};
+
+// ----------------------------------------------------------------------
+
+class BnPermissionController : public BnInterface
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IPERMISSION_CONTROLLER_H
+
diff --git a/phonelibs/android_frameworks_native/include/binder/IProcessInfoService.h b/phonelibs/android_frameworks_native/include/binder/IProcessInfoService.h
new file mode 100644
index 000000000..dc62f457c
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/binder/IProcessInfoService.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * 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 ANDROID_I_PROCESS_INFO_SERVICE_H
+#define ANDROID_I_PROCESS_INFO_SERVICE_H
+
+#include
+
+namespace android {
+
+// ----------------------------------------------------------------------
+
+class IProcessInfoService : public IInterface {
+public:
+ DECLARE_META_INTERFACE(ProcessInfoService);
+
+ virtual status_t getProcessStatesFromPids( size_t length,
+ /*in*/ int32_t* pids,
+ /*out*/ int32_t* states) = 0;
+
+ enum {
+ GET_PROCESS_STATES_FROM_PIDS = IBinder::FIRST_CALL_TRANSACTION,
+ };
+};
+
+// ----------------------------------------------------------------------
+
+class BnProcessInfoService : public BnInterface {
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_I_PROCESS_INFO_SERVICE_H
diff --git a/phonelibs/android_frameworks_native/include/binder/IServiceManager.h b/phonelibs/android_frameworks_native/include/binder/IServiceManager.h
new file mode 100644
index 000000000..2c297d64f
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/binder/IServiceManager.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2005 The Android Open Source Project
+ *
+ * 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 ANDROID_ISERVICE_MANAGER_H
+#define ANDROID_ISERVICE_MANAGER_H
+
+#include
+#include
+#include
+#include
+
+namespace android {
+
+// ----------------------------------------------------------------------
+
+class IServiceManager : public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(ServiceManager);
+
+ /**
+ * Retrieve an existing service, blocking for a few seconds
+ * if it doesn't yet exist.
+ */
+ virtual sp getService( const String16& name) const = 0;
+
+ /**
+ * Retrieve an existing service, non-blocking.
+ */
+ virtual sp checkService( const String16& name) const = 0;
+
+ /**
+ * Register a service.
+ */
+ virtual status_t addService( const String16& name,
+ const sp& service,
+ bool allowIsolated = false) = 0;
+
+ /**
+ * Return list of all existing services.
+ */
+ virtual Vector listServices() = 0;
+
+ enum {
+ GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
+ CHECK_SERVICE_TRANSACTION,
+ ADD_SERVICE_TRANSACTION,
+ LIST_SERVICES_TRANSACTION,
+ };
+};
+
+sp defaultServiceManager();
+
+template
+status_t getService(const String16& name, sp* outService)
+{
+ const sp sm = defaultServiceManager();
+ if (sm != NULL) {
+ *outService = interface_cast(sm->getService(name));
+ if ((*outService) != NULL) return NO_ERROR;
+ }
+ return NAME_NOT_FOUND;
+}
+
+bool checkCallingPermission(const String16& permission);
+bool checkCallingPermission(const String16& permission,
+ int32_t* outPid, int32_t* outUid);
+bool checkPermission(const String16& permission, pid_t pid, uid_t uid);
+
+
+// ----------------------------------------------------------------------
+
+class BnServiceManager : public BnInterface
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_ISERVICE_MANAGER_H
+
diff --git a/phonelibs/android_frameworks_native/include/binder/MemoryBase.h b/phonelibs/android_frameworks_native/include/binder/MemoryBase.h
new file mode 100644
index 000000000..463e26d97
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/binder/MemoryBase.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * 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 ANDROID_MEMORY_BASE_H
+#define ANDROID_MEMORY_BASE_H
+
+#include
+#include
+
+#include
+
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+class MemoryBase : public BnMemory
+{
+public:
+ MemoryBase(const sp& heap, ssize_t offset, size_t size);
+ virtual ~MemoryBase();
+ virtual sp getMemory(ssize_t* offset, size_t* size) const;
+
+protected:
+ size_t getSize() const { return mSize; }
+ ssize_t getOffset() const { return mOffset; }
+ const sp& getHeap() const { return mHeap; }
+
+private:
+ size_t mSize;
+ ssize_t mOffset;
+ sp mHeap;
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_MEMORY_BASE_H
diff --git a/phonelibs/android_frameworks_native/include/binder/MemoryDealer.h b/phonelibs/android_frameworks_native/include/binder/MemoryDealer.h
new file mode 100644
index 000000000..aa415d5ac
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/binder/MemoryDealer.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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 ANDROID_MEMORY_DEALER_H
+#define ANDROID_MEMORY_DEALER_H
+
+
+#include
+#include
+
+#include
+#include
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+class SimpleBestFitAllocator;
+
+// ----------------------------------------------------------------------------
+
+class MemoryDealer : public RefBase
+{
+public:
+ MemoryDealer(size_t size, const char* name = 0,
+ uint32_t flags = 0 /* or bits such as MemoryHeapBase::READ_ONLY */ );
+
+ virtual sp allocate(size_t size);
+ virtual void deallocate(size_t offset);
+ virtual void dump(const char* what) const;
+
+ sp getMemoryHeap() const { return heap(); }
+
+protected:
+ virtual ~MemoryDealer();
+
+private:
+ const sp& heap() const;
+ SimpleBestFitAllocator* allocator() const;
+
+ sp mHeap;
+ SimpleBestFitAllocator* mAllocator;
+};
+
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_MEMORY_DEALER_H
diff --git a/phonelibs/android_frameworks_native/include/binder/MemoryHeapBase.h b/phonelibs/android_frameworks_native/include/binder/MemoryHeapBase.h
new file mode 100644
index 000000000..ea9b66c49
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/binder/MemoryHeapBase.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * 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 ANDROID_MEMORY_HEAP_BASE_H
+#define ANDROID_MEMORY_HEAP_BASE_H
+
+#include
+#include
+
+#include
+
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+class MemoryHeapBase : public virtual BnMemoryHeap
+{
+public:
+ enum {
+ READ_ONLY = IMemoryHeap::READ_ONLY,
+ // memory won't be mapped locally, but will be mapped in the remote
+ // process.
+ DONT_MAP_LOCALLY = 0x00000100,
+ NO_CACHING = 0x00000200
+ };
+
+ /*
+ * maps the memory referenced by fd. but DOESN'T take ownership
+ * of the filedescriptor (it makes a copy with dup()
+ */
+ MemoryHeapBase(int fd, size_t size, uint32_t flags = 0, uint32_t offset = 0);
+
+ /*
+ * maps memory from the given device
+ */
+ MemoryHeapBase(const char* device, size_t size = 0, uint32_t flags = 0);
+
+ /*
+ * maps memory from ashmem, with the given name for debugging
+ */
+ MemoryHeapBase(size_t size, uint32_t flags = 0, char const* name = NULL);
+
+ virtual ~MemoryHeapBase();
+
+ /* implement IMemoryHeap interface */
+ virtual int getHeapID() const;
+
+ /* virtual address of the heap. returns MAP_FAILED in case of error */
+ virtual void* getBase() const;
+
+ virtual size_t getSize() const;
+ virtual uint32_t getFlags() const;
+ virtual uint32_t getOffset() const;
+
+ const char* getDevice() const;
+
+ /* this closes this heap -- use carefully */
+ void dispose();
+
+ /* this is only needed as a workaround, use only if you know
+ * what you are doing */
+ status_t setDevice(const char* device) {
+ if (mDevice == 0)
+ mDevice = device;
+ return mDevice ? NO_ERROR : ALREADY_EXISTS;
+ }
+
+protected:
+ MemoryHeapBase();
+ // init() takes ownership of fd
+ status_t init(int fd, void *base, int size,
+ int flags = 0, const char* device = NULL);
+
+private:
+ status_t mapfd(int fd, size_t size, uint32_t offset = 0);
+
+ int mFD;
+ size_t mSize;
+ void* mBase;
+ uint32_t mFlags;
+ const char* mDevice;
+ bool mNeedUnmap;
+ uint32_t mOffset;
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_MEMORY_HEAP_BASE_H
diff --git a/phonelibs/android_frameworks_native/include/binder/MemoryHeapIon.h b/phonelibs/android_frameworks_native/include/binder/MemoryHeapIon.h
new file mode 100644
index 000000000..7e059f4ea
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/binder/MemoryHeapIon.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright 2011, Samsung Electronics Co. LTD
+ *
+ * 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.
+ */
+/*!
+ * \file MemoryHeapIon.h
+ * \brief header file for MemoryHeapIon
+ * \author MinGu, Jeon(mingu85.jeon)
+ * \date 2011/11/20
+ *
+ * Revision History:
+ * - 2011/11/21 : MinGu, Jeon(mingu85.jeon)) \n
+ * Initial version
+ * - 2012/11/29 : MinGu, Jeon(mingu85.jeon)) \n
+ * Change name
+ */
+
+#ifndef ANDROID_MEMORY_HEAP_ION_H
+#define ANDROID_MEMORY_HEAP_ION_H
+
+#include
+#include
+#include
+
+#define MHB_ION_HEAP_SYSTEM_CONTIG_MASK (1 << 1)
+#define MHB_ION_HEAP_EXYNOS_CONTIG_MASK (1 << 4)
+#define MHB_ION_HEAP_EXYNOS_MASK (1 << 5)
+#define MHB_ION_HEAP_SYSTEM_MASK (1 << 6)
+
+#define MHB_ION_FLAG_CACHED (1 << 16)
+#define MHB_ION_FLAG_CACHED_NEEDS_SYNC (1 << 17)
+#define MHB_ION_FLAG_PRESERVE_KMAP (1 << 18)
+
+#define MHB_ION_EXYNOS_VIDEO_MASK (1 << 21)
+#define MHB_ION_EXYNOS_MFC_INPUT_MASK (1 << 25)
+#define MHB_ION_EXYNOS_MFC_OUTPUT_MASK (1 << 26)
+#define MHB_ION_EXYNOS_GSC_MASK (1 << 27)
+#define MHB_ION_EXYNOS_FIMD_VIDEO_MASK (1 << 28)
+
+namespace android {
+
+class MemoryHeapIon : public MemoryHeapBase
+{
+public:
+ enum {
+ USE_ION_FD = IMemoryHeap::USE_ION_FD
+ };
+ MemoryHeapIon(size_t size, uint32_t flags = 0, char const* name = NULL);
+ MemoryHeapIon(int fd, size_t size, uint32_t flags = 0, uint32_t offset = 0);
+ ~MemoryHeapIon();
+private:
+ int mIonClient;
+};
+
+};
+#endif
diff --git a/phonelibs/android_frameworks_native/include/binder/Parcel.h b/phonelibs/android_frameworks_native/include/binder/Parcel.h
new file mode 100644
index 000000000..91ffae0ba
--- /dev/null
+++ b/phonelibs/android_frameworks_native/include/binder/Parcel.h
@@ -0,0 +1,436 @@
+/*
+ * Copyright (C) 2005 The Android Open Source Project
+ *
+ * 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 ANDROID_PARCEL_H
+#define ANDROID_PARCEL_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+template class Flattenable;
+template class LightFlattenable;
+class IBinder;
+class IPCThreadState;
+class ProcessState;
+class String8;
+class TextOutput;
+
+class Parcel {
+ friend class IPCThreadState;
+public:
+ class ReadableBlob;
+ class WritableBlob;
+
+ Parcel();
+ ~Parcel();
+
+ const uint8_t* data() const;
+ size_t dataSize() const;
+ size_t dataAvail() const;
+ size_t dataPosition() const;
+ size_t dataCapacity() const;
+
+ status_t setDataSize(size_t size);
+ void setDataPosition(size_t pos) const;
+ status_t setDataCapacity(size_t size);
+
+ status_t setData(const uint8_t* buffer, size_t len);
+
+ status_t appendFrom(const Parcel *parcel,
+ size_t start, size_t len);
+
+ bool allowFds() const;
+ bool pushAllowFds(bool allowFds);
+ void restoreAllowFds(bool lastValue);
+
+ bool hasFileDescriptors() const;
+
+ // Writes the RPC header.
+ status_t writeInterfaceToken(const String16& interface);
+
+ // Parses the RPC header, returning true if the interface name
+ // in the header matches the expected interface from the caller.
+ //
+ // Additionally, enforceInterface does part of the work of
+ // propagating the StrictMode policy mask, populating the current
+ // IPCThreadState, which as an optimization may optionally be
+ // passed in.
+ bool enforceInterface(const String16& interface,
+ IPCThreadState* threadState = NULL) const;
+ bool checkInterface(IBinder*) const;
+
+ void freeData();
+
+private:
+ const binder_size_t* objects() const;
+
+public:
+ size_t objectsCount() const;
+
+ status_t errorCheck() const;
+ void setError(status_t err);
+
+ status_t write(const void* data, size_t len);
+ void* writeInplace(size_t len);
+ status_t writeUnpadded(const void* data, size_t len);
+ status_t writeInt32(int32_t val);
+ status_t writeUint32(uint32_t val);
+ status_t writeInt64(int64_t val);
+ status_t writeUint64(uint64_t val);
+ status_t writeFloat(float val);
+ status_t writeDouble(double val);
+ status_t writeCString(const char* str);
+ status_t writeString8(const String8& str);
+ status_t writeString16(const String16& str);
+ status_t writeString16(const char16_t* str, size_t len);
+ status_t writeStrongBinder(const sp& val);
+ status_t writeWeakBinder(const wp& val);
+ status_t writeInt32Array(size_t len, const int32_t *val);
+ status_t writeByteArray(size_t len, const uint8_t *val);
+
+ template
+ status_t write(const Flattenable& val);
+
+ template
+ status_t write(const LightFlattenable& val);
+
+
+ // Place a native_handle into the parcel (the native_handle's file-
+ // descriptors are dup'ed, so it is safe to delete the native_handle
+ // when this function returns).
+ // Doesn't take ownership of the native_handle.
+ status_t writeNativeHandle(const native_handle* handle);
+
+ // Place a file descriptor into the parcel. The given fd must remain
+ // valid for the lifetime of the parcel.
+ // The Parcel does not take ownership of the given fd unless you ask it to.
+ status_t writeFileDescriptor(int fd, bool takeOwnership = false);
+
+ // Place a file descriptor into the parcel. A dup of the fd is made, which
+ // will be closed once the parcel is destroyed.
+ status_t writeDupFileDescriptor(int fd);
+
+ // Writes a blob to the parcel.
+ // If the blob is small, then it is stored in-place, otherwise it is
+ // transferred by way of an anonymous shared memory region. Prefer sending
+ // immutable blobs if possible since they may be subsequently transferred between
+ // processes without further copying whereas mutable blobs always need to be copied.
+ // The caller should call release() on the blob after writing its contents.
+ status_t writeBlob(size_t len, bool mutableCopy, WritableBlob* outBlob);
+
+ // Write an existing immutable blob file descriptor to the parcel.
+ // This allows the client to send the same blob to multiple processes
+ // as long as it keeps a dup of the blob file descriptor handy for later.
+ status_t writeDupImmutableBlobFileDescriptor(int fd);
+
+ status_t writeObject(const flat_binder_object& val, bool nullMetaData);
+
+ // Like Parcel.java's writeNoException(). Just writes a zero int32.
+ // Currently the native implementation doesn't do any of the StrictMode
+ // stack gathering and serialization that the Java implementation does.
+ status_t writeNoException();
+
+ void remove(size_t start, size_t amt);
+
+ status_t read(void* outData, size_t len) const;
+ const void* readInplace(size_t len) const;
+ int32_t readInt32() const;
+ status_t readInt32(int32_t *pArg) const;
+ uint32_t readUint32() const;
+ status_t readUint32(uint32_t *pArg) const;
+ int64_t readInt64() const;
+ status_t readInt64(int64_t *pArg) const;
+ uint64_t readUint64() const;
+ status_t readUint64(uint64_t *pArg) const;
+ float readFloat() const;
+ status_t readFloat(float *pArg) const;
+ double readDouble() const;
+ status_t readDouble(double *pArg) const;
+ intptr_t readIntPtr() const;
+ status_t readIntPtr(intptr_t *pArg) const;
+
+ const char* readCString() const;
+ String8 readString8() const;
+ String16 readString16() const;
+ const char16_t* readString16Inplace(size_t* outLen) const;
+ sp readStrongBinder() const;
+ wp readWeakBinder() const;
+
+ template
+ status_t read(Flattenable& val) const;
+
+ template
+ status_t read(LightFlattenable& val) const;
+
+ // Like Parcel.java's readExceptionCode(). Reads the first int32
+ // off of a Parcel's header, returning 0 or the negative error
+ // code on exceptions, but also deals with skipping over rich
+ // response headers. Callers should use this to read & parse the
+ // response headers rather than doing it by hand.
+ int32_t readExceptionCode() const;
+
+ // Retrieve native_handle from the parcel. This returns a copy of the
+ // parcel's native_handle (the caller takes ownership). The caller
+ // must free the native_handle with native_handle_close() and
+ // native_handle_delete().
+ native_handle* readNativeHandle() const;
+
+
+ // Retrieve a file descriptor from the parcel. This returns the raw fd
+ // in the parcel, which you do not own -- use dup() to get your own copy.
+ int readFileDescriptor() const;
+
+ // Reads a blob from the parcel.
+ // The caller should call release() on the blob after reading its contents.
+ status_t readBlob(size_t len, ReadableBlob* outBlob) const;
+
+ const flat_binder_object* readObject(bool nullMetaData) const;
+
+ // Explicitly close all file descriptors in the parcel.
+ void closeFileDescriptors();
+
+ // Debugging: get metrics on current allocations.
+ static size_t getGlobalAllocSize();
+ static size_t getGlobalAllocCount();
+
+private:
+ typedef void (*release_func)(Parcel* parcel,
+ const uint8_t* data, size_t dataSize,
+ const binder_size_t* objects, size_t objectsSize,
+ void* cookie);
+
+ uintptr_t ipcData() const;
+ size_t ipcDataSize() const;
+ uintptr_t ipcObjects() const;
+ size_t ipcObjectsCount() const;
+ void ipcSetDataReference(const uint8_t* data, size_t dataSize,
+ const binder_size_t* objects, size_t objectsCount,
+ release_func relFunc, void* relCookie);
+
+public:
+ void print(TextOutput& to, uint32_t flags = 0) const;
+
+private:
+ Parcel(const Parcel& o);
+ Parcel& operator=(const Parcel& o);
+
+ status_t finishWrite(size_t len);
+ void releaseObjects();
+ void acquireObjects();
+ status_t growData(size_t len);
+ status_t restartWrite(size_t desired);
+ status_t continueWrite(size_t desired);
+ status_t writePointer(uintptr_t val);
+ status_t readPointer(uintptr_t *pArg) const;
+ uintptr_t readPointer() const;
+ void freeDataNoInit();
+ void initState();
+ void scanForFds() const;
+
+ template
+ status_t readAligned(T *pArg) const;
+
+ template T readAligned() const;
+
+ template
+ status_t writeAligned(T val);
+
+ status_t mError;
+ uint8_t* mData;
+ size_t mDataSize;
+ size_t mDataCapacity;
+ mutable size_t mDataPos;
+ binder_size_t* mObjects;
+ size_t mObjectsSize;
+ size_t mObjectsCapacity;
+ mutable size_t mNextObjectHint;
+
+ mutable bool mFdsKnown;
+ mutable bool mHasFds;
+ bool mAllowFds;
+
+ release_func mOwner;
+ void* mOwnerCookie;
+
+ class Blob {
+ public:
+ Blob();
+ ~Blob();
+
+ void clear();
+ void release();
+ inline size_t size() const { return mSize; }
+ inline int fd() const { return mFd; };
+ inline bool isMutable() const { return mMutable; }
+
+ protected:
+ void init(int fd, void* data, size_t size, bool isMutable);
+
+ int mFd; // owned by parcel so not closed when released
+ void* mData;
+ size_t mSize;
+ bool mMutable;
+ };
+
+ class FlattenableHelperInterface {
+ protected:
+ ~FlattenableHelperInterface() { }
+ public:
+ virtual size_t getFlattenedSize() const = 0;
+ virtual size_t getFdCount() const = 0;
+ virtual status_t flatten(void* buffer, size_t size, int* fds, size_t count) const = 0;
+ virtual status_t unflatten(void const* buffer, size_t size, int const* fds, size_t count) = 0;
+ };
+
+ template
+ class FlattenableHelper : public FlattenableHelperInterface {
+ friend class Parcel;
+ const Flattenable& val;
+ explicit FlattenableHelper(const Flattenable& val) : val(val) { }
+
+ public:
+ virtual size_t getFlattenedSize() const {
+ return val.getFlattenedSize();
+ }
+ virtual size_t getFdCount() const {
+ return val.getFdCount();
+ }
+ virtual status_t flatten(void* buffer, size_t size, int* fds, size_t count) const {
+ return val.flatten(buffer, size, fds, count);
+ }
+ virtual status_t unflatten(void const* buffer, size_t size, int const* fds, size_t count) {
+ return const_cast&>(val).unflatten(buffer, size, fds, count);
+ }
+ };
+ status_t write(const FlattenableHelperInterface& val);
+ status_t read(FlattenableHelperInterface& val) const;
+
+public:
+ class ReadableBlob : public Blob {
+ friend class Parcel;
+ public:
+ inline const void* data() const { return mData; }
+ inline void* mutableData() { return isMutable() ? mData : NULL; }
+ };
+
+ class WritableBlob : public Blob {
+ friend class Parcel;
+ public:
+ inline void* data() { return mData; }
+ };
+
+#ifndef DISABLE_ASHMEM_TRACKING
+private:
+ size_t mOpenAshmemSize;
+#endif
+
+public:
+ // TODO: Remove once ABI can be changed.
+ size_t getBlobAshmemSize() const;
+ size_t getOpenAshmemSize() const;
+};
+
+// ---------------------------------------------------------------------------
+
+template
+status_t Parcel::write(const Flattenable& val) {
+ const FlattenableHelper helper(val);
+ return write(helper);
+}
+
+template
+status_t Parcel::write(const LightFlattenable