Skip to content
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

Allow Zero Length Packet (ZLP) to be sent #753

Open
HiFiPhile opened this issue May 9, 2024 · 0 comments
Open

Allow Zero Length Packet (ZLP) to be sent #753

HiFiPhile opened this issue May 9, 2024 · 0 comments

Comments

@HiFiPhile
Copy link

From USB 2.0 specification:

 A bulk transfer is complete when the endpoint does one of the following:
• Has transferred exactly the amount of data expected
• Transfers a packet with a payload size less than wMaxPacketSize or transfers a zero-length packet
When a bulk transfer is complete, the Host Controller retires the current IRP and advances to the next IRP.
If a data payload is received that is larger than expected, all pending bulk IRPs for that endpoint will be
aborted/retired.

If a ZLP is not sent, the device layer could wait for more data.

A workaround for Windows is in pyserialwin32.py:

    def write(self, data):
        """Output the given byte string over the serial port."""
        if not self.is_open:
            raise PortNotOpenError()
        #~ if not isinstance(data, (bytes, bytearray)):
            #~ raise TypeError('expected %s or bytearray, got %s' % (bytes, type(data)))
        # convert data (needed in case of memoryview instance: Py 3.1 io lib), ctypes doesn't like memoryview
        data = to_bytes(data)
        #~ win32event.ResetEvent(self._overlapped_write.hEvent)
        n = win32.DWORD()
        if data:
            success = win32.WriteFile(self._port_handle, data, len(data), ctypes.byref(n), self._overlapped_write)
        else:
            success = win32.WriteFile(self._port_handle, 0, 0, ctypes.byref(n), self._overlapped_write)
        if self._write_timeout != 0:  # if blocking (None) or w/ write timeout (>0)
            if not success and win32.GetLastError() not in (win32.ERROR_SUCCESS, win32.ERROR_IO_PENDING):
                raise SerialException("WriteFile failed ({!r})".format(ctypes.WinError()))

            # Wait for the write to complete.
            #~ win32.WaitForSingleObject(self._overlapped_write.hEvent, win32.INFINITE)
            win32.GetOverlappedResult(self._port_handle, self._overlapped_write, ctypes.byref(n), True)
            if win32.GetLastError() == win32.ERROR_OPERATION_ABORTED:
                return n.value  # canceled IO is no error
            if n.value != len(data):
                raise SerialTimeoutException('Write timeout')
            return n.value
        else:
            errorcode = win32.ERROR_SUCCESS if success else win32.GetLastError()
            if errorcode in (win32.ERROR_INVALID_USER_BUFFER, win32.ERROR_NOT_ENOUGH_MEMORY,
                             win32.ERROR_OPERATION_ABORTED):
                return 0
            elif errorcode in (win32.ERROR_SUCCESS, win32.ERROR_IO_PENDING):
                # no info on true length provided by OS function in async mode
                return len(data)
            else:
                raise SerialException("WriteFile failed ({!r})".format(ctypes.WinError()))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant