From 40e1e4b7ff3daa41f974a388b99d3d7b8bdbeb2f Mon Sep 17 00:00:00 2001 From: hcoffin-vecatom Date: Tue, 1 Oct 2024 09:38:34 -0700 Subject: [PATCH] Fixed bug in USBTMC code which caused issues when packets were longer than max usb packet size (#449) * following USBTMC specification sec. 3.3, updated read function for USBTMC class to correctly handle messages longer than the usb packet size. Created USBIntstrSession read to handle case where an incomplete message is read (i.e., before a term character is reached) * fixed linting errors * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * allowed suppress_end_en, changed Session_read so it won't hang when suppress_end_en==True * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * removed USBIntrsSession.read * update changelog --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: MatthieuDartiailh --- CHANGES | 4 ++++ pyvisa_py/protocols/usbtmc.py | 10 ++++++++-- pyvisa_py/sessions.py | 7 +++---- pyvisa_py/usb.py | 5 ----- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/CHANGES b/CHANGES index 7822169..b00bfc1 100644 --- a/CHANGES +++ b/CHANGES @@ -5,6 +5,10 @@ PyVISA-py Changelog ------------------ - add read_stb method for TCPIP HiSLIP client PR #429 +- fix usbtmc implementation to respect section 3.3 of the spec PR #449 + Read now reads from usb until a "short packet" has been read + (see specification), and only expects a header on the first packet received. +- add support for VI_ATTR_SUPPRESS_END_EN for USB resources PR #449 0.7.2 (07/03/2024) ------------------ diff --git a/pyvisa_py/protocols/usbtmc.py b/pyvisa_py/protocols/usbtmc.py index 483421f..fe50cfe 100644 --- a/pyvisa_py/protocols/usbtmc.py +++ b/pyvisa_py/protocols/usbtmc.py @@ -479,13 +479,19 @@ def read(self, size): try: resp = raw_read(recv_chunk + header_size + max_padding) response = BulkInMessage.from_bytes(resp) + received.extend(response.data) + while len(resp) == self.usb_recv_ep.wMaxPacketSize: + # USBTMC Section 3.3 specifies that the first usb packet + # must contain the header. the remaining packets do not need + # the header the message is finished when a "short packet" + # is sent (one whose length is less than wMaxPacketSize) + resp = raw_read(recv_chunk + header_size + max_padding) + received.extend(resp) except (usb.core.USBError, ValueError): # Abort failed Bulk-IN operation. self._abort_bulk_in(self._btag) raise - received.extend(response.data) - # Detect EOM only when device sends all expected bytes. if len(response.data) >= response.transfer_size: eom = response.transfer_attributes & 1 diff --git a/pyvisa_py/sessions.py b/pyvisa_py/sessions.py index f5c8e07..b2a09eb 100644 --- a/pyvisa_py/sessions.py +++ b/pyvisa_py/sessions.py @@ -796,10 +796,9 @@ def _read( if current: out.extend(current) end_indicator_received = end_indicator_checker(current) - if end_indicator_received: - if not suppress_end_en: - # RULE 6.1.1 - return bytes(out), StatusCode.success + if end_indicator_received and not suppress_end_en: + # RULE 6.1.1 + return bytes(out), StatusCode.success else: if termination_char_en and (term_char in current): # RULE 6.1.2 diff --git a/pyvisa_py/usb.py b/pyvisa_py/usb.py index bbc9c8e..7411683 100644 --- a/pyvisa_py/usb.py +++ b/pyvisa_py/usb.py @@ -157,11 +157,6 @@ def _usb_reader(): supress_end_en, _ = self.get_attribute(ResourceAttribute.suppress_end_enabled) - if supress_end_en: - raise ValueError( - "VI_ATTR_SUPPRESS_END_EN == True is currently unsupported by pyvisa-py" - ) - term_char, _ = self.get_attribute(ResourceAttribute.termchar) term_char_en, _ = self.get_attribute(ResourceAttribute.termchar_enabled)