This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

DLPNIRNANOEVM: Python USB writing issue

Part Number: DLPNIRNANOEVM

Hi,

I have rewritten some parts of the C++ API bundled with the GUI as a small Python library for automation tasks and so on...

The message that gets written into the output buffer is quite similiar:

class USBMessage(Structure):
    class Header(Structure):
        class Flags(LittleEndianStructure):
            _fields_ = [("destination", c_ubyte, 2),
                        ("reserved",    c_ubyte, 2),
                        ("response",    c_ubyte, 2),
                        ("reply",       c_ubyte, 1),
                        ("rw",          c_ubyte, 1)]
                      
        _fields_ = [("flags", Flags),
                    ("sequence", c_ubyte),
                    ("length", c_ushort)]

    class Payload(Union):
        _fields_ = [("command", c_short),
                    ("data", (c_ubyte * _DATA_MAX_SIZE))]

    _fields_ = [("header", Header),
                ("payload", Payload)]

I am using the pyhidapi library for USB communication and writing commands to the EVM works fine but most of the time, reading from the device results in wrong data. Both input and output buffers are the same in the Python and the reference C++ version at any time except after calling the 'read' function.

    def _read_message(self):
        self._reset_input_buffer()
        
        msg_length = _USB_MIN_PACKET_SIZE
        bytes_read = 0
        
        if self._send_message() > 0:
            while bytes_read < msg_length:
                data = bytearray(self.read(_USB_MIN_PACKET_SIZE, self._timeout))
                dlength = len(data)

                self._input_buffer[bytes_read:bytes_read+dlength] = data
                if dlength < 0:
                    return bytes_read
                elif dlength == 0:
                    return ReturnType.READ_TIMEOUT.value

                if bytes_read == 0:
                    msg = USBMessage.from_buffer_copy(self._input_buffer)

                    if msg.header.flags.response == ResponseType.BUSY.value:
                        return ReturnType.BUSY.value
                    elif ((msg.header.flags.response == ResponseType.ERROR.value) or
                          (msg.header.length == 0)):
                        return ReturnType.NACK.value
                    
                    msg_length = sizeof(msg.header) + msg.header.length
                
                bytes_read += dlength
            return bytes_read
        return ReturnType.FAIL.value

If you compare it to the C++-Version, the code is quite similiar. My class inherits the hid.Device class from pyhidapi:

    def read(self, size, timeout=None):
        data = ctypes.create_string_buffer(size)

        if timeout is None:
            size = self.__hidcall(hidapi.hid_read, self.__dev, data, size)
        else:
            size = self.__hidcall(
                hidapi.hid_read_timeout, self.__dev, data, size, timeout)

        return data.raw[:size]

The call to the hid api is exactly the same as used in the GUI code (see USB.cpp). When reading from the device, the resulting header part is often wrong or only the flags are returned. If I run a small sample script to start the scan and poll for the device status, it works every fourth or fifth time but most of the time a header length value of zero is returned (_read_message will then return NACK).

So writing to the device works like a charm but reading not. Any ideas what is wrong with the Python code?

Thank you very much!

Lukas