-
-
Notifications
You must be signed in to change notification settings - Fork 124
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
solution to fix usbtmc frame partitioning issues on Linux. #468
Comments
After reading #465 I realized I was still on 0.7.1, sorry. After update: I did some tests with version 0.7.2: 1 - If I execute: I get: rep size : 54 image size : 2 I have the correct answer to "*IDN?", it is indeed 54 bytes. 2 - If I run only the screenshot: I get: .../lib64/python3.9/site-packages/pyvisa_py/protocols/usbtmc.py:116: image size : 56 I only get the first 56 bytes of the image (out of the expected 1843200 bytes). 3 - If I test version 0.7.2 on the Keysight EDUX1002A which does not partition its frames: the operation is correct. 4 - If I add my patch in version 0.7.2:
Version 0.7.2 seems less stable than 0.7.1 in case of partitioning of usbtmc frames. |
0.7.2 does not contain the fix I mentionned. Can you test installing the current main branch |
Hello, I haven't been able to do any yet "pip install git+https://github.com/pyvisa/pyvisa-py" under a Linux machine (python 3.9 not compatible). But I did some tests with PyVISA-py 0.7.3.dev34+g4a77dd0 under Windows. To check the integrity of the usbtmc frames I put the instruction "print(resp)" in the USBTMC.read() class Version 0.7.1 works fine. Version 0.7.2 crashes. Version 0.7.3.dev34+g4a77dd0 also crashes. In conclusion, I'm sticking with version 0.7.1 for now. |
What changed between 0.7.1 and 0.7.2 is that we now used the MaxPacketSize as reported by the USB endpoints instead of 2048 which was hardcoded. This was done to fix en issue with a Rigol scope whose size 64 and that truly could not manage larger transfer. Reading your first message, I understand that your patch is sufficient to recover valid data (although slowly I assume). Is that so ? resp = raw_read(recv_chunk + header_size + max_padding)
response = BulkInMessage.from_bytes(resp)
received_transfer.extend(response.data)
while (
len(resp) == self.usb_recv_ep.wMaxPacketSize
or len(received_transfer) < response.transfer_size
):
# 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)
# wMaxPacketSize may be incorrectly reported by certain drivers.
# Therefore, continue reading until the transfer_size is reached.
resp = raw_read(recv_chunk + header_size + max_padding)
received_transfer.extend(resp) So if your patch works I would expect 0.7.3 to also work. But the fact it is slow will remain. |
@Jimmyvandenbergh could you join this conversation. You and @jyfrau have spent far more time than me going though the USBTMC standard. |
I think that both in 0.7.2 and 0.7.3 some details are causing this problem.
@jyfrau are you able to test PR #470 with your device, i tested with a Rigol for *IDN? and tested multiple Admesy devices with |
please note that i have used I know in C you normally would use a known buffer size and request that amount of bytes from libusb. But here also multiple read may be performed as libusb does not return the so maybe there is a speed improvement to be made for large data returns in the future. |
Hello,
I am sharing with you a solution to fix the usbtmc frame partitioning issues that are not handled properly under Linux.
I am using pyvisa and pyvisa-py to communicate with Siglent devices (SSA3032X and SVA1032X). On Linux it does not work. I get the message "Unexpected MsgID format. Consider updating the device's firmware. See #20".
The problem comes from the fact that usbtmc frames are split into 64-byte packets. A problem that does not appear under Windows, nor on a Linux virtual machine on a Windows host (which therefore goes through the Windows driver...).
Although this partitioning management problem does not come from pyvisa-py, I found a solution to add a processing of these packets in the file "…/site-packages/pyvisa/usbtmc.c", in the read() function of the USBTMC class :
when receiving the usbtmc frame (resp = raw_read(…)), I read the data length field directly in the usbtmc header and I receive the missing packets (resp += raw_read(…)) as long as the usbtmc frame is not the expected length.
It takes just 3 lines of code (between "### DEB PATCH" and "### END PATCH"):
try:
resp = raw_read(recv_chunk + header_size + max_padding)
except (usb.core.USBError, ValueError):
# Abort failed Bulk-IN operation.
self._abort_bulk_in(self._btag)
raise
received.extend(response.data)
This partitioned frame handling in usbtmc.c works very well. I tested it with the Siglent SSA3032X and SVA1032X, as well as with a Keysight EDUX1002A (which does not partition its frames). I did this under Linux and under Windows, it works fine.
These 3 additional lines of code remain transparent if they are not needed but provide a great service in the event of partitioning poorly managed by the lower layers.
Although it is not the role of pyvisa-py to do this processing, do you think it is possible to integrate it into a future update of the pyvisa-py module?
Best regard
The modified read method of the USBTMC class:
The text was updated successfully, but these errors were encountered: