[haiku-commits] haiku: hrev50114 - src/add-ons/kernel/drivers/ports/usb_serial src/system/libroot/posix headers/posix

  • From: pulkomandy@xxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sat, 27 Feb 2016 19:24:50 +0100 (CET)

hrev50114 adds 1 changeset to branch 'master'
old head: 44547a899c6d6b6e98efa90e6430588999bab8bf
new head: 93ea83e53dd4bf06c3d38c3b1cb6b29b5deec47d
overview: 
http://cgit.haiku-os.org/haiku/log/?qt=range&q=93ea83e53dd4+%5E44547a899c6d

----------------------------------------------------------------------------

93ea83e53dd4: Allow custom baud rates for FTDI serial ports
  
  - Termios: cf{get,set}{i,o}speed can handle arbitrary speed values.
  - The value is stored in the appropriate fields of the termios structure
    in this case. The old constants (stored in the flags) are preserved
    for BeOS binary compatibility.
  - Adjust the FTDI FT232* driver to accept custom rates, by replacing the
    hardcoded regster values with a function that will compute it
    according to FTDI documentation (confirmed giving the same values for
    the existing baudrates).

                             [ Adrien Destugues <pulkomandy@xxxxxxxxxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev50114
Commit:      93ea83e53dd4bf06c3d38c3b1cb6b29b5deec47d
URL:         http://cgit.haiku-os.org/haiku/commit/?id=93ea83e53dd4
Author:      Adrien Destugues <pulkomandy@xxxxxxxxxxxxx>
Date:        Sat Feb 27 18:08:53 2016 UTC

----------------------------------------------------------------------------

5 files changed, 54 insertions(+), 48 deletions(-)
headers/posix/termios.h                          |  4 +--
.../kernel/drivers/ports/usb_serial/FTDI.cpp     | 34 +++++++++----------
.../kernel/drivers/ports/usb_serial/FTDIRegs.h   | 25 ++++++--------
.../drivers/ports/usb_serial/SerialDevice.cpp    |  4 +--
src/system/libroot/posix/termios.c               | 35 +++++++++++++-------

----------------------------------------------------------------------------

diff --git a/headers/posix/termios.h b/headers/posix/termios.h
index f1c800f..141746e 100644
--- a/headers/posix/termios.h
+++ b/headers/posix/termios.h
@@ -21,8 +21,8 @@ struct termios {
        tcflag_t        c_cflag;        /* control modes */
        tcflag_t        c_lflag;        /* local modes */
        char            c_line;         /* line discipline */
-       speed_t         c_ispeed;       /* (unused) */
-       speed_t         c_ospeed;       /* (unused) */
+       speed_t         c_ispeed;       /* custom input baudrate */
+       speed_t         c_ospeed;       /* custom output baudrate */
        cc_t            c_cc[NCCS];     /* control characters */
 };
 
diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/FTDI.cpp 
b/src/add-ons/kernel/drivers/ports/usb_serial/FTDI.cpp
index 649975b..60f2a79 100644
--- a/src/add-ons/kernel/drivers/ports/usb_serial/FTDI.cpp
+++ b/src/add-ons/kernel/drivers/ports/usb_serial/FTDI.cpp
@@ -111,26 +111,24 @@ FTDIDevice::SetLineCoding(usb_cdc_line_coding *lineCoding)
                        break;
                }
        } else {
-               switch (lineCoding->speed) {
-                       case 300: rate = ftdi_8u232am_b300; break;
-                       case 600: rate = ftdi_8u232am_b600; break;
-                       case 1200: rate = ftdi_8u232am_b1200; break;
-                       case 2400: rate = ftdi_8u232am_b2400; break;
-                       case 4800: rate = ftdi_8u232am_b4800; break;
-                       case 9600: rate = ftdi_8u232am_b9600; break;
-                       case 19200: rate = ftdi_8u232am_b19200; break;
-                       case 38400: rate = ftdi_8u232am_b38400; break;
-                       case 57600: rate = ftdi_8u232am_b57600; break;
-                       case 115200: rate = ftdi_8u232am_b115200; break;
-                       case 230400: rate = ftdi_8u232am_b230400; break;
-                       case 460800: rate = ftdi_8u232am_b460800; break;
-                       case 921600: rate = ftdi_8u232am_b921600; break;
-                       default:
-                               rate = ftdi_sio_b19200;
+               /* Compute baudrate register value as documented in AN232B-05 
from FTDI.
+                Bits 13-0 are the integer divider, and bits 16-14 are the 
fractional
+                divider setting. 3Mbaud and 2Mbaud are special values, and at 
such
+                high speeds the use of the fractional divider is not possible. 
*/
+               if (lineCoding->speed == 3000000)
+                       rate = 0;
+               else if (lineCoding->speed == 2000000)
+                       rate = 1;
+               else {
+                       if (lineCoding->speed > 1500000) {
                                TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): 
Datarate: %d is "
                                        "not supported by this hardware. 
Defaulted to %d\n",
-                                       lineCoding->speed, rate);
-                               break;
+                                       lineCoding->speed, 19200);
+                               lineCoding->speed = 19200;
+                       }
+                       rate = 3000000 * 8 / lineCoding->speed;
+                       int frac = ftdi_8u232am_frac[rate & 0x7];
+                       rate = (rate >> 3) | frac;
                }
        }
 
diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/FTDIRegs.h 
b/src/add-ons/kernel/drivers/ports/usb_serial/FTDIRegs.h
index 2ae8401..dd2e552 100644
--- a/src/add-ons/kernel/drivers/ports/usb_serial/FTDIRegs.h
+++ b/src/add-ons/kernel/drivers/ports/usb_serial/FTDIRegs.h
@@ -101,20 +101,17 @@ enum {
        ftdi_sio_b115200 = 9
 };
 
-enum {
-       ftdi_8u232am_b300 = 0x2710,
-       ftdi_8u232am_b600 = 0x1388,
-       ftdi_8u232am_b1200 = 0x09c4,
-       ftdi_8u232am_b2400 = 0x04e2,
-       ftdi_8u232am_b4800 = 0x0271,
-       ftdi_8u232am_b9600 = 0x4138,
-       ftdi_8u232am_b19200 = 0x809c,
-       ftdi_8u232am_b38400 = 0xc04e,
-       ftdi_8u232am_b57600 = 0x0034,
-       ftdi_8u232am_b115200 = 0x001a,
-       ftdi_8u232am_b230400 = 0x000d,
-       ftdi_8u232am_b460800 = 0x4006,
-       ftdi_8u232am_b921600 = 0x8003
+
+/* Fractional divider values for FT232A/B devices */
+static const int ftdi_8u232am_frac[8] = {
+       0x0 << 14, /* .0   */
+       0x3 << 14, /* .125 */
+       0x2 << 14, /* .25  */
+       0x4 << 14, /* .375 */
+       0x1 << 14, /* .5   */
+       0x5 << 14, /* .625 */
+       0x6 << 14, /* .75  */
+       0x7 << 14 /* .875 */
 };
 
 /*
diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/SerialDevice.cpp 
b/src/add-ons/kernel/drivers/ports/usb_serial/SerialDevice.cpp
index 4af8c16..eca908f 100644
--- a/src/add-ons/kernel/drivers/ports/usb_serial/SerialDevice.cpp
+++ b/src/add-ons/kernel/drivers/ports/usb_serial/SerialDevice.cpp
@@ -161,8 +161,8 @@ SerialDevice::SetModes(struct termios *tios)
        uint8 baud = tios->c_cflag & CBAUD;
        int32 speed = baud_index_to_speed(baud);
        if (speed < 0) {
-               baud = B19200;
-               speed = 19200;
+               baud = CBAUD;
+               speed = tios->c_ospeed;
        }
 
        // update our master config in full
diff --git a/src/system/libroot/posix/termios.c 
b/src/system/libroot/posix/termios.c
index 9a6e57b..f9191da 100644
--- a/src/system/libroot/posix/termios.c
+++ b/src/system/libroot/posix/termios.c
@@ -105,6 +105,11 @@ tcsendbreak(int fd, int duration)
 speed_t
 cfgetispeed(const struct termios *termios)
 {
+       if (termios->c_cflag & CBAUD == CBAUD)
+       {
+               return termios->c_ispeed;
+       }
+
        return termios->c_cflag & CBAUD;
 }
 
@@ -112,14 +117,14 @@ cfgetispeed(const struct termios *termios)
 int
 cfsetispeed(struct termios *termios, speed_t speed)
 {
-       /*      Check for values that the system cannot handle:
-       greater values than B230400 which is
-       the maximum value defined in termios.h
-       Note that errors from hardware device are detected only
-       until the tcsetattr() function is called */
-       if (speed > B230400 || (speed & CBAUD) != speed) {
-               __set_errno(EINVAL);
-               return -1;
+       /*      Check for custom baudrates, which must be stored in the c_ispeed
+       field instead of inlined in the flags.
+       Note that errors from hardware device (unsupported baudrates, etc) are
+       detected only when the tcsetattr() function is called */
+       if (speed > B31250) {
+               termios->c_cflag |= CBAUD;
+               termios->c_ispeed = speed;
+               return 0;
        }
 
        termios->c_cflag &= ~CBAUD;
@@ -131,6 +136,11 @@ cfsetispeed(struct termios *termios, speed_t speed)
 speed_t
 cfgetospeed(const struct termios *termios)
 {
+       if (termios->c_cflag & CBAUD == CBAUD)
+       {
+               return termios->c_ospeed;
+       }
+
        return termios->c_cflag & CBAUD;
 }
 
@@ -138,10 +148,11 @@ cfgetospeed(const struct termios *termios)
 int
 cfsetospeed(struct termios *termios, speed_t speed)
 {
-       /* Check for unaccepted speed values (see above) */
-       if (speed > B230400 || (speed & CBAUD) != speed) {
-               __set_errno(EINVAL);
-               return -1;
+       /* Check for custom speed values (see above) */
+       if (speed > B31250) {
+               termios->c_cflag |= CBAUD;
+               termios->c_ospeed = speed;
+               return 0;
        }
 
        termios->c_cflag &= ~CBAUD;


Other related posts: