diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 52e456066c62905..000000000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,118 +0,0 @@ -version: 2 -jobs: - safety: - machine: - docker_layer_caching: true - steps: - - checkout - - run: - name: Build image - command: "docker build -t panda_safety -f tests/safety/Dockerfile ." - - run: - name: Run safety test - command: | - docker run panda_safety /bin/bash -c "cd /openpilot/panda/tests/safety; PYTHONPATH=/openpilot ./test.sh" - - misra-c2012: - machine: - docker_layer_caching: true - steps: - - checkout - - run: - name: Build image - command: "docker build -t panda_misra -f tests/misra/Dockerfile ." - - run: - name: Run Misra C 2012 test - 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/misra_output.txt - - build: - machine: - docker_layer_caching: true - steps: - - checkout - - run: - name: Build image - command: "docker build -t panda_build -f tests/build/Dockerfile ." - - run: - name: Test python package installer - command: | - docker run panda_build /bin/bash -c "cd /panda; python setup.py install" - - run: - name: Build Panda STM image - command: | - docker run panda_build /bin/bash -c "cd /panda/board; make bin" - - run: - name: Build Panda STM bootstub image - command: | - docker run panda_build /bin/bash -c "cd /panda/board; make obj/bootstub.panda.bin" - - run: - name: Build Pedal STM image - command: | - docker run panda_build /bin/bash -c "cd /panda/board/pedal; make obj/comma.bin" - - run: - name: Build Pedal STM bootstub image - command: | - docker run panda_build /bin/bash -c "cd /panda/board/pedal; make obj/bootstub.bin" - - run: - name: Build ESP image - command: | - docker run panda_build /bin/bash -c "cd /panda/boardesp; ./get_sdk.sh; 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" - - language_check: - machine: - docker_layer_caching: true - steps: - - checkout - - run: - name: Build image - command: "docker build -t language_check -f tests/language/Dockerfile ." - - run: - name: Check code for bad language - command: | - docker run language_check /bin/bash -c "cd /panda/tests/language; ./test_language.py" - - linter_python: - machine: - docker_layer_caching: true - steps: - - checkout - - run: - name: Build image - command: "docker build -t linter_python -f tests/linter_python/Dockerfile ." - - run: - name: Run linter python test - command: | - docker run linter_python /bin/bash -c "cd /panda/tests/linter_python; PYTHONPATH=/ ./flake8_panda.sh" - docker run linter_python /bin/bash -c "cd /panda/tests/linter_python; PYTHONPATH=/ ./pylint_panda.sh" - -workflows: - version: 2 - main: - jobs: - - safety - - misra-c2012 - - build - - safety_replay - - language_check - - linter_python diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 000000000000000..fd7d57cc47b0b4e --- /dev/null +++ b/.github/workflows/test.yaml @@ -0,0 +1,129 @@ +name: panda tests +on: [push, pull_request] + +env: + RUN: docker run --rm panda /bin/bash -c + PERSIST: docker run --name panda panda /bin/sh -c + BUILD: | + docker pull $(grep -ioP '(?<=^from)\s+\S+' Dockerfile.panda) || true + docker pull docker.io/commaai/panda:latest || true + docker build --cache-from docker.io/commaai/panda:latest -t panda -f Dockerfile.panda . + +jobs: + docker_push: + name: docker push + runs-on: ubuntu-16.04 + timeout-minutes: 45 + if: github.ref == 'refs/heads/master' && github.event_name != 'pull_request' && github.repository == 'commaai/panda' + steps: + - uses: actions/checkout@v2 + - name: Build Docker image + run: eval "$BUILD" + - name: Login to dockerhub + run: docker login -u wmelching -p ${{ secrets.DOCKERHUB_TOKEN }} + - name: Tag image + run: docker tag panda docker.io/commaai/panda:latest + - name: Push image + run: docker push docker.io/commaai/panda:latest + + build: + name: build + runs-on: ubuntu-16.04 + timeout-minutes: 45 + steps: + - uses: actions/checkout@v2 + - name: Build Docker image + run: eval "$BUILD" + - name: Test python package installer + run: $RUN "cd /tmp/openpilot/panda && python setup.py install" + - name: Build panda STM image + run: $RUN "cd /tmp/openpilot/panda/board && make bin" + - name: Build panda STM bootstub image + run: $RUN "cd /tmp/openpilot/panda/board && make obj/bootstub.panda.bin" + - name: Build pedal STM image + run: $RUN "cd /tmp/openpilot/panda/board/pedal && make obj/comma.bin" + - name: Build pedal STM bootstub image + run: $RUN "cd /tmp/openpilot/panda/board/pedal && make obj/bootstub.bin" + + build_esp: + name: build esp + runs-on: ubuntu-16.04 + timeout-minutes: 45 + steps: + - uses: actions/checkout@v2 + - name: Build docker image + run: | + docker pull $(grep -ioP '(?<=^from)\s+\S+' tests/build/Dockerfile.panda_esp) || true + docker pull docker.io/commaai/panda_esp:latest || true + docker build --cache-from docker.io/commaai/panda_esp:latest -t panda_esp -f tests/build/Dockerfile.panda_esp . + - name: Build ESP image + run: docker run --rm panda_esp /bin/sh -c "cd /panda/boardesp && make user1.bin" + - name: Push image + if: github.ref == 'refs/heads/master' && github.event_name != 'pull_request' && github.repository == 'commaai/panda' + run: | + docker login -u wmelching -p ${{ secrets.DOCKERHUB_TOKEN }} + docker tag panda_esp docker.io/commaai/panda_esp:latest + docker push docker.io/commaai/panda_esp:latest + + safety: + name: safety + runs-on: ubuntu-16.04 + timeout-minutes: 45 + steps: + - uses: actions/checkout@v2 + - name: Build Docker image + run: eval "$BUILD" + - name: Run safety tests + run: | + $RUN "cd /tmp/openpilot && \ + scons -c && \ + scons -j$(nproc) opendbc/ cereal/ && \ + cd panda/tests/safety && \ + ./test.sh" + + safety_replay: + name: safety replay + runs-on: ubuntu-16.04 + timeout-minutes: 45 + steps: + - uses: actions/checkout@v2 + - name: Build Docker image + run: eval "$BUILD" + - name: Run safety replay + run: $RUN "cd /tmp/openpilot/panda/tests/safety_replay && ./test_safety_replay.py" + + misra: + name: misra c2012 + runs-on: ubuntu-16.04 + timeout-minutes: 45 + steps: + - uses: actions/checkout@v2 + - name: Build Docker image + run: eval "$BUILD" + - name: Run Misra C 2012 analysis + run: $PERSIST "cd /tmp/openpilot/panda/tests/misra && ./test_misra.sh" + - name: Copy analysis outputs + run: docker cp panda:/tmp/misra /tmp + - uses: actions/upload-artifact@v2 + if: always() + with: + name: cppcheck.txt + path: /tmp/misra/cppcheck_output.txt + - uses: actions/upload-artifact@v2 + if: always() + with: + name: misra.txt + path: /tmp/misra/misra_output.txt + + python_linter: + name: python linter + runs-on: ubuntu-16.04 + timeout-minutes: 45 + steps: + - uses: actions/checkout@v2 + - name: Build Docker image + run: eval "$BUILD" + - name: Run linters + run: | + $RUN "cd /tmp/openpilot/panda/tests/linter_python/ && ./flake8_panda.sh" + $RUN "cd /tmp/openpilot/panda/tests/linter_python/ && ./pylint_panda.sh" diff --git a/Dockerfile.panda b/Dockerfile.panda new file mode 100644 index 000000000000000..bcae97319958500 --- /dev/null +++ b/Dockerfile.panda @@ -0,0 +1,64 @@ +FROM ubuntu:16.04 +ENV PYTHONUNBUFFERED 1 +ENV PYTHONPATH /tmp/openpilot:$PYTHONPATH + +RUN apt-get update && apt-get install -y --no-install-recommends \ + autoconf \ + automake \ + bzip2 \ + capnproto \ + clang \ + curl \ + g++ \ + gcc-arm-none-eabi libnewlib-arm-none-eabi \ + git \ + libarchive-dev \ + libavformat-dev libavcodec-dev libavdevice-dev libavutil-dev libswscale-dev libavresample-dev libavfilter-dev \ + libbz2-dev \ + libcapnp-dev \ + libcurl4-openssl-dev \ + libffi-dev \ + libtool \ + libssl-dev \ + libusb-1.0-0 \ + libzmq3-dev \ + locales \ + make \ + pkg-config \ + python \ + python-dev \ + python-pip \ + unzip \ + wget \ + zlib1g-dev \ + && rm -rf /var/lib/apt/lists/* + +RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL en_US.UTF-8 + +RUN curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash +ENV PATH="/root/.pyenv/bin:/root/.pyenv/shims:${PATH}" + +COPY requirements.txt /tmp/ +RUN pyenv install 3.7.3 && \ + pyenv global 3.7.3 && \ + pyenv rehash && \ + pip install --no-cache-dir --upgrade pip==18.0 && \ + pip install --no-cache-dir -r /tmp/requirements.txt + +RUN cd /tmp && \ + git clone https://github.com/commaai/openpilot.git tmppilot || true && \ + cd /tmp/tmppilot && \ + git pull && git checkout 44560b5bb74e451767725144c3fa5f1564481a20 && \ + git submodule update --init cereal opendbc && \ + mkdir /tmp/openpilot && \ + cp -pR SConstruct tools/ selfdrive/ common/ cereal/ opendbc/ /tmp/openpilot && \ + rm -rf /tmp/tmppilot + +RUN cd /tmp/openpilot && \ + pip install --no-cache-dir -r opendbc/requirements.txt && \ + pip install --no-cache-dir -r tools/requirements.txt + +COPY . /tmp/openpilot/panda diff --git a/README.md b/README.md index 9979295a0b2834a..55b30f5528fdf95 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ It uses an [STM32F413](http://www.st.com/en/microcontrollers/stm32f413-423.html? It is 2nd gen hardware, reusing code and parts from the [NEO](https://github.com/commaai/neo) interface board. -[![CircleCI](https://circleci.com/gh/commaai/panda.svg?style=svg)](https://circleci.com/gh/commaai/panda) +![panda tests](https://github.com/commaai/panda/workflows/panda%20tests/badge.svg) Usage (Python) ------ @@ -99,7 +99,7 @@ When compiled from an [EON Dev Kit](https://comma.ai/shop/products/eon-gold-dash conjuction with [openpilot](https://github.com/commaai/openpilot). The panda FW, through its safety model, provides and enforces the [openpilot Safety](https://github.com/commaai/openpilot/blob/devel/SAFETY.md). Due to its critical function, it's important that the application code rigor within the `board` folder is held to high standards. -These are the [CI regression tests](https://circleci.com/gh/commaai/panda) we have in place: +These are the [CI regression tests](https://github.com/commaai/panda/actions) we have in place: * A generic static code analysis is performed by [Cppcheck](https://github.com/danmar/cppcheck/). * In addition, [Cppcheck](https://github.com/danmar/cppcheck/) has a specific addon to check for [MISRA C:2012](https://www.misra.org.uk/MISRAHome/MISRAC2012/tabid/196/Default.aspx) violations. See [current coverage](https://github.com/commaai/panda/blob/master/tests/misra/coverage_table). * Compiler options are relatively strict: the flags `-Wall -Wextra -Wstrict-prototypes -Werror` are enforced on board and pedal makefiles. diff --git a/board/board.h b/board/board.h index 30e1fa4d17a51ea..28516299c85d738 100644 --- a/board/board.h +++ b/board/board.h @@ -13,6 +13,7 @@ #include "boards/grey.h" #include "boards/black.h" #include "boards/uno.h" + #include "boards/dos.h" #else #include "boards/pedal.h" #endif @@ -22,7 +23,10 @@ void detect_board_type(void) { // SPI lines floating: white (TODO: is this reliable? Not really, we have to enable ESP/GPS to be able to detect this on the UART) set_gpio_output(GPIOC, 14, 1); set_gpio_output(GPIOC, 5, 1); - if((detect_with_pull(GPIOA, 4, PULL_DOWN)) || (detect_with_pull(GPIOA, 5, PULL_DOWN)) || (detect_with_pull(GPIOA, 6, PULL_DOWN)) || (detect_with_pull(GPIOA, 7, PULL_DOWN))){ + if(!detect_with_pull(GPIOB, 1, PULL_UP)){ + hw_type = HW_TYPE_DOS; + current_board = &board_dos; + } else if((detect_with_pull(GPIOA, 4, PULL_DOWN)) || (detect_with_pull(GPIOA, 5, PULL_DOWN)) || (detect_with_pull(GPIOA, 6, PULL_DOWN)) || (detect_with_pull(GPIOA, 7, PULL_DOWN))){ hw_type = HW_TYPE_WHITE_PANDA; current_board = &board_white; } else if(detect_with_pull(GPIOA, 13, PULL_DOWN)) { // Rev AB deprecated, so no pullup means black. In REV C, A13 is pulled up to 5V with a 10K @@ -78,7 +82,7 @@ bool board_has_gmlan(void) { } bool board_has_obd(void) { - return ((hw_type == HW_TYPE_BLACK_PANDA) || (hw_type == HW_TYPE_UNO)); + return ((hw_type == HW_TYPE_BLACK_PANDA) || (hw_type == HW_TYPE_UNO) || (hw_type == HW_TYPE_DOS)); } bool board_has_lin(void) { @@ -86,9 +90,9 @@ bool board_has_lin(void) { } bool board_has_rtc(void) { - return (hw_type == HW_TYPE_UNO); + return ((hw_type == HW_TYPE_UNO) || (hw_type == HW_TYPE_DOS)); } bool board_has_relay(void) { - return ((hw_type == HW_TYPE_BLACK_PANDA) || (hw_type == HW_TYPE_UNO)); + return ((hw_type == HW_TYPE_BLACK_PANDA) || (hw_type == HW_TYPE_UNO) || (hw_type == HW_TYPE_DOS)); } diff --git a/board/board_declarations.h b/board/board_declarations.h index d973551bafc2e04..d5e9e06a8c5991b 100644 --- a/board/board_declarations.h +++ b/board/board_declarations.h @@ -39,6 +39,7 @@ struct board { #define HW_TYPE_BLACK_PANDA 3U #define HW_TYPE_PEDAL 4U #define HW_TYPE_UNO 5U +#define HW_TYPE_DOS 6U // LED colors #define LED_RED 0U diff --git a/board/boards/dos.h b/board/boards/dos.h new file mode 100644 index 000000000000000..afccd373da2e7d9 --- /dev/null +++ b/board/boards/dos.h @@ -0,0 +1,224 @@ +// ///////////// // +// Dos + Harness // +// ///////////// // + +void dos_enable_can_transciever(uint8_t transciever, bool enabled) { + switch (transciever){ + case 1U: + set_gpio_output(GPIOC, 1, !enabled); + break; + case 2U: + set_gpio_output(GPIOC, 13, !enabled); + break; + case 3U: + set_gpio_output(GPIOA, 0, !enabled); + break; + case 4U: + set_gpio_output(GPIOB, 10, !enabled); + break; + default: + puts("Invalid CAN transciever ("); puth(transciever); puts("): enabling failed\n"); + break; + } +} + +void dos_enable_can_transcievers(bool enabled) { + for(uint8_t i=1U; i<=4U; i++){ + // Leave main CAN always on for CAN-based ignition detection + if((car_harness_status == HARNESS_STATUS_FLIPPED) ? (i == 3U) : (i == 1U)){ + uno_enable_can_transciever(i, true); + } else { + uno_enable_can_transciever(i, enabled); + } + } +} + +void dos_set_led(uint8_t color, bool enabled) { + switch (color){ + case LED_RED: + set_gpio_output(GPIOC, 9, !enabled); + break; + case LED_GREEN: + set_gpio_output(GPIOC, 7, !enabled); + break; + case LED_BLUE: + set_gpio_output(GPIOC, 6, !enabled); + break; + default: + break; + } +} + +void dos_set_gps_load_switch(bool enabled) { + UNUSED(enabled); +} + +void dos_set_bootkick(bool enabled){ + UNUSED(enabled); +} + +void dos_bootkick(void) {} + +void dos_set_phone_power(bool enabled){ + UNUSED(enabled); +} + +void dos_set_usb_power_mode(uint8_t mode) { + UNUSED(mode); +} + +void dos_set_esp_gps_mode(uint8_t mode) { + UNUSED(mode); +} + +void dos_set_can_mode(uint8_t mode){ + switch (mode) { + case CAN_MODE_NORMAL: + case CAN_MODE_OBD_CAN2: + if ((bool)(mode == CAN_MODE_NORMAL) != (bool)(car_harness_status == HARNESS_STATUS_FLIPPED)) { + // B12,B13: disable OBD mode + set_gpio_mode(GPIOB, 12, MODE_INPUT); + set_gpio_mode(GPIOB, 13, MODE_INPUT); + + // B5,B6: normal CAN2 mode + set_gpio_alternate(GPIOB, 5, GPIO_AF9_CAN2); + set_gpio_alternate(GPIOB, 6, GPIO_AF9_CAN2); + } else { + // B5,B6: disable normal CAN2 mode + set_gpio_mode(GPIOB, 5, MODE_INPUT); + set_gpio_mode(GPIOB, 6, MODE_INPUT); + + // B12,B13: OBD mode + set_gpio_alternate(GPIOB, 12, GPIO_AF9_CAN2); + set_gpio_alternate(GPIOB, 13, GPIO_AF9_CAN2); + } + break; + default: + puts("Tried to set unsupported CAN mode: "); puth(mode); puts("\n"); + break; + } +} + +void dos_usb_power_mode_tick(uint32_t uptime){ + UNUSED(uptime); + if(bootkick_timer != 0U){ + bootkick_timer--; + } else { + dos_set_bootkick(false); + } +} + +bool dos_check_ignition(void){ + // ignition is checked through harness + return harness_check_ignition(); +} + +void dos_set_usb_switch(bool phone){ + set_gpio_output(GPIOB, 3, phone); +} + +void dos_set_ir_power(uint8_t percentage){ + pwm_set(TIM4, 2, percentage); +} + +void dos_set_fan_power(uint8_t percentage){ + // Enable fan power only if percentage is non-zero. + set_gpio_output(GPIOA, 1, (percentage != 0U)); + fan_set_power(percentage); +} + +uint32_t dos_read_current(void){ + // No current sense on Dos + return 0U; +} + +void dos_init(void) { + common_init_gpio(); + + // A8,A15: normal CAN3 mode + set_gpio_alternate(GPIOA, 8, GPIO_AF11_CAN3); + set_gpio_alternate(GPIOA, 15, GPIO_AF11_CAN3); + + // C0: OBD_SBU1 (orientation detection) + // C3: OBD_SBU2 (orientation detection) + set_gpio_mode(GPIOC, 0, MODE_ANALOG); + set_gpio_mode(GPIOC, 3, MODE_ANALOG); + + // C10: OBD_SBU1_RELAY (harness relay driving output) + // C11: OBD_SBU2_RELAY (harness relay driving output) + set_gpio_mode(GPIOC, 10, MODE_OUTPUT); + set_gpio_mode(GPIOC, 11, MODE_OUTPUT); + set_gpio_output_type(GPIOC, 10, OUTPUT_TYPE_OPEN_DRAIN); + set_gpio_output_type(GPIOC, 11, OUTPUT_TYPE_OPEN_DRAIN); + set_gpio_output(GPIOC, 10, 1); + set_gpio_output(GPIOC, 11, 1); + + // C8: FAN PWM aka TIM3_CH3 + set_gpio_alternate(GPIOC, 8, GPIO_AF2_TIM3); + + // Initialize IR PWM and set to 0% + set_gpio_alternate(GPIOB, 7, GPIO_AF2_TIM4); + pwm_init(TIM4, 2); + dos_set_ir_power(0U); + + // Initialize fan and set to 0% + fan_init(); + dos_set_fan_power(0U); + + // Initialize harness + harness_init(); + + // Initialize RTC + rtc_init(); + + // Enable CAN transcievers + dos_enable_can_transcievers(true); + + // Disable LEDs + dos_set_led(LED_RED, false); + dos_set_led(LED_GREEN, false); + dos_set_led(LED_BLUE, false); + + // Set normal CAN mode + dos_set_can_mode(CAN_MODE_NORMAL); + + // flip CAN0 and CAN2 if we are flipped + if (car_harness_status == HARNESS_STATUS_FLIPPED) { + can_flip_buses(0, 2); + } + + // init multiplexer + can_set_obd(car_harness_status, false); +} + +const harness_configuration dos_harness_config = { + .has_harness = true, + .GPIO_SBU1 = GPIOC, + .GPIO_SBU2 = GPIOC, + .GPIO_relay_SBU1 = GPIOC, + .GPIO_relay_SBU2 = GPIOC, + .pin_SBU1 = 0, + .pin_SBU2 = 3, + .pin_relay_SBU1 = 10, + .pin_relay_SBU2 = 11, + .adc_channel_SBU1 = 10, + .adc_channel_SBU2 = 13 +}; + +const board board_dos = { + .board_type = "Dos", + .harness_config = &dos_harness_config, + .init = dos_init, + .enable_can_transciever = dos_enable_can_transciever, + .enable_can_transcievers = dos_enable_can_transcievers, + .set_led = dos_set_led, + .set_usb_power_mode = dos_set_usb_power_mode, + .set_esp_gps_mode = dos_set_esp_gps_mode, + .set_can_mode = dos_set_can_mode, + .usb_power_mode_tick = dos_usb_power_mode_tick, + .check_ignition = dos_check_ignition, + .read_current = dos_read_current, + .set_fan_power = dos_set_fan_power, + .set_ir_power = dos_set_ir_power, + .set_phone_power = dos_set_phone_power +}; diff --git a/board/drivers/llcan.h b/board/drivers/llcan.h index e467d67bc164ae4..0e331526444b177 100644 --- a/board/drivers/llcan.h +++ b/board/drivers/llcan.h @@ -14,6 +14,7 @@ #define GET_BYTE(msg, b) (((int)(b) > 3) ? (((msg)->RDHR >> (8U * ((unsigned int)(b) % 4U))) & 0xFFU) : (((msg)->RDLR >> (8U * (unsigned int)(b))) & 0xFFU)) #define GET_BYTES_04(msg) ((msg)->RDLR) #define GET_BYTES_48(msg) ((msg)->RDHR) +#define GET_FLAG(value, mask) (((__typeof__(mask))param & mask) == mask) #define CAN_INIT_TIMEOUT_MS 500U #define CAN_NAME_FROM_CANIF(CAN_DEV) (((CAN_DEV)==CAN1) ? "CAN1" : (((CAN_DEV) == CAN2) ? "CAN2" : "CAN3")) diff --git a/board/safety.h b/board/safety.h index d2d107d66a2772d..ebe81f92c55a3ad 100644 --- a/board/safety.h +++ b/board/safety.h @@ -72,10 +72,14 @@ void gen_crc_lookup_table(uint8_t poly, uint8_t crc_lut[]) { } } -bool msg_allowed(int addr, int bus, const AddrBus addr_list[], int len) { +bool msg_allowed(CAN_FIFOMailBox_TypeDef *to_send, const CanMsg msg_list[], int len) { + int addr = GET_ADDR(to_send); + int bus = GET_BUS(to_send); + int length = GET_LEN(to_send); + bool allowed = false; for (int i = 0; i < len; i++) { - if ((addr == addr_list[i].addr) && (bus == addr_list[i].bus)) { + if ((addr == msg_list[i].addr) && (bus == msg_list[i].bus) && (length == msg_list[i].len)) { allowed = true; break; } @@ -92,11 +96,13 @@ uint32_t get_ts_elapsed(uint32_t ts, uint32_t ts_last) { int get_addr_check_index(CAN_FIFOMailBox_TypeDef *to_push, AddrCheckStruct addr_list[], const int len) { int bus = GET_BUS(to_push); int addr = GET_ADDR(to_push); + int length = GET_LEN(to_push); int index = -1; for (int i = 0; i < len; i++) { - for (uint8_t j = 0U; addr_list[i].addr[j] != 0; j++) { - if ((addr == addr_list[i].addr[j]) && (bus == addr_list[i].bus)) { + for (uint8_t j = 0U; addr_list[i].msg[j].addr != 0; j++) { + if ((addr == addr_list[i].msg[j].addr) && (bus == addr_list[i].msg[j].bus) && + (length == addr_list[i].msg[j].len)) { index = i; goto Return; } @@ -209,13 +215,13 @@ const safety_hook_config safety_hook_registry[] = { {SAFETY_CHRYSLER, &chrysler_hooks}, {SAFETY_SUBARU, &subaru_hooks}, {SAFETY_SUBARU_LEGACY, &subaru_legacy_hooks}, - {SAFETY_MAZDA, &mazda_hooks}, {SAFETY_VOLKSWAGEN_MQB, &volkswagen_mqb_hooks}, {SAFETY_VOLKSWAGEN_PQ, &volkswagen_pq_hooks}, + {SAFETY_NISSAN, &nissan_hooks}, {SAFETY_NOOUTPUT, &nooutput_hooks}, #ifdef ALLOW_DEBUG + {SAFETY_MAZDA, &mazda_hooks}, {SAFETY_TESLA, &tesla_hooks}, - {SAFETY_NISSAN, &nissan_hooks}, {SAFETY_ALLOUTPUT, &alloutput_hooks}, {SAFETY_GM_ASCM, &gm_ascm_hooks}, {SAFETY_FORD, &ford_hooks}, diff --git a/board/safety/safety_chrysler.h b/board/safety/safety_chrysler.h index 82fcfb1495d5794..59d8af69b5fbbec 100644 --- a/board/safety/safety_chrysler.h +++ b/board/safety/safety_chrysler.h @@ -6,15 +6,14 @@ const int CHRYSLER_MAX_RATE_DOWN = 3; const int CHRYSLER_MAX_TORQUE_ERROR = 80; // max torque cmd in excess of torque motor const int CHRYSLER_GAS_THRSLD = 30; // 7% more than 2m/s const int CHRYSLER_STANDSTILL_THRSLD = 10; // about 1m/s -const AddrBus CHRYSLER_TX_MSGS[] = {{571, 0}, {658, 0}, {678, 0}}; +const CanMsg CHRYSLER_TX_MSGS[] = {{571, 0, 3}, {658, 0, 6}, {678, 0, 8}}; -// TODO: do checksum and counter checks AddrCheckStruct chrysler_rx_checks[] = { - {.addr = {544}, .bus = 0, .check_checksum = true, .max_counter = 15U, .expected_timestep = 10000U}, - {.addr = {514}, .bus = 0, .check_checksum = false, .max_counter = 0U, .expected_timestep = 10000U}, - {.addr = {500}, .bus = 0, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, - {.addr = {308}, .bus = 0, .check_checksum = false, .max_counter = 15U, .expected_timestep = 20000U}, - {.addr = {320}, .bus = 0, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, + {.msg = {{544, 0, 8}}, .check_checksum = true, .max_counter = 15U, .expected_timestep = 10000U}, + {.msg = {{514, 0, 8}}, .check_checksum = false, .max_counter = 0U, .expected_timestep = 10000U}, + {.msg = {{500, 0, 8}}, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, + {.msg = {{308, 0, 8}}, .check_checksum = false, .max_counter = 15U, .expected_timestep = 20000U}, + {.msg = {{320, 0, 8}}, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, }; const int CHRYSLER_RX_CHECK_LEN = sizeof(chrysler_rx_checks) / sizeof(chrysler_rx_checks[0]); @@ -132,9 +131,8 @@ static int chrysler_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { int tx = 1; int addr = GET_ADDR(to_send); - int bus = GET_BUS(to_send); - if (!msg_allowed(addr, bus, CHRYSLER_TX_MSGS, sizeof(CHRYSLER_TX_MSGS) / sizeof(CHRYSLER_TX_MSGS[0]))) { + if (!msg_allowed(to_send, CHRYSLER_TX_MSGS, sizeof(CHRYSLER_TX_MSGS) / sizeof(CHRYSLER_TX_MSGS[0]))) { tx = 0; } diff --git a/board/safety/safety_gm.h b/board/safety/safety_gm.h index 264df31323c2a96..da1acd499e8bae5 100644 --- a/board/safety/safety_gm.h +++ b/board/safety/safety_gm.h @@ -18,18 +18,18 @@ const int GM_DRIVER_TORQUE_FACTOR = 4; const int GM_MAX_GAS = 3072; const int GM_MAX_REGEN = 1404; const int GM_MAX_BRAKE = 350; -const AddrBus GM_TX_MSGS[] = {{384, 0}, {1033, 0}, {1034, 0}, {715, 0}, {880, 0}, // pt bus - {161, 1}, {774, 1}, {776, 1}, {784, 1}, // obs bus - {789, 2}, // ch bus - {0x104c006c, 3}, {0x10400060, 3}}; // gmlan +const CanMsg GM_TX_MSGS[] = {{384, 0, 4}, {1033, 0, 7}, {1034, 0, 7}, {715, 0, 8}, {880, 0, 6}, // pt bus + {161, 1, 7}, {774, 1, 8}, {776, 1, 7}, {784, 1, 2}, // obs bus + {789, 2, 5}, // ch bus + {0x104c006c, 3, 3}, {0x10400060, 3, 5}}; // gmlan // TODO: do checksum and counter checks. Add correct timestep, 0.1s for now. AddrCheckStruct gm_rx_checks[] = { - {.addr = {388}, .bus = 0, .expected_timestep = 100000U}, - {.addr = {842}, .bus = 0, .expected_timestep = 100000U}, - {.addr = {481}, .bus = 0, .expected_timestep = 100000U}, - {.addr = {241}, .bus = 0, .expected_timestep = 100000U}, - {.addr = {417}, .bus = 0, .expected_timestep = 100000U}, + {.msg = {{388, 0, 8}}, .expected_timestep = 100000U}, + {.msg = {{842, 0, 5}}, .expected_timestep = 100000U}, + {.msg = {{481, 0, 7}}, .expected_timestep = 100000U}, + {.msg = {{241, 0, 6}}, .expected_timestep = 100000U}, + {.msg = {{417, 0, 7}}, .expected_timestep = 100000U}, }; const int GM_RX_CHECK_LEN = sizeof(gm_rx_checks) / sizeof(gm_rx_checks[0]); @@ -122,9 +122,8 @@ static int gm_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { int tx = 1; int addr = GET_ADDR(to_send); - int bus = GET_BUS(to_send); - if (!msg_allowed(addr, bus, GM_TX_MSGS, sizeof(GM_TX_MSGS)/sizeof(GM_TX_MSGS[0]))) { + if (!msg_allowed(to_send, GM_TX_MSGS, sizeof(GM_TX_MSGS)/sizeof(GM_TX_MSGS[0]))) { tx = 0; } diff --git a/board/safety/safety_honda.h b/board/safety/safety_honda.h index 9f09da95375e053..3ee1a73d37ff377 100644 --- a/board/safety/safety_honda.h +++ b/board/safety/safety_honda.h @@ -6,9 +6,11 @@ // accel rising edge // brake rising edge // brake > 0mph -const AddrBus HONDA_N_TX_MSGS[] = {{0xE4, 0}, {0x194, 0}, {0x1FA, 0}, {0x200, 0}, {0x30C, 0}, {0x33D, 0}}; -const AddrBus HONDA_BG_TX_MSGS[] = {{0xE4, 2}, {0xE5, 2}, {0x296, 0}, {0x33D, 2}}; // Bosch Giraffe -const AddrBus HONDA_BH_TX_MSGS[] = {{0xE4, 0}, {0xE5, 0}, {0x296, 1}, {0x33D, 0}}; // Bosch Harness +const CanMsg HONDA_N_TX_MSGS[] = {{0xE4, 0, 5}, {0x194, 0, 4}, {0x1FA, 0, 8}, {0x200, 0, 6}, {0x30C, 0, 8}, {0x33D, 0, 5}}; +const CanMsg HONDA_BG_TX_MSGS[] = {{0xE4, 2, 5}, {0xE5, 2, 8}, {0x296, 0, 4}, {0x33D, 2, 5}}; // Bosch Giraffe +const CanMsg HONDA_BH_TX_MSGS[] = {{0xE4, 0, 5}, {0xE5, 0, 8}, {0x296, 1, 4}, {0x33D, 0, 5}}; // Bosch Harness +const CanMsg HONDA_BG_LONG_TX_MSGS[] = {{0xE4, 0, 5}, {0x1DF, 0, 8}, {0x1EF, 0, 8}, {0x1FA, 0, 8}, {0x30C, 0, 8}, {0x33D, 0, 5}, {0x39F, 0, 8}, {0x18DAB0F1, 0, 8}}; // Bosch Giraffe w/ gas and brakes +const CanMsg HONDA_BH_LONG_TX_MSGS[] = {{0xE4, 1, 5}, {0x1DF, 1, 8}, {0x1EF, 1, 8}, {0x1FA, 1, 8}, {0x30C, 1, 8}, {0x33D, 1, 5}, {0x39F, 1, 8}, {0x18DAB0F1, 1, 8}}; // Bosch Harness w/ gas and brakes // Roughly calculated using the offsets in openpilot +5%: // In openpilot: ((gas1_norm + gas2_norm)/2) > 15 @@ -18,26 +20,33 @@ const AddrBus HONDA_BH_TX_MSGS[] = {{0xE4, 0}, {0xE5, 0}, {0x296, 1}, {0x33D, 0} // In this safety: ((gas1 + (gas2/2))/2) > THRESHOLD const int HONDA_GAS_INTERCEPTOR_THRESHOLD = 344; #define HONDA_GET_INTERCEPTOR(msg) (((GET_BYTE((msg), 0) << 8) + GET_BYTE((msg), 1) + ((GET_BYTE((msg), 2) << 8) + GET_BYTE((msg), 3)) / 2 ) / 2) // avg between 2 tracks +const int HONDA_BOSCH_NO_GAS_VALUE = -30000; // value sent when not requesting gas +const int HONDA_BOSCH_GAS_MAX = 2000; +const int HONDA_BOSCH_ACCEL_MIN = -350; // max braking == -3.5m/s2 // Nidec and Bosch giraffe have pt on bus 0 AddrCheckStruct honda_rx_checks[] = { - {.addr = {0x1A6, 0x296}, .bus = 0, .check_checksum = true, .max_counter = 3U, .expected_timestep = 40000U}, - {.addr = { 0x158}, .bus = 0, .check_checksum = true, .max_counter = 3U, .expected_timestep = 10000U}, - {.addr = { 0x17C}, .bus = 0, .check_checksum = true, .max_counter = 3U, .expected_timestep = 10000U}, + {.msg = {{0x1A6, 0, 8}, {0x296, 0, 4}}, .check_checksum = true, .max_counter = 3U, .expected_timestep = 40000U}, + {.msg = {{0x158, 0, 8}}, .check_checksum = true, .max_counter = 3U, .expected_timestep = 10000U}, + {.msg = {{0x17C, 0, 8}}, .check_checksum = true, .max_counter = 3U, .expected_timestep = 10000U}, }; const int HONDA_RX_CHECKS_LEN = sizeof(honda_rx_checks) / sizeof(honda_rx_checks[0]); // Bosch harness has pt on bus 1 AddrCheckStruct honda_bh_rx_checks[] = { - {.addr = {0x296}, .bus = 1, .check_checksum = true, .max_counter = 3U, .expected_timestep = 40000U}, - {.addr = {0x158}, .bus = 1, .check_checksum = true, .max_counter = 3U, .expected_timestep = 10000U}, - {.addr = {0x17C}, .bus = 1, .check_checksum = true, .max_counter = 3U, .expected_timestep = 10000U}, + {.msg = {{0x296, 1, 4}}, .check_checksum = true, .max_counter = 3U, .expected_timestep = 40000U}, + {.msg = {{0x158, 1, 8}}, .check_checksum = true, .max_counter = 3U, .expected_timestep = 10000U}, + {.msg = {{0x17C, 1, 8}}, .check_checksum = true, .max_counter = 3U, .expected_timestep = 10000U}, }; const int HONDA_BH_RX_CHECKS_LEN = sizeof(honda_bh_rx_checks) / sizeof(honda_bh_rx_checks[0]); +const uint16_t HONDA_PARAM_ALT_BRAKE = 1; +const uint16_t HONDA_PARAM_BOSCH_LONG = 2; + int honda_brake = 0; bool honda_alt_brake_msg = false; bool honda_fwd_brake = false; +bool honda_bosch_long = false; enum {HONDA_N_HW, HONDA_BG_HW, HONDA_BH_HW} honda_hw = HONDA_N_HW; @@ -191,12 +200,16 @@ static int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { int addr = GET_ADDR(to_send); int bus = GET_BUS(to_send); - if (honda_hw == HONDA_BG_HW) { - tx = msg_allowed(addr, bus, HONDA_BG_TX_MSGS, sizeof(HONDA_BG_TX_MSGS)/sizeof(HONDA_BG_TX_MSGS[0])); - } else if (honda_hw == HONDA_BH_HW) { - tx = msg_allowed(addr, bus, HONDA_BH_TX_MSGS, sizeof(HONDA_BH_TX_MSGS)/sizeof(HONDA_BH_TX_MSGS[0])); + if ((honda_hw == HONDA_BG_HW) && !honda_bosch_long) { + tx = msg_allowed(to_send, HONDA_BG_TX_MSGS, sizeof(HONDA_BG_TX_MSGS)/sizeof(HONDA_BG_TX_MSGS[0])); + } else if ((honda_hw == HONDA_BG_HW) && honda_bosch_long) { + tx = msg_allowed(to_send, HONDA_BG_LONG_TX_MSGS, sizeof(HONDA_BG_LONG_TX_MSGS)/sizeof(HONDA_BG_LONG_TX_MSGS[0])); + } else if ((honda_hw == HONDA_BH_HW) && !honda_bosch_long) { + tx = msg_allowed(to_send, HONDA_BH_TX_MSGS, sizeof(HONDA_BH_TX_MSGS)/sizeof(HONDA_BH_TX_MSGS[0])); + } else if ((honda_hw == HONDA_BH_HW) && honda_bosch_long) { + tx = msg_allowed(to_send, HONDA_BH_LONG_TX_MSGS, sizeof(HONDA_BH_LONG_TX_MSGS)/sizeof(HONDA_BH_LONG_TX_MSGS[0])); } else { - tx = msg_allowed(addr, bus, HONDA_N_TX_MSGS, sizeof(HONDA_N_TX_MSGS)/sizeof(HONDA_N_TX_MSGS[0])); + tx = msg_allowed(to_send, HONDA_N_TX_MSGS, sizeof(HONDA_N_TX_MSGS)/sizeof(HONDA_N_TX_MSGS[0])); } if (relay_malfunction) { @@ -211,9 +224,10 @@ static int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { pedal_pressed = pedal_pressed || gas_pressed_prev || (gas_interceptor_prev > HONDA_GAS_INTERCEPTOR_THRESHOLD); } bool current_controls_allowed = controls_allowed && !(pedal_pressed); + int bus_pt = (honda_hw == HONDA_BH_HW)? 1 : 0; - // BRAKE: safety check - if ((addr == 0x1FA) && (bus == 0)) { + // BRAKE: safety check (nidec) + if ((addr == 0x1FA) && (bus == bus_pt)) { honda_brake = (GET_BYTE(to_send, 0) << 2) + ((GET_BYTE(to_send, 1) >> 6) & 0x3); if (!current_controls_allowed) { if (honda_brake != 0) { @@ -228,6 +242,31 @@ static int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { } } + // BRAKE/GAS: safety check (bosch) + if ((addr == 0x1DF) && (bus == bus_pt)) { + int accel = (GET_BYTE(to_send, 3) << 3) | ((GET_BYTE(to_send, 4) >> 5) & 0x7); + accel = to_signed(accel, 11); + if (!current_controls_allowed) { + if (accel != 0) { + tx = 0; + } + } + if (accel < HONDA_BOSCH_ACCEL_MIN) { + tx = 0; + } + + int gas = (GET_BYTE(to_send, 0) << 8) | GET_BYTE(to_send, 1); + gas = to_signed(gas, 16); + if (!current_controls_allowed) { + if (gas != HONDA_BOSCH_NO_GAS_VALUE) { + tx = 0; + } + } + if (gas > HONDA_BOSCH_GAS_MAX) { + tx = 0; + } + } + // STEER: safety check if ((addr == 0xE4) || (addr == 0x194)) { if (!current_controls_allowed) { @@ -245,7 +284,7 @@ static int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { } } - // GAS: safety check + // GAS: safety check (interceptor) if (addr == 0x200) { if (!current_controls_allowed) { if (GET_BYTE(to_send, 0) || GET_BYTE(to_send, 1)) { @@ -257,7 +296,6 @@ static int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { // 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 - int bus_pt = (honda_hw == HONDA_BH_HW)? 1 : 0; if ((addr == 0x296) && !current_controls_allowed && (bus == bus_pt)) { if (((GET_BYTE(to_send, 0) >> 5) & 0x7) != 2) { tx = 0; @@ -275,6 +313,7 @@ static void honda_nidec_init(int16_t param) { gas_interceptor_detected = 0; honda_hw = HONDA_N_HW; honda_alt_brake_msg = false; + honda_bosch_long = false; } static void honda_bosch_giraffe_init(int16_t param) { @@ -282,7 +321,9 @@ static void honda_bosch_giraffe_init(int16_t param) { relay_malfunction_reset(); honda_hw = HONDA_BG_HW; // Checking for alternate brake override from safety parameter - honda_alt_brake_msg = (param == 1) ? true : false; + honda_alt_brake_msg = GET_FLAG(param, HONDA_PARAM_ALT_BRAKE); + // radar disabled so allow gas/brakes + honda_bosch_long = GET_FLAG(param, HONDA_PARAM_BOSCH_LONG); } static void honda_bosch_harness_init(int16_t param) { @@ -290,7 +331,9 @@ static void honda_bosch_harness_init(int16_t param) { relay_malfunction_reset(); honda_hw = HONDA_BH_HW; // Checking for alternate brake override from safety parameter - honda_alt_brake_msg = (param == 1) ? true : false; + honda_alt_brake_msg = GET_FLAG(param, HONDA_PARAM_ALT_BRAKE); + // radar disabled so allow gas/brakes + honda_bosch_long = GET_FLAG(param, HONDA_PARAM_BOSCH_LONG); } static int honda_nidec_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) { diff --git a/board/safety/safety_hyundai.h b/board/safety/safety_hyundai.h index 61c3b7e8dc393d0..5c6ac470b68a833 100644 --- a/board/safety/safety_hyundai.h +++ b/board/safety/safety_hyundai.h @@ -6,15 +6,15 @@ const int HYUNDAI_MAX_RATE_DOWN = 7; const int HYUNDAI_DRIVER_TORQUE_ALLOWANCE = 50; const int HYUNDAI_DRIVER_TORQUE_FACTOR = 2; const int HYUNDAI_STANDSTILL_THRSLD = 30; // ~1kph -const AddrBus HYUNDAI_TX_MSGS[] = {{832, 0}, {1265, 0}, {1157, 0}}; +const CanMsg HYUNDAI_TX_MSGS[] = {{832, 0, 8}, {1265, 0, 4}, {1157, 0, 4}}; // TODO: do checksum checks AddrCheckStruct hyundai_rx_checks[] = { - {.addr = {608}, .bus = 0, .max_counter = 3U, .expected_timestep = 10000U}, - {.addr = {897}, .bus = 0, .max_counter = 255U, .expected_timestep = 10000U}, - {.addr = {902}, .bus = 0, .max_counter = 3U, .expected_timestep = 10000U}, - {.addr = {916}, .bus = 0, .max_counter = 7U, .expected_timestep = 10000U}, - {.addr = {1057}, .bus = 0, .max_counter = 15U, .expected_timestep = 20000U}, + {.msg = {{608, 0, 8}}, .check_checksum = true, .max_counter = 3U, .expected_timestep = 10000U}, + {.msg = {{897, 0, 8}}, .max_counter = 255U, .expected_timestep = 10000U}, + {.msg = {{902, 0, 8}}, .max_counter = 15U, .expected_timestep = 10000U}, + {.msg = {{916, 0, 8}}, .check_checksum = true, .max_counter = 7U, .expected_timestep = 10000U}, + {.msg = {{1057, 0, 8}}, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, }; const int HYUNDAI_RX_CHECK_LEN = sizeof(hyundai_rx_checks) / sizeof(hyundai_rx_checks[0]); @@ -27,7 +27,7 @@ static uint8_t hyundai_get_counter(CAN_FIFOMailBox_TypeDef *to_push) { } else if (addr == 897) { cnt = GET_BYTE(to_push, 5); } else if (addr == 902) { - cnt = (GET_BYTE(to_push, 1) >> 6) & 0x3; + cnt = ((GET_BYTE(to_push, 3) >> 6) << 2) | (GET_BYTE(to_push, 1) >> 6); } else if (addr == 916) { cnt = (GET_BYTE(to_push, 1) >> 5) & 0x7; } else if (addr == 1057) { @@ -38,10 +38,43 @@ static uint8_t hyundai_get_counter(CAN_FIFOMailBox_TypeDef *to_push) { return cnt; } +static uint8_t hyundai_get_checksum(CAN_FIFOMailBox_TypeDef *to_push) { + int addr = GET_ADDR(to_push); + + uint8_t chksum; + if (addr == 608) { + chksum = GET_BYTE(to_push, 7) & 0xF; + } else if (addr == 916) { + chksum = GET_BYTE(to_push, 6) & 0xF; + } else if (addr == 1057) { + chksum = GET_BYTE(to_push, 7) >> 4; + } else { + chksum = 0; + } + return chksum; +} + +static uint8_t hyundai_compute_checksum(CAN_FIFOMailBox_TypeDef *to_push) { + int addr = GET_ADDR(to_push); + + uint8_t chksum = 0; + // same algorithm, but checksum is in a different place + for (int i = 0; i < 8; i++) { + uint8_t b = GET_BYTE(to_push, i); + if (((addr == 608) && (i == 7)) || ((addr == 916) && (i == 6)) || ((addr == 1057) && (i == 7))) { + b &= (addr == 1057) ? 0x0FU : 0xF0U; // remove checksum + } + chksum += (b % 16U) + (b / 16U); + } + chksum = (16U - (chksum % 16U)) % 16U; + return chksum; +} + static int hyundai_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) { bool valid = addr_safety_check(to_push, hyundai_rx_checks, HYUNDAI_RX_CHECK_LEN, - NULL, NULL, hyundai_get_counter); + hyundai_get_checksum, hyundai_compute_checksum, + hyundai_get_counter); bool unsafe_allow_gas = unsafe_mode & UNSAFE_DISABLE_DISENGAGE_ON_GAS; @@ -106,9 +139,8 @@ static int hyundai_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { int tx = 1; int addr = GET_ADDR(to_send); - int bus = GET_BUS(to_send); - if (!msg_allowed(addr, bus, HYUNDAI_TX_MSGS, sizeof(HYUNDAI_TX_MSGS)/sizeof(HYUNDAI_TX_MSGS[0]))) { + if (!msg_allowed(to_send, HYUNDAI_TX_MSGS, sizeof(HYUNDAI_TX_MSGS)/sizeof(HYUNDAI_TX_MSGS[0]))) { tx = 0; } @@ -192,7 +224,6 @@ static int hyundai_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) { return bus_fwd; } - const safety_hooks hyundai_hooks = { .init = nooutput_init, .rx = hyundai_rx_hook, diff --git a/board/safety/safety_nissan.h b/board/safety/safety_nissan.h index aca99d19b69aa9d..5a3e33bbdfa4293 100644 --- a/board/safety/safety_nissan.h +++ b/board/safety/safety_nissan.h @@ -11,14 +11,14 @@ const struct lookup_t NISSAN_LOOKUP_ANGLE_RATE_DOWN = { const int NISSAN_DEG_TO_CAN = 100; -const AddrBus NISSAN_TX_MSGS[] = {{0x169, 0}, {0x2b1, 0}, {0x4cc, 0}, {0x20b, 2}, {0x280, 2}}; +const CanMsg NISSAN_TX_MSGS[] = {{0x169, 0, 8}, {0x2b1, 0, 8}, {0x4cc, 0, 8}, {0x20b, 2, 8}, {0x280, 2, 8}}; AddrCheckStruct nissan_rx_checks[] = { - {.addr = {0x2}, .bus = 0, .expected_timestep = 10000U}, // STEER_ANGLE_SENSOR (100Hz) - {.addr = {0x285}, .bus = 0, .expected_timestep = 20000U}, // WHEEL_SPEEDS_REAR (50Hz) - {.addr = {0x30f}, .bus = 2, .expected_timestep = 100000U}, // CRUISE_STATE (10Hz) - {.addr = {0x15c, 0x239}, .bus = 0, .expected_timestep = 20000U}, // GAS_PEDAL (100Hz / 50Hz) - {.addr = {0x454, 0x1cc}, .bus = 0, .expected_timestep = 100000U}, // DOORS_LIGHTS (10Hz) / BRAKE (100Hz) + {.msg = {{0x2, 0, 5}}, .expected_timestep = 10000U}, // STEER_ANGLE_SENSOR (100Hz) + {.msg = {{0x285, 0, 8}}, .expected_timestep = 20000U}, // WHEEL_SPEEDS_REAR (50Hz) + {.msg = {{0x30f, 2, 3}}, .expected_timestep = 100000U}, // CRUISE_STATE (10Hz) + {.msg = {{0x15c, 0, 8}, {0x239, 0, 8}}, .expected_timestep = 20000U}, // GAS_PEDAL (100Hz / 50Hz) + {.msg = {{0x454, 0, 8}, {0x1cc, 0, 8}}, .expected_timestep = 100000U}, // DOORS_LIGHTS (10Hz) / BRAKE (100Hz) }; const int NISSAN_RX_CHECK_LEN = sizeof(nissan_rx_checks) / sizeof(nissan_rx_checks[0]); @@ -119,10 +119,9 @@ static int nissan_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) { static int nissan_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { int tx = 1; int addr = GET_ADDR(to_send); - int bus = GET_BUS(to_send); bool violation = 0; - if (!msg_allowed(addr, bus, NISSAN_TX_MSGS, sizeof(NISSAN_TX_MSGS) / sizeof(NISSAN_TX_MSGS[0]))) { + if (!msg_allowed(to_send, NISSAN_TX_MSGS, sizeof(NISSAN_TX_MSGS) / sizeof(NISSAN_TX_MSGS[0]))) { tx = 0; } diff --git a/board/safety/safety_subaru.h b/board/safety/safety_subaru.h index 17bd699d68ec0f1..b663802190cc96f 100644 --- a/board/safety/safety_subaru.h +++ b/board/safety/safety_subaru.h @@ -9,23 +9,23 @@ const int SUBARU_DRIVER_TORQUE_ALLOWANCE = 60; const int SUBARU_DRIVER_TORQUE_FACTOR = 10; const int SUBARU_STANDSTILL_THRSLD = 20; // about 1kph -const AddrBus SUBARU_TX_MSGS[] = {{0x122, 0}, {0x221, 0}, {0x322, 0}}; -const AddrBus SUBARU_L_TX_MSGS[] = {{0x164, 0}, {0x221, 0}, {0x322, 0}}; +const CanMsg SUBARU_TX_MSGS[] = {{0x122, 0, 8}, {0x221, 0, 8}, {0x322, 0, 8}}; +const CanMsg SUBARU_L_TX_MSGS[] = {{0x164, 0, 8}, {0x221, 0, 8}, {0x322, 0, 8}}; const int SUBARU_TX_MSGS_LEN = sizeof(SUBARU_TX_MSGS) / sizeof(SUBARU_TX_MSGS[0]); const int SUBARU_L_TX_MSGS_LEN = sizeof(SUBARU_L_TX_MSGS) / sizeof(SUBARU_L_TX_MSGS[0]); AddrCheckStruct subaru_rx_checks[] = { - {.addr = { 0x40}, .bus = 0, .check_checksum = true, .max_counter = 15U, .expected_timestep = 10000U}, - {.addr = {0x119}, .bus = 0, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, - {.addr = {0x139}, .bus = 0, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, - {.addr = {0x13a}, .bus = 0, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, - {.addr = {0x240}, .bus = 0, .check_checksum = true, .max_counter = 15U, .expected_timestep = 50000U}, + {.msg = {{ 0x40, 0, 8}}, .check_checksum = true, .max_counter = 15U, .expected_timestep = 10000U}, + {.msg = {{0x119, 0, 8}}, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, + {.msg = {{0x139, 0, 8}}, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, + {.msg = {{0x13a, 0, 8}}, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, + {.msg = {{0x240, 0, 8}}, .check_checksum = true, .max_counter = 15U, .expected_timestep = 50000U}, }; // TODO: do checksum and counter checks after adding the signals to the outback dbc file AddrCheckStruct subaru_l_rx_checks[] = { - {.addr = {0x140}, .bus = 0, .expected_timestep = 10000U}, - {.addr = {0x371}, .bus = 0, .expected_timestep = 20000U}, - {.addr = {0x144}, .bus = 0, .expected_timestep = 50000U}, + {.msg = {{0x140, 0, 8}}, .expected_timestep = 10000U}, + {.msg = {{0x371, 0, 8}}, .expected_timestep = 20000U}, + {.msg = {{0x144, 0, 8}}, .expected_timestep = 50000U}, }; const int SUBARU_RX_CHECK_LEN = sizeof(subaru_rx_checks) / sizeof(subaru_rx_checks[0]); const int SUBARU_L_RX_CHECK_LEN = sizeof(subaru_l_rx_checks) / sizeof(subaru_l_rx_checks[0]); @@ -131,10 +131,9 @@ static int subaru_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) { static int subaru_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { int tx = 1; int addr = GET_ADDR(to_send); - int bus = GET_BUS(to_send); - if ((!msg_allowed(addr, bus, SUBARU_TX_MSGS, SUBARU_TX_MSGS_LEN) && subaru_global) || - (!msg_allowed(addr, bus, SUBARU_L_TX_MSGS, SUBARU_L_TX_MSGS_LEN) && !subaru_global)) { + if ((!msg_allowed(to_send, SUBARU_TX_MSGS, SUBARU_TX_MSGS_LEN) && subaru_global) || + (!msg_allowed(to_send, SUBARU_L_TX_MSGS, SUBARU_L_TX_MSGS_LEN) && !subaru_global)) { tx = 0; } diff --git a/board/safety/safety_toyota.h b/board/safety/safety_toyota.h index f69e4d3c6c0385f..8d91504012430cd 100644 --- a/board/safety/safety_toyota.h +++ b/board/safety/safety_toyota.h @@ -29,16 +29,16 @@ const int TOYOTA_STANDSTILL_THRSLD = 100; // 1kph const int TOYOTA_GAS_INTERCEPTOR_THRSLD = 845; #define TOYOTA_GET_INTERCEPTOR(msg) (((GET_BYTE((msg), 0) << 8) + GET_BYTE((msg), 1) + (GET_BYTE((msg), 2) << 8) + GET_BYTE((msg), 3)) / 2) // avg between 2 tracks -const AddrBus TOYOTA_TX_MSGS[] = {{0x283, 0}, {0x2E6, 0}, {0x2E7, 0}, {0x33E, 0}, {0x344, 0}, {0x365, 0}, {0x366, 0}, {0x4CB, 0}, // DSU bus 0 - {0x128, 1}, {0x141, 1}, {0x160, 1}, {0x161, 1}, {0x470, 1}, // DSU bus 1 - {0x2E4, 0}, {0x411, 0}, {0x412, 0}, {0x343, 0}, {0x1D2, 0}, // LKAS + ACC - {0x200, 0}, {0x750, 0}}; // interceptor + Blindspot monitor +const CanMsg TOYOTA_TX_MSGS[] = {{0x283, 0, 7}, {0x2E6, 0, 8}, {0x2E7, 0, 8}, {0x33E, 0, 7}, {0x344, 0, 8}, {0x365, 0, 7}, {0x366, 0, 7}, {0x4CB, 0, 8}, // DSU bus 0 + {0x128, 1, 6}, {0x141, 1, 4}, {0x160, 1, 8}, {0x161, 1, 7}, {0x470, 1, 4}, // DSU bus 1 + {0x2E4, 0, 5}, {0x411, 0, 8}, {0x412, 0, 8}, {0x343, 0, 8}, {0x1D2, 0, 8}, // LKAS + ACC + {0x200, 0, 6}, {0x750, 0, 8}}; // interceptor + Blindspot monitor AddrCheckStruct toyota_rx_checks[] = { - {.addr = { 0xaa}, .bus = 0, .check_checksum = false, .expected_timestep = 12000U}, - {.addr = {0x260}, .bus = 0, .check_checksum = true, .expected_timestep = 20000U}, - {.addr = {0x1D2}, .bus = 0, .check_checksum = true, .expected_timestep = 30000U}, - {.addr = {0x224, 0x226}, .bus = 0, .check_checksum = false, .expected_timestep = 25000U}, + {.msg = {{ 0xaa, 0, 8}}, .check_checksum = false, .expected_timestep = 12000U}, + {.msg = {{0x260, 0, 8}}, .check_checksum = true, .expected_timestep = 20000U}, + {.msg = {{0x1D2, 0, 8}}, .check_checksum = true, .expected_timestep = 30000U}, + {.msg = {{0x224, 0, 8}, {0x226, 0, 8}}, .check_checksum = false, .expected_timestep = 25000U}, }; const int TOYOTA_RX_CHECKS_LEN = sizeof(toyota_rx_checks) / sizeof(toyota_rx_checks[0]); @@ -153,7 +153,7 @@ static int toyota_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { int addr = GET_ADDR(to_send); int bus = GET_BUS(to_send); - if (!msg_allowed(addr, bus, TOYOTA_TX_MSGS, sizeof(TOYOTA_TX_MSGS)/sizeof(TOYOTA_TX_MSGS[0]))) { + if (!msg_allowed(to_send, TOYOTA_TX_MSGS, sizeof(TOYOTA_TX_MSGS)/sizeof(TOYOTA_TX_MSGS[0]))) { tx = 0; } diff --git a/board/safety/safety_volkswagen.h b/board/safety/safety_volkswagen.h index 4063fa7d5e8ea06..a02375dc02812fc 100644 --- a/board/safety/safety_volkswagen.h +++ b/board/safety/safety_volkswagen.h @@ -18,15 +18,15 @@ const int VOLKSWAGEN_DRIVER_TORQUE_FACTOR = 3; #define MSG_LDW_02 0x397 // TX by OP, Lane line recognition and text alerts // Transmit of GRA_ACC_01 is allowed on bus 0 and 2 to keep compatibility with gateway and camera integration -const AddrBus VOLKSWAGEN_MQB_TX_MSGS[] = {{MSG_HCA_01, 0}, {MSG_GRA_ACC_01, 0}, {MSG_GRA_ACC_01, 2}, {MSG_LDW_02, 0}}; +const CanMsg VOLKSWAGEN_MQB_TX_MSGS[] = {{MSG_HCA_01, 0, 8}, {MSG_GRA_ACC_01, 0, 8}, {MSG_GRA_ACC_01, 2, 8}, {MSG_LDW_02, 0, 8}}; const int VOLKSWAGEN_MQB_TX_MSGS_LEN = sizeof(VOLKSWAGEN_MQB_TX_MSGS) / sizeof(VOLKSWAGEN_MQB_TX_MSGS[0]); AddrCheckStruct volkswagen_mqb_rx_checks[] = { - {.addr = {MSG_ESP_19}, .bus = 0, .check_checksum = false, .max_counter = 0U, .expected_timestep = 10000U}, - {.addr = {MSG_EPS_01}, .bus = 0, .check_checksum = true, .max_counter = 15U, .expected_timestep = 10000U}, - {.addr = {MSG_ESP_05}, .bus = 0, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, - {.addr = {MSG_TSK_06}, .bus = 0, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, - {.addr = {MSG_MOTOR_20}, .bus = 0, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, + {.msg = {{MSG_ESP_19, 0, 8}}, .check_checksum = false, .max_counter = 0U, .expected_timestep = 10000U}, + {.msg = {{MSG_EPS_01, 0, 8}}, .check_checksum = true, .max_counter = 15U, .expected_timestep = 10000U}, + {.msg = {{MSG_ESP_05, 0, 8}}, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, + {.msg = {{MSG_TSK_06, 0, 8}}, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, + {.msg = {{MSG_MOTOR_20, 0, 8}}, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, }; const int VOLKSWAGEN_MQB_RX_CHECKS_LEN = sizeof(volkswagen_mqb_rx_checks) / sizeof(volkswagen_mqb_rx_checks[0]); @@ -40,14 +40,14 @@ const int VOLKSWAGEN_MQB_RX_CHECKS_LEN = sizeof(volkswagen_mqb_rx_checks) / size #define MSG_LDW_1 0x5BE // TX by OP, Lane line recognition and text alerts // Transmit of GRA_Neu is allowed on bus 0 and 2 to keep compatibility with gateway and camera integration -const AddrBus VOLKSWAGEN_PQ_TX_MSGS[] = {{MSG_HCA_1, 0}, {MSG_GRA_NEU, 0}, {MSG_GRA_NEU, 2}, {MSG_LDW_1, 0}}; +const CanMsg VOLKSWAGEN_PQ_TX_MSGS[] = {{MSG_HCA_1, 0, 5}, {MSG_GRA_NEU, 0, 4}, {MSG_GRA_NEU, 2, 4}, {MSG_LDW_1, 0, 8}}; const int VOLKSWAGEN_PQ_TX_MSGS_LEN = sizeof(VOLKSWAGEN_PQ_TX_MSGS) / sizeof(VOLKSWAGEN_PQ_TX_MSGS[0]); AddrCheckStruct volkswagen_pq_rx_checks[] = { - {.addr = {MSG_LENKHILFE_3}, .bus = 0, .check_checksum = true, .max_counter = 15U, .expected_timestep = 10000U}, - {.addr = {MSG_MOTOR_2}, .bus = 0, .check_checksum = false, .max_counter = 0U, .expected_timestep = 20000U}, - {.addr = {MSG_MOTOR_3}, .bus = 0, .check_checksum = false, .max_counter = 0U, .expected_timestep = 10000U}, - {.addr = {MSG_BREMSE_3}, .bus = 0, .check_checksum = false, .max_counter = 0U, .expected_timestep = 10000U}, + {.msg = {{MSG_LENKHILFE_3, 0, 6}}, .check_checksum = true, .max_counter = 15U, .expected_timestep = 10000U}, + {.msg = {{MSG_MOTOR_2, 0, 8}}, .check_checksum = false, .max_counter = 0U, .expected_timestep = 20000U}, + {.msg = {{MSG_MOTOR_3, 0, 8}}, .check_checksum = false, .max_counter = 0U, .expected_timestep = 10000U}, + {.msg = {{MSG_BREMSE_3, 0, 8}}, .check_checksum = false, .max_counter = 0U, .expected_timestep = 10000U}, }; const int VOLKSWAGEN_PQ_RX_CHECKS_LEN = sizeof(volkswagen_pq_rx_checks) / sizeof(volkswagen_pq_rx_checks[0]); @@ -311,10 +311,9 @@ static bool volkswagen_steering_check(int desired_torque) { static int volkswagen_mqb_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { int addr = GET_ADDR(to_send); - int bus = GET_BUS(to_send); int tx = 1; - if (!msg_allowed(addr, bus, VOLKSWAGEN_MQB_TX_MSGS, VOLKSWAGEN_MQB_TX_MSGS_LEN) || relay_malfunction) { + if (!msg_allowed(to_send, VOLKSWAGEN_MQB_TX_MSGS, VOLKSWAGEN_MQB_TX_MSGS_LEN) || relay_malfunction) { tx = 0; } @@ -348,10 +347,9 @@ static int volkswagen_mqb_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { static int volkswagen_pq_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { int addr = GET_ADDR(to_send); - int bus = GET_BUS(to_send); int tx = 1; - if (!msg_allowed(addr, bus, VOLKSWAGEN_PQ_TX_MSGS, VOLKSWAGEN_PQ_TX_MSGS_LEN) || relay_malfunction) { + if (!msg_allowed(to_send, VOLKSWAGEN_PQ_TX_MSGS, VOLKSWAGEN_PQ_TX_MSGS_LEN) || relay_malfunction) { tx = 0; } diff --git a/board/safety_declarations.h b/board/safety_declarations.h index be8be93b78023b7..7ce73054e8e4fef 100644 --- a/board/safety_declarations.h +++ b/board/safety_declarations.h @@ -17,13 +17,13 @@ struct lookup_t { typedef struct { int addr; int bus; -} AddrBus; + int len; +} CanMsg; // params and flags about checksum, counter and frequency checks for each monitored address typedef struct { // const params - const int addr[3]; // check either messages (e.g. honda steer). Array MUST terminate with a zero to know its length. - const int bus; // bus where to expect the addr. Temp hack: -1 means skip the bus check + const CanMsg msg[3]; // check either messages (e.g. honda steer). Array MUST terminate with an empty struct to know its length. const bool check_checksum; // true is checksum check is performed const uint8_t max_counter; // maximum value of the counter. 0 means that the counter check is skipped const uint32_t expected_timestep; // expected time between message updates [us] @@ -50,7 +50,7 @@ bool driver_limit_check(int val, int val_last, struct sample_t *val_driver, bool rt_rate_limit_check(int val, int val_last, const int MAX_RT_DELTA); float interpolate(struct lookup_t xy, float x); void gen_crc_lookup_table(uint8_t poly, uint8_t crc_lut[]); -bool msg_allowed(int addr, int bus, const AddrBus addr_list[], int len); +bool msg_allowed(CAN_FIFOMailBox_TypeDef *to_send, const CanMsg msg_list[], int len); int get_addr_check_index(CAN_FIFOMailBox_TypeDef *to_push, AddrCheckStruct addr_list[], const int len); void update_counter(AddrCheckStruct addr_list[], int index, uint8_t counter); void update_addr_timestamp(AddrCheckStruct addr_list[], int index); diff --git a/python/uds.py b/python/uds.py index 548f1bcceaab9cd..92fc46b90863685 100644 --- a/python/uds.py +++ b/python/uds.py @@ -372,7 +372,7 @@ def send(self, dat: bytes) -> None: self._tx_first_frame() def _tx_first_frame(self) -> None: - if self.tx_len < 8: + if self.tx_len < self.max_len: # single frame (send all bytes) if self.debug: print("ISO-TP: TX - single frame") msg = (bytes([self.tx_len]) + self.tx_dat).ljust(self.max_len, b"\x00") @@ -380,7 +380,7 @@ def _tx_first_frame(self) -> None: else: # first frame (send first 6 bytes) if self.debug: print("ISO-TP: TX - first frame") - msg = (struct.pack("!H", 0x1000 | self.tx_len) + self.tx_dat[:6]).ljust(self.max_len, b"\x00") + msg = (struct.pack("!H", 0x1000 | self.tx_len) + self.tx_dat[:self.max_len - 2]).ljust(self.max_len - 2, b"\x00") self._can_client.send([msg]) def recv(self) -> bytes: diff --git a/tests/build/Dockerfile b/tests/build/Dockerfile.panda_esp similarity index 73% rename from tests/build/Dockerfile rename to tests/build/Dockerfile.panda_esp index 0f982160beb8ded..63c2cae3fd0463f 100644 --- a/tests/build/Dockerfile +++ b/tests/build/Dockerfile.panda_esp @@ -1,21 +1,13 @@ FROM ubuntu:16.04 -RUN apt-get update && apt-get install -y gcc-arm-none-eabi libnewlib-arm-none-eabi python python-pip gcc g++ git autoconf gperf bison flex automake texinfo wget help2man gawk libtool libtool-bin ncurses-dev unzip unrar-free libexpat-dev sed bzip2 locales curl zlib1g-dev libffi-dev libssl-dev +RUN apt-get update && apt-get install -y gcc-arm-none-eabi libnewlib-arm-none-eabi python python-pip gcc g++ git autoconf gperf bison flex automake texinfo wget help2man gawk libtool libtool-bin ncurses-dev unzip unrar-free libexpat-dev sed bzip2 locales curl zlib1g-dev libffi-dev libssl-dev python3 python3-pip RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen ENV LANG en_US.UTF-8 ENV LANGUAGE en_US:en ENV LC_ALL en_US.UTF-8 -RUN curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash - -ENV PATH="/root/.pyenv/bin:/root/.pyenv/shims:${PATH}" -RUN pyenv install 2.7.12 -RUN pyenv install 3.7.3 -RUN pyenv global 3.7.3 -RUN pyenv rehash - -RUN pip install pycrypto==2.6.1 +RUN pip3 install pycrypto==2.6.1 # Build esp toolchain RUN mkdir -p /panda/boardesp diff --git a/tests/language/Dockerfile b/tests/language/Dockerfile deleted file mode 100644 index 6a1d8bb7c77ff9e..000000000000000 --- a/tests/language/Dockerfile +++ /dev/null @@ -1,17 +0,0 @@ -FROM ubuntu:16.04 - -RUN apt-get update && apt-get install -y make python python-pip locales curl git zlib1g-dev libffi-dev bzip2 libssl-dev - -RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen -ENV LANG en_US.UTF-8 -ENV LANGUAGE en_US:en -ENV LC_ALL en_US.UTF-8 - -RUN curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash - -ENV PATH="/root/.pyenv/bin:/root/.pyenv/shims:${PATH}" -RUN pyenv install 3.7.3 -RUN pyenv global 3.7.3 -RUN pyenv rehash - -COPY . /panda diff --git a/tests/language/LICENSE b/tests/language/LICENSE deleted file mode 100644 index 8dada3edaf50dbc..000000000000000 --- a/tests/language/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/tests/language/list.txt b/tests/language/list.txt deleted file mode 100644 index cfd25897d8dc55f..000000000000000 --- a/tests/language/list.txt +++ /dev/null @@ -1,451 +0,0 @@ -4r5e -5h1t -5hit -a55 -anal -anus -ar5e -arrse -arse -ass -ass-fucker -asses -assfucker -assfukka -asshole -assholes -asswhole -a_s_s -b!tch -b00bs -b17ch -b1tch -ballbag -balls -ballsack -bastard -beastial -beastiality -bellend -bestial -bestiality -bi+ch -biatch -bitch -bitcher -bitchers -bitches -bitchin -bitching -bloody -blow job -blowjob -blowjobs -boiolas -bollock -bollok -boner -boob -boobs -booobs -boooobs -booooobs -booooooobs -breasts -buceta -bugger -bum -bunny fucker -bullshit -butt -butthole -buttmuch -buttplug -c0ck -c0cksucker -carpet muncher -cawk -chink -cipa -cl1t -clit -clitoris -clits -cnut -cock -cock-sucker -cockface -cockhead -cockmunch -cockmuncher -cocks -cocksuck -cocksucked -cocksucker -cocksucking -cocksucks -cocksuka -cocksukka -cok -cokmuncher -coksucka -coon -cox -crap -cum -cummer -cumming -cums -cumshot -cunilingus -cunillingus -cunnilingus -cunt -cuntlick -cuntlicker -cuntlicking -cunts -cyalis -cyberfuc -cyberfuck -cyberfucked -cyberfucker -cyberfuckers -cyberfucking -d1ck -damn -dick -dickhead -dildo -dildos -dink -dinks -dirsa -dlck -dog-fucker -doggin -dogging -donkeyribber -doosh -duche -dyke -ejaculate -ejaculated -ejaculates -ejaculating -ejaculatings -ejaculation -ejakulate -f u c k -f u c k e r -f4nny -fag -fagging -faggitt -faggot -faggs -fagot -fagots -fags -fanny -fannyflaps -fannyfucker -fanyy -fatass -fcuk -fcuker -fcuking -feck -fecker -felching -fellate -fellatio -fingerfuck -fingerfucked -fingerfucker -fingerfuckers -fingerfucking -fingerfucks -fistfuck -fistfucked -fistfucker -fistfuckers -fistfucking -fistfuckings -fistfucks -flange -fook -fooker -fuck -fucka -fucked -fucker -fuckers -fuckhead -fuckheads -fuckin -fucking -fuckings -fuckingshitmotherfucker -fuckme -fucks -fuckwhit -fuckwit -fudge packer -fudgepacker -fuk -fuker -fukker -fukkin -fuks -fukwhit -fukwit -fux -fux0r -f_u_c_k -gangbang -gangbanged -gangbangs -gaylord -gaysex -goatse -God -god-dam -god-damned -goddamn -goddamned -hardcoresex -hell -heshe -hoar -hoare -hoer -homo -hore -horniest -horny -hotsex -jack-off -jackoff -jap -jerk-off -jism -jiz -jizm -jizz -kawk -knob -knobead -knobed -knobend -knobhead -knobjocky -knobjokey -kock -kondum -kondums -kum -kummer -kumming -kums -kunilingus -l3i+ch -l3itch -labia -lmfao -lust -lusting -m0f0 -m0fo -m45terbate -ma5terb8 -ma5terbate -masochist -master-bate -masterb8 -masterbat* -masterbat3 -masterbate -masterbation -masterbations -masturbate -mo-fo -mof0 -mofo -mothafuck -mothafucka -mothafuckas -mothafuckaz -mothafucked -mothafucker -mothafuckers -mothafuckin -mothafucking -mothafuckings -mothafucks -mother fucker -motherfuck -motherfucked -motherfucker -motherfuckers -motherfuckin -motherfucking -motherfuckings -motherfuckka -motherfucks -muff -mutha -muthafecker -muthafuckker -muther -mutherfucker -n1gga -n1gger -nazi -nigg3r -nigg4h -nigga -niggah -niggas -niggaz -nigger -niggers -nob -nob jokey -nobhead -nobjocky -nobjokey -numbnuts -nutsack -orgasim -orgasims -orgasm -orgasms -p0rn -pawn -pecker -penis -penisfucker -phonesex -phuck -phuk -phuked -phuking -phukked -phukking -phuks -phuq -pigfucker -pimpis -piss -pissed -pisser -pissers -pisses -pissflaps -pissin -pissing -pissoff -poop -porn -porno -pornography -pornos -prick -pricks -pron -pube -pusse -pussi -pussies -pussy -pussys -rectum -retard -rimjaw -rimming -s hit -s.o.b. -sadist -schlong -screwing -scroat -scrote -scrotum -semen -sex -sh!+ -sh!t -sh1t -shag -shagger -shaggin -shagging -shemale -shi+ -shit -shitdick -shite -shited -shitey -shitfuck -shitfull -shithead -shiting -shitings -shits -shitted -shitter -shitters -shitting -shittings -shitty -skank -slut -sluts -smegma -smut -snatch -son-of-a-bitch -spac -spunk -s_h_i_t -t1tt1e5 -t1tties -teets -teez -testical -testicle -tit -titfuck -tits -titt -tittie5 -tittiefucker -titties -tittyfuck -tittywank -titwank -tosser -turd -tw4t -twat -twathead -twatty -twunt -twunter -v14gra -v1gra -vagina -viagra -vulva -w00se -wang -wank -wanker -wanky -whoar -whore -willies -willy -xrated diff --git a/tests/language/test_language.py b/tests/language/test_language.py deleted file mode 100755 index 98b029042551e90..000000000000000 --- a/tests/language/test_language.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env python3 - -import subprocess -import sys - -checked_ext = ["h", "c", "py", "pyx", "cpp", "hpp", "md", "mk"] - -if __name__ == "__main__": - with open("list.txt", 'r') as handle: - - suffix_cmd = " " - for i in checked_ext: - suffix_cmd += "--include \*." + i + " " - - found_bad_language = False - for line in handle: - line = line.rstrip('\n').rstrip(" ") - try: - cmd = "cd ../../; grep -R -i -w " + suffix_cmd + " '" + line + "'" - res = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT) - print(res) - found_bad_language = True - except subprocess.CalledProcessError: - pass - if found_bad_language: - sys.exit("Failed: found bad language") - else: - print("Success") diff --git a/tests/linter_python/Dockerfile b/tests/linter_python/Dockerfile deleted file mode 100644 index 819d692109e1c3b..000000000000000 --- a/tests/linter_python/Dockerfile +++ /dev/null @@ -1,19 +0,0 @@ -FROM ubuntu:16.04 - -RUN apt-get update && apt-get install -y make python python-pip locales curl git zlib1g-dev libffi-dev bzip2 libssl-dev - -RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen -ENV LANG en_US.UTF-8 -ENV LANGUAGE en_US:en -ENV LC_ALL en_US.UTF-8 - -RUN curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash - -ENV PATH="/root/.pyenv/bin:/root/.pyenv/shims:${PATH}" -RUN pyenv install 3.7.3 -RUN pyenv global 3.7.3 -RUN pyenv rehash - -COPY requirements.txt /tmp/ -RUN pip install -r /tmp/requirements.txt -COPY . /panda diff --git a/tests/misra/Dockerfile b/tests/misra/Dockerfile deleted file mode 100644 index 06882834fcdfbe9..000000000000000 --- a/tests/misra/Dockerfile +++ /dev/null @@ -1,19 +0,0 @@ -FROM ubuntu:16.04 - -RUN apt-get update && apt-get install -y clang make python python-pip git curl locales zlib1g-dev libffi-dev bzip2 libssl-dev libbz2-dev libusb-1.0-0 - -RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen -ENV LANG en_US.UTF-8 -ENV LANGUAGE en_US:en -ENV LC_ALL en_US.UTF-8 - -RUN curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash - -ENV PATH="/root/.pyenv/bin:/root/.pyenv/shims:${PATH}" -RUN pyenv install 3.7.3 -RUN pyenv global 3.7.3 -RUN pyenv rehash - -COPY requirements.txt /tmp/ -RUN pip install -r /tmp/requirements.txt -COPY . /panda diff --git a/tests/safety/Dockerfile b/tests/safety/Dockerfile deleted file mode 100644 index 524cfc3991a071c..000000000000000 --- a/tests/safety/Dockerfile +++ /dev/null @@ -1,50 +0,0 @@ -FROM ubuntu:16.04 - -RUN apt-get update && apt-get install -y \ - autoconf \ - clang \ - curl \ - git \ - libtool \ - libssl-dev \ - libusb-1.0-0 \ - libzmq3-dev \ - locales \ - make \ - python \ - python-pip \ - wget \ - zlib1g-dev - -RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen -ENV LANG en_US.UTF-8 -ENV LANGUAGE en_US:en -ENV LC_ALL en_US.UTF-8 - -RUN curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash - -ENV PATH="/root/.pyenv/bin:/root/.pyenv/shims:${PATH}" -RUN pyenv install 3.7.3 -RUN pyenv global 3.7.3 -RUN pyenv rehash - -COPY requirements.txt /tmp/ -RUN pip install -r /tmp/requirements.txt - -WORKDIR /openpilot -RUN git clone https://github.com/commaai/opendbc.git || true -WORKDIR /openpilot/opendbc -RUN git pull && git checkout 7f3b1774dd248d4ebad91cc9de0fb1c561fab54b -WORKDIR /openpilot -RUN git clone https://github.com/commaai/cereal.git -WORKDIR /openpilot/cereal -RUN git pull && git checkout e370f79522ff7fc0b16f33f4fef420be48061206 -RUN /openpilot/cereal/install_capnp.sh - -RUN pip install -r /openpilot/opendbc/requirements.txt - -WORKDIR /openpilot -RUN cp /openpilot/opendbc/SConstruct /openpilot -COPY . /openpilot/panda - -RUN scons -c && scons -j$(nproc) diff --git a/tests/safety/common.py b/tests/safety/common.py index 8d81f115c18b771..945a974f2e648b1 100644 --- a/tests/safety/common.py +++ b/tests/safety/common.py @@ -32,8 +32,10 @@ def make_msg(bus, addr, length=8): return package_can_msg([addr, 0, b'\x00'*length, bus]) class CANPackerPanda(CANPacker): - def make_can_msg_panda(self, name_or_addr, bus, values, counter=-1): + def make_can_msg_panda(self, name_or_addr, bus, values, counter=-1, fix_checksum=None): msg = self.make_can_msg(name_or_addr, bus, values, counter=-1) + if fix_checksum is not None: + msg = fix_checksum(msg) return package_can_msg(msg) class PandaSafetyTestBase(unittest.TestCase): diff --git a/tests/safety/libpandasafety_py.py b/tests/safety/libpandasafety_py.py index 9898e6df8924b9c..00209c668379d9d 100644 --- a/tests/safety/libpandasafety_py.py +++ b/tests/safety/libpandasafety_py.py @@ -66,6 +66,7 @@ void init_tests_honda(void); void set_honda_fwd_brake(bool); void set_honda_alt_brake_msg(bool); +void set_honda_bosch_long(bool c); int get_honda_hw(void); void init_tests_chrysler(void); diff --git a/tests/safety/test.c b/tests/safety/test.c index 52d2ea7f1a10806..cf43baa9730cb02 100644 --- a/tests/safety/test.c +++ b/tests/safety/test.c @@ -71,6 +71,7 @@ void fault_recovered(uint32_t fault) { #define GET_BYTE(msg, b) (((int)(b) > 3) ? (((msg)->RDHR >> (8U * ((unsigned int)(b) % 4U))) & 0XFFU) : (((msg)->RDLR >> (8U * (unsigned int)(b))) & 0xFFU)) #define GET_BYTES_04(msg) ((msg)->RDLR) #define GET_BYTES_48(msg) ((msg)->RDHR) +#define GET_FLAG(value, mask) (((__typeof__(mask))param & mask) == mask) #define UNUSED(x) (void)(x) @@ -183,6 +184,10 @@ void set_honda_alt_brake_msg(bool c){ honda_alt_brake_msg = c; } +void set_honda_bosch_long(bool c){ + honda_bosch_long = c; +} + int get_honda_hw(void) { return honda_hw; } diff --git a/tests/safety/test_honda.py b/tests/safety/test_honda.py index 5cd2ba05f2cdd24..e053e4e586922fb 100755 --- a/tests/safety/test_honda.py +++ b/tests/safety/test_honda.py @@ -7,8 +7,6 @@ from panda.tests.safety.common import CANPackerPanda, make_msg, \ MAX_WRONG_COUNTERS, UNSAFE_MODE -MAX_BRAKE = 255 - class Btn: CANCEL = 2 SET = 3 @@ -20,11 +18,14 @@ class Btn: class TestHondaSafety(common.PandaSafetyTest): + MAX_BRAKE = 255 + PT_BUS = None # must be set when inherited + STEER_BUS = None # must be set when inherited + cnt_speed = 0 cnt_gas = 0 cnt_button = 0 - - PT_BUS = 0 + cnt_brake = 0 @classmethod def setUpClass(cls): @@ -58,15 +59,13 @@ def _gas_msg(self, gas): self.__class__.cnt_gas += 1 return self.packer.make_can_msg_panda("POWERTRAIN_DATA", self.PT_BUS, values) - def _send_brake_msg(self, brake): - values = {} - if self.safety.get_honda_hw() == HONDA_N_HW: - values = {"COMPUTER_BRAKE": brake} - return self.packer.make_can_msg_panda("BRAKE_COMMAND", 0, values) - def _send_steer_msg(self, steer): values = {"STEER_TORQUE": steer} - return self.packer.make_can_msg_panda("STEERING_CONTROL", 0, values) + return self.packer.make_can_msg_panda("STEERING_CONTROL", self.STEER_BUS, values) + + def _send_brake_msg(self, brake): + # must be implemented when inherited + raise NotImplementedError() def test_resume_button(self): self.safety.set_controls_allowed(0) @@ -157,13 +156,14 @@ def test_tx_hook_on_pedal_pressed(self): hw = self.safety.get_honda_hw() if hw == HONDA_N_HW: self.safety.set_honda_fwd_brake(False) - self.assertEqual(allow_ctrl, self._tx(self._send_brake_msg(MAX_BRAKE))) + self.assertEqual(allow_ctrl, self._tx(self._send_brake_msg(self.MAX_BRAKE))) self.assertEqual(allow_ctrl, self._tx(self._send_steer_msg(0x1000))) # reset status self.safety.set_controls_allowed(0) self.safety.set_unsafe_mode(UNSAFE_MODE.DEFAULT) - self._tx(self._send_brake_msg(0)) + if hw == HONDA_N_HW: + self._tx(self._send_brake_msg(0)) self._tx(self._send_steer_msg(0)) if pedal == 'brake': self._rx(self._speed_msg(0)) @@ -181,6 +181,9 @@ class TestHondaNidecSafety(TestHondaSafety, common.InterceptorSafetyTest): FWD_BLACKLISTED_ADDRS = {2: [0xE4, 0x194, 0x33D, 0x30C]} FWD_BUS_LOOKUP = {0: 2, 2: 0} + PT_BUS = 0 + STEER_BUS = 0 + INTERCEPTOR_THRESHOLD = 344 def setUp(self): @@ -197,6 +200,10 @@ def _interceptor_msg(self, gas, addr): ((gas2 & 0xff) << 24) | ((gas2 & 0xff00) << 8) return to_send + def _send_brake_msg(self, brake): + values = {"COMPUTER_BRAKE": brake} + return self.packer.make_can_msg_panda("BRAKE_COMMAND", 0, values) + def test_fwd_hook(self): # normal operation, not forwarding AEB self.FWD_BLACKLISTED_ADDRS[2].append(0x1FA) @@ -212,13 +219,13 @@ def test_fwd_hook(self): def test_brake_safety_check(self): for fwd_brake in [False, True]: self.safety.set_honda_fwd_brake(fwd_brake) - for brake in np.arange(0, MAX_BRAKE + 10, 1): + for brake in np.arange(0, self.MAX_BRAKE + 10, 1): for controls_allowed in [True, False]: self.safety.set_controls_allowed(controls_allowed) if fwd_brake: send = False # block openpilot brake msg when fwd'ing stock msg elif controls_allowed: - send = MAX_BRAKE >= brake >= 0 + send = self.MAX_BRAKE >= brake >= 0 else: send = brake == 0 self.assertEqual(send, self._tx(self._send_brake_msg(brake))) @@ -234,7 +241,7 @@ def test_tx_hook_on_interceptor_pressed(self): self.safety.set_controls_allowed(1) self.safety.set_honda_fwd_brake(False) - self.assertEqual(allow_ctrl, self._tx(self._send_brake_msg(MAX_BRAKE))) + self.assertEqual(allow_ctrl, self._tx(self._send_brake_msg(self.MAX_BRAKE))) self.assertEqual(allow_ctrl, self._tx(self._interceptor_msg(self.INTERCEPTOR_THRESHOLD, 0x200))) self.assertEqual(allow_ctrl, self._tx(self._send_steer_msg(0x1000))) @@ -247,27 +254,62 @@ def test_tx_hook_on_interceptor_pressed(self): self.safety.set_gas_interceptor_detected(False) -class TestHondaBoschHarnessSafety(TestHondaSafety): - TX_MSGS = [[0xE4, 0], [0xE5, 0], [0x296, 1], [0x33D, 0]] # Bosch Harness +class TestHondaBoschSafety(TestHondaSafety): STANDSTILL_THRESHOLD = 0 RELAY_MALFUNCTION_ADDR = 0xE4 + + @classmethod + def setUpClass(cls): + if cls.__name__ == "TestHondaBoschSafety": + cls.packer = None + cls.safety = None + raise unittest.SkipTest + + def setUp(self): + self.packer = CANPackerPanda("honda_accord_s2t_2018_can_generated") + self.safety = libpandasafety_py.libpandasafety + + def _alt_brake_msg(self, brake): + values = {"BRAKE_PRESSED": brake, "COUNTER": self.cnt_brake % 4} + self.__class__.cnt_brake += 1 + return self.packer.make_can_msg_panda("BRAKE_MODULE", self.PT_BUS, values) + + # TODO: add back in once alternative brake checksum/counter validation is added + # def test_alt_brake_rx_hook(self): + # self.safety.set_honda_alt_brake_msg(1) + # self.safety.set_controls_allowed(1) + # to_push = self._alt_brake_msg(0) + # self.assertTrue(self._rx(to_push)) + # to_push[0].RDLR = to_push[0].RDLR & 0xFFF0FFFF # invalidate checksum + # self.assertFalse(self._rx(to_push)) + # 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._rx(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._rx(self._alt_brake_msg(1)) + self.assertTrue(self.safety.get_controls_allowed()) + + +class TestHondaBoschHarnessSafety(TestHondaBoschSafety): + TX_MSGS = [[0xE4, 0], [0xE5, 0], [0x296, 1], [0x33D, 0]] # Bosch Harness RELAY_MALFUNCTION_BUS = 0 FWD_BLACKLISTED_ADDRS = {2: [0xE4, 0xE5, 0x33D]} FWD_BUS_LOOKUP = {0: 2, 2: 0} PT_BUS = 1 + STEER_BUS = 0 def setUp(self): - self.packer = CANPackerPanda("honda_accord_s2t_2018_can_generated") - self.safety = libpandasafety_py.libpandasafety + super().setUp() self.safety.set_safety_hooks(Panda.SAFETY_HONDA_BOSCH_HARNESS, 0) self.safety.init_tests_honda() - def _alt_brake_msg(self, brake): - to_send = make_msg(0, 0x1BE) - to_send[0].RDLR = 0x10 if brake else 0 - return to_send - def test_spam_cancel_safety_check(self): self.safety.set_controls_allowed(0) self.assertTrue(self._tx(self._button_msg(Btn.CANCEL))) @@ -277,37 +319,85 @@ def test_spam_cancel_safety_check(self): self.safety.set_controls_allowed(1) self.assertTrue(self._tx(self._button_msg(Btn.RESUME))) - def test_alt_disengage_on_brake(self): - self.safety.set_honda_alt_brake_msg(1) - self.safety.set_controls_allowed(1) - self._rx(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._rx(self._alt_brake_msg(1)) - self.assertTrue(self.safety.get_controls_allowed()) - class TestHondaBoschGiraffeSafety(TestHondaBoschHarnessSafety): TX_MSGS = [[0xE4, 2], [0xE5, 2], [0x296, 0], [0x33D, 2]] # Bosch Giraffe - STANDSTILL_THRESHOLD = 0 - RELAY_MALFUNCTION_ADDR = 0xE4 RELAY_MALFUNCTION_BUS = 2 FWD_BLACKLISTED_ADDRS = {1: [0xE4, 0xE5, 0x33D]} FWD_BUS_LOOKUP = {1: 2, 2: 1} PT_BUS = 0 + STEER_BUS = 2 def setUp(self): super().setUp() - self.safety = libpandasafety_py.libpandasafety self.safety.set_safety_hooks(Panda.SAFETY_HONDA_BOSCH_GIRAFFE, 0) self.safety.init_tests_honda() - def _send_steer_msg(self, steer): - values = {"STEER_TORQUE": steer} - return self.packer.make_can_msg_panda("STEERING_CONTROL", 2, values) + +class TestHondaBoschLongSafety(TestHondaBoschSafety): + NO_GAS = -30000 + MAX_GAS = 2000 + MAX_BRAKE = -3.5 + + @classmethod + def setUpClass(cls): + if cls.__name__ == "TestHondaBoschLongSafety": + cls.packer = None + cls.safety = None + raise unittest.SkipTest + + def _send_gas_brake_msg(self, gas, accel): + values = { + "GAS_COMMAND": gas, + "ACCEL_COMMAND": accel, + "BRAKE_REQUEST": accel < 0, + } + return self.packer.make_can_msg_panda("ACC_CONTROL", self.PT_BUS, values) + + def test_gas_safety_check(self): + for controls_allowed in [True, False]: + for gas in np.arange(self.NO_GAS, self.MAX_GAS + 2000, 100): + accel = 0 if gas < 0 else gas / 1000 + self.safety.set_controls_allowed(controls_allowed) + send = gas <= self.MAX_GAS if controls_allowed else gas == self.NO_GAS + self.assertEqual(send, self.safety.safety_tx_hook(self._send_gas_brake_msg(gas, accel)), gas) + + def test_brake_safety_check(self): + for controls_allowed in [True, False]: + for accel in np.arange(0, self.MAX_BRAKE - 1, -0.1): + self.safety.set_controls_allowed(controls_allowed) + send = self.MAX_BRAKE <= accel <= 0 if controls_allowed else accel == 0 + self.assertEqual(send, self._tx(self._send_gas_brake_msg(self.NO_GAS, accel)), (controls_allowed, accel)) + +class TestHondaBoschLongHarnessSafety(TestHondaBoschLongSafety): + TX_MSGS = [[0xE4, 1], [0x1DF, 1], [0x1EF, 1], [0x1FA, 1], [0x30C, 1], [0x33D, 1], [0x39F, 1], [0x18DAB0F1, 1]] # Bosch Harness w/ gas and brakes + RELAY_MALFUNCTION_BUS = 0 + FWD_BLACKLISTED_ADDRS = {2: [0xE4, 0xE5, 0x33D]} + FWD_BUS_LOOKUP = {0: 2, 2: 0} + + PT_BUS = 1 + STEER_BUS = 1 + + def setUp(self): + super().setUp() + self.safety.set_safety_hooks(Panda.SAFETY_HONDA_BOSCH_HARNESS, 2) + self.safety.init_tests_honda() + + +class TestHondaBoschLongGiraffeSafety(TestHondaBoschLongSafety): + TX_MSGS = [[0xE4, 0], [0x1DF, 0], [0x1EF, 0], [0x1FA, 0], [0x30C, 0], [0x33D, 0], [0x39F, 0], [0x18DAB0F1, 0]] # Bosch Giraffe w/ gas and brakes + RELAY_MALFUNCTION_BUS = 2 + FWD_BLACKLISTED_ADDRS = {1: [0xE4, 0xE5, 0x33D]} + FWD_BUS_LOOKUP = {1: 2, 2: 1} + + PT_BUS = 0 + STEER_BUS = 0 + + def setUp(self): + super().setUp() + self.safety.set_safety_hooks(Panda.SAFETY_HONDA_BOSCH_GIRAFFE, 2) + self.safety.init_tests_honda() if __name__ == "__main__": diff --git a/tests/safety/test_hyundai.py b/tests/safety/test_hyundai.py index dad07edf0f10016..9f173253c2644ac 100644 --- a/tests/safety/test_hyundai.py +++ b/tests/safety/test_hyundai.py @@ -16,6 +16,22 @@ DRIVER_TORQUE_ALLOWANCE = 50 DRIVER_TORQUE_FACTOR = 2 +# 4 bit checkusm used in some hyundai messages +# lives outside the can packer because we never send this msg +def checksum(msg): + addr, t, dat, bus = msg + + chksum = 0 + for i, b in enumerate(dat): + if addr in [608, 1057] and i == 7: + b &= 0x0F if addr == 1057 else 0xF0 + elif addr == 916 and i == 6: + b &= 0xF0 + chksum += sum(divmod(b, 16)) + chksum = (16 - chksum) % 16 + ret = bytearray(dat) + ret[6 if addr == 916 else 7] |= chksum << (4 if addr == 1057 else 0) + return addr, t, ret, bus class TestHyundaiSafety(common.PandaSafetyTest): TX_MSGS = [[832, 0], [1265, 0], [1157, 0]] @@ -43,24 +59,25 @@ def _button_msg(self, buttons): def _gas_msg(self, val): values = {"CF_Ems_AclAct": val, "AliveCounter": self.cnt_gas % 4} self.__class__.cnt_gas += 1 - return self.packer.make_can_msg_panda("EMS16", 0, values) + return self.packer.make_can_msg_panda("EMS16", 0, values, fix_checksum=checksum) def _brake_msg(self, brake): values = {"DriverBraking": brake, "AliveCounterTCS": self.cnt_brake % 8} self.__class__.cnt_brake += 1 - return self.packer.make_can_msg_panda("TCS13", 0, values) + return self.packer.make_can_msg_panda("TCS13", 0, values, fix_checksum=checksum) def _speed_msg(self, speed): # panda safety doesn't scale, so undo the scaling values = {"WHL_SPD_%s"%s: speed*0.03125 for s in ["FL", "FR", "RL", "RR"]} - values["WHL_SPD_AliveCounter_LSB"] = self.cnt_speed % 4 + values["WHL_SPD_AliveCounter_LSB"] = (self.cnt_speed % 16) & 0x3 + values["WHL_SPD_AliveCounter_MSB"] = (self.cnt_speed % 16) >> 2 self.__class__.cnt_speed += 1 return self.packer.make_can_msg_panda("WHL_SPD11", 0, values) def _pcm_status_msg(self, enabled): values = {"ACCMode": enabled, "CR_VSM_Alive": self.cnt_cruise % 16} self.__class__.cnt_cruise += 1 - return self.packer.make_can_msg_panda("SCC12", 0, values) + return self.packer.make_can_msg_panda("SCC12", 0, values, fix_checksum=checksum) def _set_prev_torque(self, t): self.safety.set_desired_torque_last(t) diff --git a/tests/safety/test_volkswagen_pq.py b/tests/safety/test_volkswagen_pq.py index f30d19f3f82af29..11310e025e1c612 100644 --- a/tests/safety/test_volkswagen_pq.py +++ b/tests/safety/test_volkswagen_pq.py @@ -82,7 +82,7 @@ def _pcm_status_msg(self, cruise): # Driver steering input torque def _lenkhilfe_3_msg(self, torque): - to_send = make_msg(0, MSG_LENKHILFE_3) + to_send = make_msg(0, MSG_LENKHILFE_3, 6) t = abs(torque) to_send[0].RDLR = ((t & 0x3FF) << 16) if torque < 0: @@ -94,7 +94,7 @@ def _lenkhilfe_3_msg(self, torque): # openpilot steering output torque def _hca_1_msg(self, torque): - to_send = make_msg(0, MSG_HCA_1) + to_send = make_msg(0, MSG_HCA_1, 5) t = abs(torque) << 5 # DBC scale from centi-Nm to PQ network (approximated) to_send[0].RDLR = (t & 0x7FFF) << 16 if torque < 0: @@ -120,7 +120,7 @@ def _gas_msg(self, gas): # Cruise control buttons def _gra_neu_msg(self, bit): - to_send = make_msg(2, MSG_GRA_NEU) + to_send = make_msg(2, MSG_GRA_NEU, 4) to_send[0].RDLR = 1 << bit to_send[0].RDLR |= volkswagen_pq_checksum(to_send[0], MSG_GRA_NEU, 8) return to_send diff --git a/tests/safety_replay/Dockerfile b/tests/safety_replay/Dockerfile deleted file mode 100644 index 09236e6a2adee49..000000000000000 --- a/tests/safety_replay/Dockerfile +++ /dev/null @@ -1,46 +0,0 @@ -FROM ubuntu:16.04 - -RUN apt-get update && apt-get install -y \ - bzip2 \ - clang \ - curl \ - git \ - libarchive-dev \ - libbz2-dev \ - libcurl4-openssl-dev \ - libffi-dev \ - libssl-dev \ - libusb-1.0-0 \ - locales \ - make \ - python \ - python-pip \ - zlib1g-dev - -RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen -ENV LANG en_US.UTF-8 -ENV LANGUAGE en_US:en -ENV LC_ALL en_US.UTF-8 - -RUN curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash - -ENV PATH="/root/.pyenv/bin:/root/.pyenv/shims:${PATH}" -RUN pyenv install 3.7.3 -RUN pyenv global 3.7.3 -RUN pyenv rehash - -COPY requirements.txt /tmp/ -RUN pip install -r /tmp/requirements.txt -COPY tests/safety_replay/requirements_extra.txt requirements_extra.txt -RUN pip install -r requirements_extra.txt -COPY tests/safety_replay/install_capnp.sh install_capnp.sh -RUN ./install_capnp.sh - -RUN git clone https://github.com/commaai/openpilot.git || true -WORKDIR /openpilot -RUN git pull && git checkout f9257fc75f68c673f9e433985fbe739f23310bb4 -RUN git submodule update --init cereal - -COPY . /openpilot/panda - -WORKDIR /openpilot/panda/tests/safety_replay