@ -7,109 +7,165 @@
// 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_BH_TX_MSGS [ ] = { { 0xE4 , 0 } , { 0x296 , 1 } , { 0x33D , 0 } } ; // Bosch Harness
const AddrBus HONDA_BG_TX_MSGS [ ] = { { 0xE4 , 2 } , { 0x296 , 0 } , { 0x33D , 2 } } ; // Bosch Giraffe
const AddrBus HONDA_BH_TX_MSGS [ ] = { { 0xE4 , 0 } , { 0x296 , 1 } , { 0x33D , 0 } } ; // Bosch Harness
const int HONDA_GAS_INTERCEPTOR_THRESHOLD = 328 ; // ratio between offset and gain from dbc file
// 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 } ,
} ;
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 } ,
} ;
const int HONDA_BH_RX_CHECKS_LEN = sizeof ( honda_bh_rx_checks ) / sizeof ( honda_bh_rx_checks [ 0 ] ) ;
int honda_brake = 0 ;
int honda_gas_prev = 0 ;
bool honda_brake_pressed_prev = false ;
bool honda_moving = false ;
bool honda_bosch_hardware = false ;
bool honda_alt_brake_msg = false ;
bool honda_fwd_brake = false ;
enum { HONDA_N_HW , HONDA_BG_HW , HONDA_BH_HW } honda_hw = HONDA_N_HW ;
static void honda_rx_hook ( CAN_FIFOMailBox_TypeDef * to_push ) {
int addr = GET_ADDR ( to_push ) ;
static uint8_t honda_get_checksum ( CAN_FIFOMailBox_TypeDef * to_push ) {
int checksum_byte = GET_LEN ( to_push ) - 1 ;
return ( uint8_t ) ( GET_BYTE ( to_push , checksum_byte ) ) & 0xFU ;
}
static uint8_t honda_compute_checksum ( CAN_FIFOMailBox_TypeDef * to_push ) {
int len = GET_LEN ( to_push ) ;
int bus = GET_BUS ( to_push ) ;
uint8_t checksum = 0U ;
unsigned int addr = GET_ADDR ( to_push ) ;
while ( addr > 0U ) {
checksum + = ( addr & 0xFU ) ; addr > > = 4 ;
}
for ( int j = 0 ; ( j < len ) ; j + + ) {
uint8_t byte = GET_BYTE ( to_push , j ) ;
checksum + = ( byte & 0xFU ) + ( byte > > 4U ) ;
if ( j = = ( len - 1 ) ) {
checksum - = ( byte & 0xFU ) ; // remove checksum in message
}
}
return ( 8U - checksum ) & 0xFU ;
}
// sample speed
if ( addr = = 0x158 ) {
// first 2 bytes
honda_moving = GET_BYTE ( to_push , 0 ) | GET_BYTE ( to_push , 1 ) ;
static uint8_t honda_get_counter ( CAN_FIFOMailBox_TypeDef * to_push ) {
int counter_byte = GET_LEN ( to_push ) - 1 ;
return ( ( uint8_t ) ( GET_BYTE ( to_push , counter_byte ) ) > > 4U ) & 0x3U ;
}
static int honda_rx_hook ( CAN_FIFOMailBox_TypeDef * to_push ) {
bool valid ;
if ( honda_hw = = HONDA_BH_HW ) {
valid = addr_safety_check ( to_push , honda_bh_rx_checks , HONDA_BH_RX_CHECKS_LEN ,
honda_get_checksum , honda_compute_checksum , honda_get_counter ) ;
} else {
valid = addr_safety_check ( to_push , honda_rx_checks , HONDA_RX_CHECKS_LEN ,
honda_get_checksum , honda_compute_checksum , honda_get_counter ) ;
}
// state machine to enter and exit controls
// 0x1A6 for the ILX, 0x296 for the Civic Touring
if ( ( addr = = 0x1A6 ) | | ( addr = = 0x296 ) ) {
int button = ( GET_BYTE ( to_push , 0 ) & 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
if ( valid ) {
int addr = GET_ADDR ( to_push ) ;
int len = GET_LEN ( to_push ) ;
int bus = GET_BUS ( to_push ) ;
// sample speed
if ( addr = = 0x158 ) {
// first 2 bytes
honda_moving = GET_BYTE ( to_push , 0 ) | GET_BYTE ( to_push , 1 ) ;
}
}
// user brake signal on 0x17C reports applied brake from computer brake on accord
// and crv, which prevents the usual brake safety from working correctly. these
// cars have a signal on 0x1BE which only detects user's brake being applied so
// in these cases, this is used instead.
// most hondas: 0x17C bit 53
// accord, crv: 0x1BE bit 4
// exit controls on rising edge of brake press or on brake press when speed > 0
bool is_user_brake_msg = honda_alt_brake_msg ? ( ( addr ) = = 0x1BE ) : ( ( addr ) = = 0x17C ) ;
if ( is_user_brake_msg ) {
bool brake_pressed = honda_alt_brake_msg ? ( GET_BYTE ( ( to_push ) , 0 ) & 0x10 ) : ( GET_BYTE ( ( to_push ) , 6 ) & 0x20 ) ;
if ( brake_pressed & & ( ! ( honda_brake_pressed_prev ) | | honda_moving ) ) {
controls_allowed = 0 ;
// state machine to enter and exit controls
// 0x1A6 for the ILX, 0x296 for the Civic Touring
if ( ( addr = = 0x1A6 ) | | ( addr = = 0x296 ) ) {
int button = ( GET_BYTE ( to_push , 0 ) & 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
}
}
honda_brake_pressed_prev = brake_pressed ;
}
// 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 ( ( addr = = 0x201 ) & & ( len = = 6 ) ) {
gas_interceptor_detected = 1 ;
int gas_interceptor = GET_INTERCEPTOR ( to_push ) ;
if ( ( gas_interceptor > HONDA_GAS_INTERCEPTOR_THRESHOLD ) & &
( gas_interceptor_prev < = HONDA_GAS_INTERCEPTOR_THRESHOLD ) & &
long_controls_allowed ) {
controls_allowed = 0 ;
// user brake signal on 0x17C reports applied brake from computer brake on accord
// and crv, which prevents the usual brake safety from working correctly. these
// cars have a signal on 0x1BE which only detects user's brake being applied so
// in these cases, this is used instead.
// most hondas: 0x17C bit 53
// accord, crv: 0x1BE bit 4
// exit controls on rising edge of brake press or on brake press when speed > 0
bool is_user_brake_msg = honda_alt_brake_msg ? ( ( addr ) = = 0x1BE ) : ( ( addr ) = = 0x17C ) ;
if ( is_user_brake_msg ) {
bool brake_pressed = honda_alt_brake_msg ? ( GET_BYTE ( ( to_push ) , 0 ) & 0x10 ) : ( GET_BYTE ( ( to_push ) , 6 ) & 0x20 ) ;
if ( brake_pressed & & ( ! ( honda_brake_pressed_prev ) | | honda_moving ) ) {
controls_allowed = 0 ;
}
honda_brake_pressed_prev = brake_pressed ;
}
gas_interceptor_prev = gas_interceptor ;
}
// exit controls on rising edge of gas press if no interceptor
if ( ! gas_interceptor_detected ) {
if ( addr = = 0x17C ) {
int gas = GET_BYTE ( to_push , 0 ) ;
if ( gas & & ! ( honda_gas_prev ) & & long_controls_allowed ) {
// 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 ( ( addr = = 0x201 ) & & ( len = = 6 ) ) {
gas_interceptor_detected = 1 ;
int gas_interceptor = GET_INTERCEPTOR ( to_push ) ;
if ( ( gas_interceptor > HONDA_GAS_INTERCEPTOR_THRESHOLD ) & &
( gas_interceptor_prev < = HONDA_GAS_INTERCEPTOR_THRESHOLD ) ) {
controls_allowed = 0 ;
}
honda_ gas_prev = gas ;
gas_interceptor _prev = gas_interceptor ;
}
}
if ( ( bus = = 2 ) & & ( addr = = 0x1FA ) ) {
bool honda_stock_aeb = GET_BYTE ( to_push , 3 ) & 0x20 ;
int honda_stock_brake = ( GET_BYTE ( to_push , 0 ) < < 2 ) + ( ( GET_BYTE ( to_push , 1 ) > > 6 ) & 0x3 ) ;
// Forward AEB when stock braking is higher than openpilot braking
// only stop forwarding when AEB event is over
if ( ! honda_stock_aeb ) {
honda_fwd_brake = false ;
} else if ( honda_stock_brake > = honda_brake ) {
honda_fwd_brake = true ;
} else {
// Leave Honda forward brake as is
// exit controls on rising edge of gas press if no interceptor
if ( ! gas_interceptor_detected ) {
if ( addr = = 0x17C ) {
int gas = GET_BYTE ( to_push , 0 ) ;
if ( gas & & ! honda_gas_prev ) {
controls_allowed = 0 ;
}
honda_gas_prev = gas ;
}
}
}
if ( ( bus = = 2 ) & & ( addr = = 0x1FA ) ) {
bool honda_stock_aeb = GET_BYTE ( to_push , 3 ) & 0x20 ;
int honda_stock_brake = ( GET_BYTE ( to_push , 0 ) < < 2 ) + ( ( GET_BYTE ( to_push , 1 ) > > 6 ) & 0x3 ) ;
// if steering controls messages are received on the destination bus, it's an indication
// that the relay might be malfunctioning
int bus_rdr_car = ( board_has_relay ( ) ) ? 0 : 2 ; // radar bus, car side
if ( ( safety_mode_cnt > RELAY_TRNS_TIMEOUT ) & & ( ( addr = = 0xE4 ) | | ( addr = = 0x194 ) ) ) {
if ( ( honda_bosch_hardware & & ( bus = = bus_rdr_car ) ) | |
( ! honda_bosch_hardware & & ( bus = = 0 ) ) ) {
relay_malfunction = true ;
// Forward AEB when stock braking is higher than openpilot braking
// only stop forwarding when AEB event is over
if ( ! honda_stock_aeb ) {
honda_fwd_brake = false ;
} else if ( honda_stock_brake > = honda_brake ) {
honda_fwd_brake = true ;
} else {
// Leave Honda forward brake as is
}
}
// if steering controls messages are received on the destination bus, it's an indication
// that the relay might be malfunctioning
int bus_rdr_car = ( honda_hw = = HONDA_BH_HW ) ? 0 : 2 ; // radar bus, car side
if ( ( safety_mode_cnt > RELAY_TRNS_TIMEOUT ) & & ( ( addr = = 0xE4 ) | | ( addr = = 0x194 ) ) ) {
if ( ( ( honda_hw ! = HONDA_N_HW ) & & ( bus = = bus_rdr_car ) ) | |
( ( honda_hw = = HONDA_N_HW ) & & ( bus = = 0 ) ) ) {
relay_malfunction = true ;
}
}
}
return valid ;
}
// all commands: gas, brake and steering
@ -124,16 +180,12 @@ static int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
int addr = GET_ADDR ( to_send ) ;
int bus = GET_BUS ( to_send ) ;
if ( honda_bosch_hardware ) {
if ( board_has_relay ( ) & & ! addr_allowed ( addr , bus , HONDA_BH_TX_MSGS , sizeof ( HONDA_BH_TX_MSGS ) / sizeof ( HONDA_BH_TX_MSGS [ 0 ] ) ) ) {
tx = 0 ;
}
if ( ! board_has_relay ( ) & & ! addr_allowed ( addr , bus , HONDA_BG_TX_MSGS , sizeof ( HONDA_BG_TX_MSGS ) / sizeof ( HONDA_BG_TX_MSGS [ 0 ] ) ) ) {
tx = 0 ;
}
}
if ( ! honda_bosch_hardware & & ! addr_allowed ( addr , bus , HONDA_N_TX_MSGS , sizeof ( HONDA_N_TX_MSGS ) / sizeof ( HONDA_N_TX_MSGS [ 0 ] ) ) ) {
tx = 0 ;
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 ] ) ) ;
} else {
tx = msg_allowed ( addr , bus , HONDA_N_TX_MSGS , sizeof ( HONDA_N_TX_MSGS ) / sizeof ( HONDA_N_TX_MSGS [ 0 ] ) ) ;
}
if ( relay_malfunction ) {
@ -149,7 +201,7 @@ static int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
// BRAKE: safety check
if ( ( addr = = 0x1FA ) & & ( bus = = 0 ) ) {
honda_brake = ( GET_BYTE ( to_send , 0 ) < < 2 ) + ( ( GET_BYTE ( to_send , 1 ) > > 6 ) & 0x3 ) ;
if ( ! current_controls_allowed | | ! long_controls_allowed ) {
if ( ! current_controls_allowed ) {
if ( honda_brake ! = 0 ) {
tx = 0 ;
}
@ -174,7 +226,7 @@ static int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
// GAS: safety check
if ( addr = = 0x200 ) {
if ( ! current_controls_allowed | | ! long_controls_allowed ) {
if ( ! current_controls_allowed ) {
if ( GET_BYTE ( to_send , 0 ) | | GET_BYTE ( to_send , 1 ) ) {
tx = 0 ;
}
@ -184,9 +236,8 @@ 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 = ( ( board_has_relay ( ) ) & & honda_bosch_hardware ) ? 1 : 0 ;
if ( ( addr = = 0x296 ) & & honda_bosch_hardware & &
! current_controls_allowed & & ( bus = = bus_pt ) ) {
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 ;
}
@ -196,23 +247,31 @@ static int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
return tx ;
}
static void honda_init ( int16_t param ) {
static void honda_nidec_ init ( int16_t param ) {
UNUSED ( param ) ;
controls_allowed = false ;
relay_malfunction = false ;
honda_bosch_hardware = false ;
honda_hw = HONDA_N_HW ;
honda_alt_brake_msg = false ;
}
static void honda_bosch_init ( int16_t param ) {
static void honda_bosch_giraffe_init ( int16_t param ) {
controls_allowed = false ;
relay_malfunction = false ;
honda_hw = HONDA_BG_HW ;
// Checking for alternate brake override from safety parameter
honda_alt_brake_msg = ( param = = 1 ) ? true : false ;
}
static void honda_bosch_harness_init ( int16_t param ) {
controls_allowed = false ;
relay_malfunction = false ;
honda_bosch_hardware = true ;
honda_hw = HONDA_BH_HW ;
// Checking for alternate brake override from safety parameter
honda_alt_brake_msg = ( param = = 1 ) ? true : false ;
}
static int honda_fwd_hook ( int bus_num , CAN_FIFOMailBox_TypeDef * to_fwd ) {
static int honda_nidec_ fwd_hook ( int bus_num , CAN_FIFOMailBox_TypeDef * to_fwd ) {
// fwd from car to camera. also fwd certain msgs from camera to car
// 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,
@ -228,9 +287,7 @@ static int honda_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
bool is_lkas_msg = ( addr = = 0xE4 ) | | ( addr = = 0x194 ) | | ( addr = = 0x33D ) ;
bool is_acc_hud_msg = addr = = 0x30C ;
bool is_brake_msg = addr = = 0x1FA ;
bool block_fwd = is_lkas_msg | |
( is_acc_hud_msg & & long_controls_allowed ) | |
( is_brake_msg & & long_controls_allowed & & ! honda_fwd_brake ) ;
bool block_fwd = is_lkas_msg | | is_acc_hud_msg | | ( is_brake_msg & & ! honda_fwd_brake ) ;
if ( ! block_fwd ) {
bus_fwd = 0 ;
}
@ -241,8 +298,8 @@ static int honda_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
static int honda_bosch_fwd_hook ( int bus_num , CAN_FIFOMailBox_TypeDef * to_fwd ) {
int bus_fwd = - 1 ;
int bus_rdr_cam = ( board_has_relay ( ) ) ? 2 : 1 ; // radar bus, camera side
int bus_rdr_car = ( board_has_relay ( ) ) ? 0 : 2 ; // radar bus, car side
int bus_rdr_cam = ( honda_hw = = HONDA_BH_HW ) ? 2 : 1 ; // radar bus, camera side
int bus_rdr_car = ( honda_hw = = HONDA_BH_HW ) ? 0 : 2 ; // radar bus, car side
if ( ! relay_malfunction ) {
if ( bus_num = = bus_rdr_car ) {
@ -259,18 +316,32 @@ static int honda_bosch_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
return bus_fwd ;
}
const safety_hooks honda_hooks = {
. init = honda_init ,
const safety_hooks honda_nidec_ hooks = {
. init = honda_nidec_ init ,
. rx = honda_rx_hook ,
. tx = honda_tx_hook ,
. tx_lin = nooutput_tx_lin_hook ,
. fwd = honda_fwd_hook ,
. fwd = honda_nidec_fwd_hook ,
. addr_check = honda_rx_checks ,
. addr_check_len = sizeof ( honda_rx_checks ) / sizeof ( honda_rx_checks [ 0 ] ) ,
} ;
const safety_hooks honda_bosch_giraffe_hooks = {
. init = honda_bosch_giraffe_init ,
. rx = honda_rx_hook ,
. tx = honda_tx_hook ,
. tx_lin = nooutput_tx_lin_hook ,
. fwd = honda_bosch_fwd_hook ,
. addr_check = honda_rx_checks ,
. addr_check_len = sizeof ( honda_rx_checks ) / sizeof ( honda_rx_checks [ 0 ] ) ,
} ;
const safety_hooks honda_bosch_hooks = {
. init = honda_bosch_init ,
const safety_hooks honda_bosch_harness_h ooks = {
. init = honda_bosch_harness_ init ,
. rx = honda_rx_hook ,
. tx = honda_tx_hook ,
. tx_lin = nooutput_tx_lin_hook ,
. fwd = honda_bosch_fwd_hook ,
. addr_check = honda_bh_rx_checks ,
. addr_check_len = sizeof ( honda_bh_rx_checks ) / sizeof ( honda_bh_rx_checks [ 0 ] ) ,
} ;