Skip to content

Commit b27a61d

Browse files
authored
ixxat: Raise exception on busoff in recv() (hardbyte#856)
1 parent f451de8 commit b27a61d

File tree

2 files changed

+51
-1
lines changed

2 files changed

+51
-1
lines changed

can/interfaces/ixxat/canlib.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
__all__ = [
3030
"VCITimeout",
3131
"VCIError",
32+
"VCIBusOffError",
3233
"VCIDeviceNotFoundError",
3334
"IXXATBus",
3435
"vciFormatError",
@@ -354,6 +355,15 @@ def __check_status(result, function, arguments):
354355
constants.CAN_ERROR_CRC: "CAN CRC error",
355356
constants.CAN_ERROR_OTHER: "Other (unknown) CAN error",
356357
}
358+
359+
CAN_STATUS_FLAGS = {
360+
constants.CAN_STATUS_TXPEND: "transmission pending",
361+
constants.CAN_STATUS_OVRRUN: "data overrun occurred",
362+
constants.CAN_STATUS_ERRLIM: "error warning limit exceeded",
363+
constants.CAN_STATUS_BUSOFF: "bus off",
364+
constants.CAN_STATUS_ININIT: "init mode active",
365+
constants.CAN_STATUS_BUSCERR: "bus coupling error",
366+
}
357367
# ----------------------------------------------------------------------------
358368

359369

@@ -644,6 +654,13 @@ def _recv_internal(self, timeout):
644654
)
645655
)
646656

657+
elif (
658+
self._message.uMsgInfo.Bits.type == constants.CAN_MSGTYPE_STATUS
659+
):
660+
log.info(_format_can_status(self._message.abData[0]))
661+
if self._message.abData[0] & constants.CAN_STATUS_BUSOFF:
662+
raise VCIBusOffError()
663+
647664
elif (
648665
self._message.uMsgInfo.Bits.type
649666
== constants.CAN_MSGTYPE_TIMEOVR
@@ -761,3 +778,25 @@ def stop(self):
761778
# the list with permanently stopped messages
762779
_canlib.canSchedulerRemMessage(self._scheduler, self._index)
763780
self._index = None
781+
782+
783+
def _format_can_status(status_flags: int):
784+
"""
785+
Format a status bitfield found in CAN_MSGTYPE_STATUS messages or in dwStatus
786+
field in CANLINESTATUS.
787+
788+
Valid states are defined in the CAN_STATUS_* constants in cantype.h
789+
"""
790+
states = []
791+
for flag, description in CAN_STATUS_FLAGS.items():
792+
if status_flags & flag:
793+
states.append(description)
794+
status_flags &= ~flag
795+
796+
if status_flags:
797+
states.append("unknown state 0x{:02x}".format(status_flags))
798+
799+
if states:
800+
return "CAN status message: {}".format(", ".join(states))
801+
else:
802+
return "Empty CAN status message"

can/interfaces/ixxat/exceptions.py

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

77
from can import CanError
88

9-
__all__ = ["VCITimeout", "VCIError", "VCIRxQueueEmptyError", "VCIDeviceNotFoundError"]
9+
__all__ = [
10+
"VCITimeout",
11+
"VCIError",
12+
"VCIRxQueueEmptyError",
13+
"VCIBusOffError",
14+
"VCIDeviceNotFoundError",
15+
]
1016

1117

1218
class VCITimeout(CanError):
@@ -24,5 +30,10 @@ def __init__(self):
2430
super().__init__("Receive queue is empty")
2531

2632

33+
class VCIBusOffError(VCIError):
34+
def __init__(self):
35+
super().__init__("Controller is in BUSOFF state")
36+
37+
2738
class VCIDeviceNotFoundError(CanError):
2839
pass

0 commit comments

Comments
 (0)