Re: ldattach: struct termios

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Mar 27, 2008 at 11:37:38PM +0100, Tilman Schmidt wrote:
> On Thu, 27 Mar 2008 14:58:50, Karel Zak wrote:
> >  I don't think that we have to care about difference between termios
> >  and termios2.  It's glibc job (and glibc supports the new method
> >  when available).
> 
> Be that as it may. What glibc does not support, however, is the actual
> benefit of the new method, namely setting arbitrary bit rates. The glibc
> functions only accept speed_t values (ie. the limited set Bnnn constants
> defined in asm/termbits.h) for specifying the input and output speeds.

 Yes and no... ;-) Few notes about speed:

 1/ you needn't to translate the speed (number) to Bxxx constant. This
    translation is supported by cfsetspeed()  -- unfortunately there
    isn't any man page about it. You have to read glibc source code...

 2/ the range of supported speeds is checked by cfset{i,o}speed(), so
    you cannot use it for arbitrary bit rates.

 3/ fortunately, it seems that tcsetattr() (that translate from glibc
    to kernel termios) doesn't check the speed setting. So you can
    bypass cfset{i,o}speed() and set it manually.


 ... so, see the patch bellow.

> That is what I did initially. It earned me a request from Mike not to
> "start off with a hobbled program".

 Sometime, the perfect is the enemy of the good :-)

