From: 
Subject: Debian changes

The Debian packaging of python-serialx is maintained in git, using a workflow
similar to the one described in dgit-maint-merge(7).
The Debian delta is represented by this one combined patch; there isn't a
patch queue that can be represented as a quilt series.

A detailed breakdown of the changes is available from their canonical
representation -- git commits in the packaging repository.
For example, to see the changes made by the Debian maintainer in the first
upload of upstream version 1.2.3, you could use:

    % git clone https://git.dgit.debian.org/python-serialx
    % cd python-serialx
    % git log --oneline 1.2.3..debian/1.2.3-1 -- . ':!debian'

(If you have dgit, use `dgit clone python-serialx`, rather than plain `git clone`.)

We don't use debian/source/options single-debian-patch because it has bugs.
Therefore, NMUs etc. may nevertheless have made additional patches.

---

diff --git a/Cargo.toml b/Cargo.toml
index 3cce8f1..d59aeea 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,12 +8,4 @@ name = "_serialx_rust"
 crate-type = ["cdylib"]
 
 [dependencies]
-pyo3 = { version = "0.23", features = ["extension-module", "abi3-py310"] }
-
-[target.'cfg(target_os = "macos")'.dependencies]
-core-foundation = "0.10"
-core-foundation-sys = "0.8"
-io-kit-sys = "0.4"
-
-[target.'cfg(target_os = "windows")'.dependencies]
-serialport = { version = "4", features = ["usbportinfo-interface"] }
+pyo3 = { version = ">=0.27,<0.29", features = ["extension-module", "abi3-py310"] }
diff --git a/serialx/descriptor_transport.py b/serialx/descriptor_transport.py
index 875fad5..b93eb27 100644
--- a/serialx/descriptor_transport.py
+++ b/serialx/descriptor_transport.py
@@ -80,7 +80,7 @@ class DescriptorTransport(BaseSerialTransport):
         )
 
         try:
-            self._fileno = await self._open_fut
+            self._fileno = await asyncio.shield(self._open_fut)
         except asyncio.CancelledError:
             # `os.open` may still finish in the executor after cancellation. If that
             # happens, close the resulting fd to avoid leaks.
diff --git a/serialx/platforms/serial_linux.py b/serialx/platforms/serial_linux.py
index 5df26c5..83b841e 100644
--- a/serialx/platforms/serial_linux.py
+++ b/serialx/platforms/serial_linux.py
@@ -10,6 +10,7 @@ import ctypes
 import errno
 import fcntl
 import logging
+import os
 from pathlib import Path
 import sys
 import termios
@@ -29,8 +30,31 @@ PORT_UNKNOWN = 0
 ASYNC_LOW_LATENCY = 1 << 13
 CMSPAR = 0o10000000000
 TCGETS = 0x5401
-TCGETS2 = 0x802C542A
-TCSETS2 = 0x402C542B
+
+_IOC_NRBITS = 8
+_IOC_TYPEBITS = 8
+_IOC_SIZEBITS = 14
+_IOC_WRITE = 1
+_IOC_READ = 2
+
+if os.uname().machine.startswith("ppc"):
+    _IOC_SIZEBITS = 13
+    _IOC_WRITE = 4
+
+_IOC_NRSHIFT = 0
+_IOC_TYPESHIFT = _IOC_NRSHIFT + _IOC_NRBITS
+_IOC_SIZESHIFT = _IOC_TYPESHIFT + _IOC_TYPEBITS
+_IOC_DIRSHIFT = _IOC_SIZESHIFT + _IOC_SIZEBITS
+
+
+def _ioc(direction: int, request_type: int, number: int, size: int) -> int:
+    return (
+        (direction << _IOC_DIRSHIFT)
+        | (request_type << _IOC_TYPESHIFT)
+        | (number << _IOC_NRSHIFT)
+        | (size << _IOC_SIZESHIFT)
+    )
+
 
 TIOCGSERIAL = getattr(termios, "TIOCGSERIAL", None)
 TIOCSSERIAL = getattr(termios, "TIOCSSERIAL", None)
@@ -64,6 +88,10 @@ class Termios2Struct(ctypes.Structure):
     )
 
 
+TCGETS2 = _ioc(_IOC_READ, ord("T"), 0x2A, ctypes.sizeof(Termios2Struct))
+TCSETS2 = _ioc(_IOC_WRITE, ord("T"), 0x2B, ctypes.sizeof(Termios2Struct))
+
+
 class LinuxSerial(ExtendedPosixSerial):
     """Linux serial port implementation."""
 
diff --git a/serialx/platforms/serial_posix.py b/serialx/platforms/serial_posix.py
index 8eef54d..5a84b40 100644
--- a/serialx/platforms/serial_posix.py
+++ b/serialx/platforms/serial_posix.py
@@ -3,6 +3,7 @@
 from __future__ import annotations
 
 import asyncio
+import array
 import errno
 import fcntl
 import logging
@@ -320,8 +321,7 @@ class PosixSerial(BaseSerial):
         """Get current modem control bits."""
         assert self._fileno is not None
 
-        # A `bytearray` is critical here: `bytes` will not be mutated
-        buffer = bytearray((0x00000000).to_bytes(4, "little"))
+        buffer = array.array("i", [0x00000000])
 
         try:
             fcntl.ioctl(self._fileno, termios.TIOCMGET, buffer)
@@ -330,7 +330,7 @@ class PosixSerial(BaseSerial):
                 LOGGER.debug("Device is not a serial port, cannot get modem pins")
                 return ModemPins()
 
-        n = int.from_bytes(buffer, "little")
+        n = buffer[0]
         return ModemPins(
             **{
                 name: PinState.HIGH if n & bit else PinState.LOW
@@ -353,7 +353,9 @@ class PosixSerial(BaseSerial):
             if all_pins_set:
                 value = modem_pins_as_int(modem_pins)
                 LOGGER.debug("Setting all with TIOCMSET: 0x%08X", value)
-                fcntl.ioctl(self._fileno, termios.TIOCMSET, value.to_bytes(4, "little"))
+                fcntl.ioctl(
+                    self._fileno, termios.TIOCMSET, array.array("i", [value])
+                )
             else:
                 to_set = modem_pins_mask_of_value(modem_pins, PinState.HIGH)
                 to_clear = modem_pins_mask_of_value(modem_pins, PinState.LOW)
@@ -361,13 +363,13 @@ class PosixSerial(BaseSerial):
                 if to_set:
                     LOGGER.debug("Setting TIOCMBIS: 0x%08X", to_set)
                     fcntl.ioctl(
-                        self._fileno, termios.TIOCMBIS, to_set.to_bytes(4, "little")
+                        self._fileno, termios.TIOCMBIS, array.array("i", [to_set])
                     )
 
                 if to_clear:
                     LOGGER.debug("TIOCMBIC: 0x%08X", to_clear)
                     fcntl.ioctl(
-                        self._fileno, termios.TIOCMBIC, to_clear.to_bytes(4, "little")
+                        self._fileno, termios.TIOCMBIC, array.array("i", [to_clear])
                     )
         except OSError as exc:
             if exc.errno == errno.ENOTTY:
@@ -461,20 +463,20 @@ class PosixSerial(BaseSerial):
     def num_unread_bytes(self) -> int:
         """Return the number of bytes waiting to be read."""
         assert self._fileno is not None
-        buffer = bytearray((0x00000000).to_bytes(4, "little"))
+        buffer = array.array("i", [0x00000000])
 
         fcntl.ioctl(self._fileno, termios.FIONREAD, buffer)
 
-        return int.from_bytes(buffer, "little")
+        return buffer[0]
 
     def num_unwritten_bytes(self) -> int:
         """Return the number of bytes waiting to be written."""
         assert self._fileno is not None
-        buffer = bytearray((0x00000000).to_bytes(4, "little"))
+        buffer = array.array("i", [0x00000000])
 
         fcntl.ioctl(self._fileno, termios.TIOCOUTQ, buffer)
 
-        return int.from_bytes(buffer, "little")
+        return buffer[0]
 
     def _reset_read_buffer(self) -> None:
         """Reset the read buffer."""
diff --git a/serialx/platforms/serial_win32.py b/serialx/platforms/serial_win32.py
index 52fcae7..637aaad 100644
--- a/serialx/platforms/serial_win32.py
+++ b/serialx/platforms/serial_win32.py
@@ -557,7 +557,7 @@ class Win32SerialTransport(BaseSerialTransport):
         self._open_fut = cast(asyncio.Future[int], open_fut)
 
         try:
-            handle = await self._open_fut
+            handle = await asyncio.shield(self._open_fut)
         except asyncio.CancelledError:
             self._open_fut.add_done_callback(self._on_cancelled_open_done)
             raise
