Package: python-serial
Version: 2.5-2.2
Severity: important
Tags: upstream patch

Dear Maintainer,

It is common for 3D printers to use a device which appears as
/dev/ttyACMn and which are intended to communicate at 250000 baud, a
nonstandard baudrate.  Unfortunately, python-serial as shipped will
refuse to open this device at the desired baudrate.

For whatever reason, the "classic" way of setting nonstandard baud
rates (ioctl TIOCGSERIAL+TIOCSSERIAL) is not implemented, but a new
way is (ioctl TCGETS2+TCSETS2).  Apparently this "new" way dates to 2006:
http://lwn.net/Articles/197106/

A patch in the upstream bug tracker
https://sourceforge.net/p/pyserial/patches/28/ allows me to
communicate with my device at the desired baudrate.  No problems
have been identified with the patch, though the main limitation
would be that it would not work with kernels that do not implement
TCSETS2.

While I am reporting this bug against the version of pyserial in
stable, I inspected the version from sid (2.6-1) and it has also not
yet been adapted to TCSETS2.  Additionally, the patch applies
clieanly to 2.6-1, but I have not tested that it works.

Thank you for your time in consideration of this patch.

Jeff Epler
[email protected]

-- System Information:
Debian Release: 7.1
  APT prefers stable
  APT policy: (990, 'stable'), (500, 'testing'), (1, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 3.2.0-4-rt-amd64 (SMP w/4 CPU cores; PREEMPT)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages python-serial depends on:
ii  python  2.7.3-4

python-serial recommends no packages.

Versions of packages python-serial suggests:
ii  python-wxgtk2.8  2.8.12.1-12

-- no debconf information
Index: pyserial/serial/serialposix.py
===================================================================
--- pyserial/serial/serialposix.py	(revision 455)
+++ pyserial/serial/serialposix.py	(working copy)
@@ -36,26 +36,25 @@
     def device(port):
         return '/dev/ttyS%d' % port
 
-    ASYNC_SPD_MASK = 0x1030
-    ASYNC_SPD_CUST = 0x0030
+    TCGETS2 = 0x802C542A
+    TCSETS2 = 0x402C542B
+    BOTHER = 0o010000
 
     def set_special_baudrate(port, baudrate):
+        # right size is 44 on x86_64, allow for some growth
         import array
-        buf = array.array('i', [0] * 32)
+        buf = array.array('i', [0] * 64)
 
         # get serial_struct
-        FCNTL.ioctl(port.fd, TERMIOS.TIOCGSERIAL, buf)
+        FCNTL.ioctl(port.fd, TCGETS2, buf)
+        # set custom speed
+        buf[2] &= ~TERMIOS.CBAUD
+        buf[2] |= BOTHER
+        buf[9] = buf[10] = baudrate
 
-        # set custom divisor
-        buf[6] = buf[7] / baudrate
-
-        # update flags
-        buf[4] &= ~ASYNC_SPD_MASK
-        buf[4] |= ASYNC_SPD_CUST
-
         # set serial_struct
         try:
-            res = FCNTL.ioctl(port.fd, TERMIOS.TIOCSSERIAL, buf)
+            res = FCNTL.ioctl(port.fd, TCSETS2, buf)
         except IOError:
             raise ValueError('Failed to set custom baud rate: %r' % baudrate)
 

Reply via email to