Skip to content

Commit 6044d93

Browse files
committed
ixxat: Raise exception on busoff in recv()
1 parent 00b72dc commit 6044d93

2 files changed

Lines changed: 56 additions & 2 deletions

File tree

can/interfaces/ixxat/canlib.py

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,14 @@
2828
from . import constants, structures
2929
from .exceptions import *
3030

31-
__all__ = ["VCITimeout", "VCIError", "VCIDeviceNotFoundError", "IXXATBus", "vciFormatError"]
31+
__all__ = [
32+
"VCITimeout",
33+
"VCIError",
34+
"VCIBusOffError",
35+
"VCIDeviceNotFoundError",
36+
"IXXATBus",
37+
"vciFormatError",
38+
]
3239

3340
log = logging.getLogger('can.ixxat')
3441

@@ -232,6 +239,15 @@ def __check_status(result, function, arguments):
232239
constants.CAN_ERROR_CRC: "CAN CRC error",
233240
constants.CAN_ERROR_OTHER: "Other (unknown) CAN error",
234241
}
242+
243+
CAN_STATUS_FLAGS = {
244+
constants.CAN_STATUS_TXPEND: "transmission pending",
245+
constants.CAN_STATUS_OVRRUN: "data overrun occurred",
246+
constants.CAN_STATUS_ERRLIM: "error warning limit exceeded",
247+
constants.CAN_STATUS_BUSOFF: "bus off",
248+
constants.CAN_STATUS_ININIT: "init mode active",
249+
constants.CAN_STATUS_BUSCERR: "bus coupling error",
250+
}
235251
#----------------------------------------------------------------------------
236252

237253

@@ -455,6 +471,11 @@ def _recv_internal(self, timeout):
455471

456472
elif self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_TIMEOVR:
457473
pass
474+
475+
elif self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_STATUS:
476+
log.info(_format_can_status(self._message.abData[0]))
477+
if self._message.abData[0] & constants.CAN_STATUS_BUSOFF:
478+
raise VCIBusOffError()
458479
else:
459480
log.warn("Unexpected message info type")
460481

@@ -575,3 +596,25 @@ def stop(self):
575596
# the list with permanently stopped messages
576597
_canlib.canSchedulerRemMessage(self._scheduler, self._index)
577598
self._index = None
599+
600+
601+
def _format_can_status(status_flags: int):
602+
"""
603+
Format a status bitfield found in CAN_MSGTYPE_STATUS messages or in dwStatus
604+
field in CANLINESTATUS.
605+
606+
Valid states are defined in the CAN_STATUS_* constants in cantype.h
607+
"""
608+
states = []
609+
for flag, description in CAN_STATUS_FLAGS.items():
610+
if status_flags & flag:
611+
states.append(description)
612+
status_flags &= ~flag
613+
614+
if status_flags:
615+
states.append("unknown state 0x{:02x}".format(status_flags))
616+
617+
if states:
618+
return "CAN status message: {}".format(", ".join(states))
619+
else:
620+
return "Empty CAN status message"

can/interfaces/ixxat/exceptions.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,13 @@
88

99
from can import CanError
1010

11-
__all__ = ['VCITimeout', 'VCIError', 'VCIRxQueueEmptyError', 'VCIDeviceNotFoundError']
11+
__all__ = [
12+
'VCITimeout',
13+
'VCIError',
14+
'VCIRxQueueEmptyError',
15+
'VCIBusOffError',
16+
'VCIDeviceNotFoundError',
17+
]
1218

1319

1420
class VCITimeout(CanError):
@@ -27,5 +33,10 @@ def __init__(self):
2733
super(VCIRxQueueEmptyError, self).__init__("Receive queue is empty")
2834

2935

36+
class VCIBusOffError(VCIError):
37+
def __init__(self):
38+
super().__init__("Controller is in BUSOFF state")
39+
40+
3041
class VCIDeviceNotFoundError(CanError):
3142
pass

0 commit comments

Comments
 (0)