Hi all,
        I've made some improvements to the slcand utility in SocketCAN.
The Lawicel CANUSB devices require some initialisation before starting
up.  I find myself often having to open minicom and manually enter the
appropriate codes to set up the CAN baud rate and open the CAN channel,
which is inconvenient to say the least.

        This adds in the ability to send arbitrary codes at startup and
shutdown of slcand.  This is specified on the command line:

        slcand <ttydevice> [<init strings> [-- <shutdown strings>]]

        e.g.    slcand ttyUSB1 S8 O -- C
                sets the CAN baud rate to 1Mbps, then opens the channel
                on startup, closes the channel on shutdown.

        The strings are terminated with \r automatically.  This allows
udev (for example) to create the slcX device.

        I've also dealt with a warning from the C library regarding an
ignored return value from freopen().  The patch is against r1164.

Regards,
-- 
Stuart Longland (aka Redhatter, VK4MSL)      .'''.
Gentoo Linux/MIPS Cobalt and Docs Developer  '.'` :
. . . . . . . . . . . . . . . . . . . . . .   .'.'
http://dev.gentoo.org/~redhatter             :.'

I haven't lost my mind...
  ...it's backed up on a tape somewhere.
Index: slcand.c
===================================================================
--- slcand.c    (revision 1164)
+++ slcand.c    (working copy)
@@ -52,6 +52,7 @@
 #include <pwd.h>
 #include <signal.h>
 #include <sys/ioctl.h>
+#include <termios.h>
 
 /* default slcan line discipline since Kernel 2.6.25 */
 #define LDISC_N_SLCAN 17
@@ -67,9 +68,10 @@
 
 void print_usage(char *prg)
 {
-       fprintf(stderr, "\nUsage: %s tty\n\n", prg);
+       fprintf(stderr, "\nUsage: %s tty [init opts... [-- close opts]]\n\n",
+               prg);
        fprintf(stderr, "Example:\n");
-       fprintf(stderr, "%s ttyUSB1\n", prg);
+       fprintf(stderr, "%s ttyUSB1 S8 O -- C\n", prg);
        fprintf(stderr, "%s ttyS0\n", prg);
        fprintf(stderr, "\n");
        exit(EXIT_FAILURE);
@@ -197,9 +199,12 @@
        }
 
        /* Redirect standard files to /dev/null */
-       freopen ("/dev/null", "r", stdin);
-       freopen ("/dev/null", "w", stdout);
-       freopen ("/dev/null", "w", stderr);
+       if ( freopen ("/dev/null", "r", stdin) == NULL )
+               syslog (LOG_NOTICE, "failed to redirect stdin");
+       if ( freopen ("/dev/null", "w", stdout) == NULL )
+               syslog (LOG_NOTICE, "failed to redirect stdout");
+       if ( freopen ("/dev/null", "w", stderr) == NULL )
+               syslog (LOG_NOTICE, "failed to redirect stderr");
 
        /* Tell the parent process that we are A-okay */
        kill (parent, SIGUSR1);
@@ -215,7 +220,7 @@
        openlog (DAEMON_NAME, LOG_PID, LOG_LOCAL5);
 
        /* See how we're called */
-       if (argc != 2)
+       if (argc < 2)
                print_usage(argv[0]);
        tty = argv[1];
 
@@ -225,7 +230,7 @@
        if (pch == tty) {
                print_usage(argv[0]);
        }
-       ttypath = malloc((strlen(devprefix) + strlen(tty)) * sizeof(char));
+       ttypath = malloc((strlen(devprefix) + strlen(tty) + 1) * sizeof(char));
        sprintf (ttypath, "%s%s", devprefix, tty);
        syslog (LOG_INFO, "starting on TTY device %s", ttypath);
 
@@ -233,14 +238,56 @@
        daemonize ("/var/lock/" DAEMON_NAME, tty);
 
        /* Now we are a daemon -- do the work for which we were paid */
+       int arg;
        int fd;
        int ldisc = LDISC_N_SLCAN;
+       struct termios serialopt;
 
-       if ((fd = open (ttypath, O_WRONLY | O_NOCTTY )) < 0) {
+       if ((fd = open (ttypath,  O_WRONLY | O_NOCTTY )) < 0) {
                perror(ttypath);
                exit(1);
        }
 
+       /* Initialise serialopt */
+       if ( tcgetattr( fd, &serialopt ) ) {
+               perror("Failed to get serial line options");
+               return(1);
+       }
+
+       /* Set the serial speed */
+       if ( cfsetospeed( &serialopt, B115200 ) ) {
+               perror("Failed to set output speed in serialopt");
+               return(1);
+       }
+
+       /* Store serialopt */
+       if ( tcsetattr( fd, TCSANOW, &serialopt ) ) {
+               perror("Failed to store serial line options");
+               return(1);
+       }
+       
+       /* Send initialisation arguments if any */
+       if ( argc > 2 ) {
+               syslog (LOG_INFO, "sending initialisation");
+               arg = 2;
+               while( ( arg < argc ) && 
+                               ( strstr( argv[arg], "--" ) == NULL ) ) {
+                       syslog (LOG_INFO, "write \"%s\"", argv[arg]);
+                       if ( write( fd, argv[arg], strlen(argv[arg]) ) <
+                                       strlen(argv[arg]) ) {
+                               syslog (LOG_ERR, "write \"%s\" failed",
+                                               argv[arg]);
+                               exit(1);
+                       }
+                       if ( write( fd, "\r", 1 ) < 1 ) {
+                               syslog (LOG_ERR, "write \"%s\" newline failed",
+                                               argv[arg]);
+                               exit(1);
+                       }
+                       arg++;
+               }
+       }
+
        if (ioctl (fd, TIOCSETD, &ldisc) < 0) {
                perror("ioctl");
                exit(1);
@@ -251,6 +298,23 @@
                sleep(60); /* wait 60 seconds */
        }
 
+       /* Send closing arguments if any (we should be on the "--" part) */
+       arg++;
+       if ( argc < arg )
+               syslog (LOG_INFO, "sending shutdown");
+       while ( arg < argc ) {
+               syslog (LOG_INFO, "write \"%s\"", argv[arg]);
+               if ( write( fd, argv[arg], strlen(argv[arg]) ) <
+                               strlen(argv[arg]) ) {
+                       syslog (LOG_ERR, "write \"%s\" failed",
+                                       argv[arg]);
+               }
+               if ( write( fd, "\r", 1 ) < 1 ) {
+                       syslog (LOG_ERR, "write \"%s\" newline failed",
+                                       argv[arg]);
+               }
+       }
+
        /* Finish up */
        syslog (LOG_NOTICE, "terminated on %s", ttypath);
        closelog ();
_______________________________________________
Socketcan-users mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/socketcan-users

Reply via email to