Skip to content

Commit 38c4dc4

Browse files
authored
Vector: use global channel_index if provided (#1681)
* fix XL_ERR_INVALID_CHANNEL_MASK for multiple devices with the same serial * add CHANGELOG.md entry
1 parent 61ee42b commit 38c4dc4

File tree

3 files changed

+57
-6
lines changed

3 files changed

+57
-6
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Bug Fixes
1616
* Fix BLFReader error for incomplete or truncated stream (#1662)
1717
* PCAN: remove Windows registry check to fix 32bit compatibility (#1672)
1818
* Vector: Skip the `can_op_mode check` if the device reports `can_op_mode=0` (#1678)
19+
* Vector: using the config from `detect_available_configs` might raise XL_ERR_INVALID_CHANNEL_MASK error (#1681)
1920

2021
Features
2122
--------

can/interfaces/vector/canlib.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -202,12 +202,20 @@ def __init__(
202202
self._can_protocol = CanProtocol.CAN_FD if is_fd else CanProtocol.CAN_20
203203

204204
for channel in self.channels:
205-
channel_index = self._find_global_channel_idx(
206-
channel=channel,
207-
serial=serial,
208-
app_name=app_name,
209-
channel_configs=channel_configs,
210-
)
205+
if (_channel_index := kwargs.get("channel_index", None)) is not None:
206+
# VectorBus._detect_available_configs() might return multiple
207+
# devices with the same serial number, e.g. if a VN8900 is connected via both USB and Ethernet
208+
# at the same time. If the VectorBus is instantiated with a config, that was returned from
209+
# VectorBus._detect_available_configs(), then use the contained global channel_index
210+
# to avoid any ambiguities.
211+
channel_index = cast(int, _channel_index)
212+
else:
213+
channel_index = self._find_global_channel_idx(
214+
channel=channel,
215+
serial=serial,
216+
app_name=app_name,
217+
channel_configs=channel_configs,
218+
)
211219
LOG.debug("Channel index %d found", channel)
212220

213221
channel_mask = 1 << channel_index
@@ -950,6 +958,7 @@ def _detect_available_configs() -> List[AutoDetectedConfig]:
950958
"interface": "vector",
951959
"channel": channel_config.hw_channel,
952960
"serial": channel_config.serial_number,
961+
"channel_index": channel_config.channel_index,
953962
# data for use in VectorBus.set_application_config():
954963
"hw_type": channel_config.hw_type,
955964
"hw_index": channel_config.hw_index,

test/test_vector.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,22 @@ def test_bus_creation() -> None:
118118
bus.shutdown()
119119

120120

121+
@pytest.mark.skipif(not XLDRIVER_FOUND, reason="Vector XL API is unavailable")
122+
def test_bus_creation_channel_index() -> None:
123+
channel_index = 3
124+
bus = can.Bus(
125+
channel=0,
126+
serial=_find_virtual_can_serial(),
127+
channel_index=channel_index,
128+
interface="vector",
129+
)
130+
assert isinstance(bus, canlib.VectorBus)
131+
assert bus.protocol == can.CanProtocol.CAN_20
132+
assert bus.channel_masks[0] == 1 << channel_index
133+
134+
bus.shutdown()
135+
136+
121137
def test_bus_creation_bitrate_mocked(mock_xldriver) -> None:
122138
bus = can.Bus(channel=0, interface="vector", bitrate=200_000, _testing=True)
123139
assert isinstance(bus, canlib.VectorBus)
@@ -833,6 +849,31 @@ def test_get_channel_configs() -> None:
833849
canlib._get_xl_driver_config = _original_func
834850

835851

852+
@pytest.mark.skipif(
853+
sys.byteorder != "little", reason="Test relies on little endian data."
854+
)
855+
def test_detect_available_configs() -> None:
856+
_original_func = canlib._get_xl_driver_config
857+
canlib._get_xl_driver_config = _get_predefined_xl_driver_config
858+
859+
available_configs = canlib.VectorBus._detect_available_configs()
860+
861+
assert len(available_configs) == 5
862+
863+
assert available_configs[0]["interface"] == "vector"
864+
assert available_configs[0]["channel"] == 2
865+
assert available_configs[0]["serial"] == 1001
866+
assert available_configs[0]["channel_index"] == 2
867+
assert available_configs[0]["hw_type"] == xldefine.XL_HardwareType.XL_HWTYPE_VN8900
868+
assert available_configs[0]["hw_index"] == 0
869+
assert available_configs[0]["supports_fd"] is True
870+
assert isinstance(
871+
available_configs[0]["vector_channel_config"], VectorChannelConfig
872+
)
873+
874+
canlib._get_xl_driver_config = _original_func
875+
876+
836877
@pytest.mark.skipif(not IS_WINDOWS, reason="Windows specific test")
837878
def test_winapi_availability() -> None:
838879
assert canlib.WaitForSingleObject is not None

0 commit comments

Comments
 (0)