> >  Is there any way how to test ldattach(8)? Do you have any simple
> >  test (I don't have GIGASET_M101;-) ?
> 
> You don't need one. The LD will happily load without a device attached
> and only complain afterwards if nothing responds on the line. So if you
> have a kernel built with CONFIG_GIGASET_M101=m (like most current
> distribution kernels I know of) or =y you can test with the GIGASET_M101
> LD and watch for the syslog message:
> 
>  kernel: ser_gigaset ser_gigaset.0: Could not initialize the device.

 Cool. See (non-standard speed):

# lsmod | grep gigaset

# /ldattach  -s 999999 M101 /dev/ttyS0

# lsmod | grep gigaset
ser_gigaset            17993  2
gigaset                57809  1 ser_gigaset
crc_ccitt              10432  1 gigaset
isdn                  132513  1 gigaset

# dmesg
...
gigaset: Driver for Gigaset 307x
ser_gigaset: Tilman Schmidt
ser_gigaset: Serial Driver for Gigaset 307x using Siemens M101
ser_gigaset ser_gigaset.0: Could not initialize the device.


    Karel


>From d14b5161e7a84f95a6873dc6537d584de9e5a8b6 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@xxxxxxxxxx>
Date: Fri, 28 Mar 2008 02:16:37 +0100
Subject: [PATCH] ldattach: use glibc termios

Signed-off-by: Karel Zak <kzak@xxxxxxxxxx>
---
 sys-utils/ldattach.c |  146 ++++++++++++-------------------------------------
 1 files changed, 36 insertions(+), 110 deletions(-)

diff --git a/sys-utils/ldattach.c b/sys-utils/ldattach.c
index a696e88..801dd1c 100644
--- a/sys-utils/ldattach.c
+++ b/sys-utils/ldattach.c
@@ -21,7 +21,7 @@
 #include <fcntl.h>
 #include <sys/ioctl.h>
 #include <errno.h>
-#include <asm/termbits.h>
+#include <termios.h>
 #include <unistd.h>
 #include <err.h>
 
@@ -31,15 +31,16 @@
 	do { if (debug) fprintf(stderr , "%s:" format "\n" , progname , ## arg); } while (0)
 
 #ifndef N_GIGASET_M101
-#define N_GIGASET_M101 16
+# define N_GIGASET_M101 16
 #endif
 
-#ifndef PACKAGE_STRING
-#define PACKAGE_STRING "me"
+#ifndef ARRAY_SIZE
+# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
 #endif
 
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+/* attach a line discipline ioctl */
+#ifndef TIOCSETD
+# define TIOCSETD   0x5423
 #endif
 
 static const char *progname;
@@ -78,105 +79,6 @@ static int lookup_ld(const char *s)
     return -1;
 }
 
-/* replacement for tcsetattr(3) and friends supporting arbitrary speed values */
-
-/* some archs don't have separate struct termios2 */
-#ifndef TCGETS2
-#define termios2 termios
-#define TCGETS2 TCGETS
-#define TCSETS2 TCSETS
-#define TCSETSW2 TCSETSW
-#define TCSETSF2 TCSETSF
-#endif
-
-static int tcgetattr2(int fd, struct termios2 *pts)
-{
-    return ioctl(fd, TCGETS2, pts);
-}
-
-static int tcsetattr2(int fd, int option, const struct termios2 *pts)
-{
-    int request;
-
-    switch (option) {
-    case TCSANOW:
-	request = TCSETS2;
-	break;
-    case TCSADRAIN:
-	request = TCSETSW2;
-	break;
-    case TCSAFLUSH:
-	request = TCSETSF2;
-	break;
-    default:
-	errno = -EINVAL;
-	return -1;
-    }
-    return ioctl(fd, request, pts);
-}
-
-static void cfmakeraw2(struct termios2 *pts)
-{
-    pts->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
-    pts->c_oflag &= ~OPOST;
-    pts->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
-    pts->c_cflag &= ~(CSIZE|PARENB);
-    pts->c_cflag |= CS8;
-}
-
-/* table of standard line speeds */
-static const struct speed_entry { int s; speed_t v; }
-speed_table[] = {
-	{ 50,     B50 },
-	{ 75,     B75 },
-	{ 110,    B110 },
-	{ 134,    B134 },
-	{ 150,    B150 },
-	{ 200,    B200 },
-	{ 300,    B300 },
-	{ 600,    B600 },
-	{ 1200,   B1200 },
-	{ 1800,   B1800 },
-	{ 2400,   B2400 },
-	{ 4800,   B4800 },
-	{ 9600,   B9600 },
-	{ 19200,  B19200 },
-	{ 38400,  B38400 }
-#ifdef B57600
-	,{ 57600,  B57600 }
-#endif
-#ifdef B115200
-	,{ 115200, B115200 }
-#endif
-#ifdef B230400
-	,{ 230400, B230400 }
-#endif
-};
-
-static int cfsetspeed2(struct termios2 *pts, int speed)
-{
-    size_t i;
-
-    /* try POSIX method first */
-    for (i = 0; i < ARRAY_SIZE(speed_table); i++)
-	if (speed_table[i].s == speed) {
-	    pts->c_cflag &= ~CBAUD;
-	    pts->c_cflag |= speed_table[i].v;
-	    return 0;
-	}
-
-#ifdef BOTHER
-    /* new method available */
-    pts->c_ospeed = pts->c_ispeed = speed;
-    pts->c_cflag &= ~CBAUD;
-    pts->c_cflag |= BOTHER;
-    return 0;
-#else
-    /* new method not available */
-    return -1;
-#endif
-}
-
 static void __attribute__((__noreturn__)) usage(int exitcode)
 {
     size_t i;
@@ -190,10 +92,34 @@ static void __attribute__((__noreturn__)) usage(int exitcode)
     exit(exitcode);
 }
 
+static int my_cfsetspeed(struct termios *ts, int speed)
+{
+	/* Standard speeds
+	 * -- cfsetspeed() is able to translate number to Bxxx constants
+	 */
+	if (cfsetspeed(ts, speed) == 0)
+		return 0;
+
+	/* Nonstandard speeds
+	 * -- we have to bypass glibc and set the speed manually (because
+	 *    glibc checks for speed and supports Bxxx bit rates only)...
+	 */
+#ifdef _HAVE_STRUCT_TERMIOS_C_ISPEED
+# define BOTHER 0010000               /* non standard rate */
+	dbg("using non-standard speeds");
+	ts->c_ospeed = ts->c_ispeed = speed;
+	ts->c_cflag &= ~CBAUD;
+	ts->c_cflag |= BOTHER;
+	return 0;
+#else
+	return -1;
+#endif
+}
+
 int main(int argc, char **argv)
 {
     int tty_fd;
-    struct termios2 ts;
+    struct termios ts;
     int speed = 0, bits = '-', parity = '-', stop = '-';
     int ldisc;
     int optc;
@@ -278,10 +204,10 @@ int main(int argc, char **argv)
     dbg("opened %s", dev);
 
     /* set line speed and format */
-    if (tcgetattr2(tty_fd, &ts) < 0)
+    if (tcgetattr(tty_fd, &ts) < 0)
 	err(EXIT_FAILURE, _("cannot get terminal attributes for %s"), dev);
-    cfmakeraw2(&ts);
-    if (speed && cfsetspeed2(&ts, speed) < 0)
+    cfmakeraw(&ts);
+    if (speed && my_cfsetspeed(&ts, speed) < 0)
 	errx(EXIT_FAILURE, _("speed %d unsupported"), speed);
     switch (stop) {
     case '1':
@@ -312,7 +238,7 @@ int main(int argc, char **argv)
 	break;
     }
     ts.c_cflag |= CREAD;	/* just to be on the safe side */
-    if (tcsetattr2(tty_fd, TCSAFLUSH, &ts) < 0)
+    if (tcsetattr(tty_fd, TCSAFLUSH, &ts) < 0)
 	err(EXIT_FAILURE, _("cannot set terminal attributes for %s"), dev);
 
     dbg("set to raw %d %c%c%c: cflag=0x%x",
-- 
1.5.3.8

--
To unsubscribe from this list: send the line "unsubscribe util-linux-ng" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux