All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] slcan2d: add new slcan daemon
@ 2013-07-11  9:54 yegorslists
  2013-07-24 12:01 ` Yegor Yefremov
  0 siblings, 1 reply; 5+ messages in thread
From: yegorslists @ 2013-07-11  9:54 UTC (permalink / raw)
  To: linux-can; +Cc: Yegor Yefremov

From: Yegor Yefremov <yegorslists@googlemail.com>

Cleaned up version of Oliver Hartkopp's effort with addition of
UART speed configuration.

Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com>
---
 GNUmakefile.am |    1 +
 slcan2d.c      |  519 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 520 insertions(+), 0 deletions(-)
 create mode 100644 slcan2d.c

diff --git a/GNUmakefile.am b/GNUmakefile.am
index fc8f6e7..e4d7de3 100644
--- a/GNUmakefile.am
+++ b/GNUmakefile.am
@@ -59,6 +59,7 @@ bin_PROGRAMS = \
 	log2long \
 	slcan_attach \
 	slcand \
+	slcan2d \
 	slcanpty
 
 EXTRA_DIST = \
diff --git a/slcan2d.c b/slcan2d.c
new file mode 100644
index 0000000..62672e3
--- /dev/null
+++ b/slcan2d.c
@@ -0,0 +1,519 @@
+/*
+ * slcan2d.c - userspace daemon for serial line CAN interface driver SLCAN
+ *
+ * Copyright (c) 2009 Robert Haddon <robert.haddon@verari.com>
+ * Copyright (c) 2009 Verari Systems Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * This code is derived from an example daemon code from
+ *
+ * http://en.wikipedia.org/wiki/Daemon_(computer_software)#Sample_Program_in_C_on_Linux
+ * (accessed 2009-05-05)
+ *
+ * So it is additionally licensed under the GNU Free Documentation License:
+ *
+ * Permission is granted to copy, distribute and/or modify this document
+ * under the terms of the GNU Free Documentation License, Version 1.2
+ * or any later version published by the Free Software Foundation;
+ * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
+ * A copy of the license is included in the section entitled "GNU
+ * Free Documentation License".
+ *
+ * Send feedback to <linux-can@vger.kernel.org>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <errno.h>
+#include <pwd.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <termios.h>
+
+/* default slcan line discipline since Kernel 2.6.25 */
+#define LDISC_N_SLCAN 17
+
+/* Change this to whatever your daemon is called */
+#define DAEMON_NAME "slcan2d"
+
+/* Change this to the user under which to run */
+#define RUN_AS_USER "root"
+
+/* The length of ttypath buffer */
+#define TTYPATH_LENGTH	64
+
+/* The length of pidfile name buffer */
+#define PIDFILE_LENGTH	64
+
+#define EXIT_SUCCESS 0
+#define EXIT_FAILURE 1
+
+
+
+void print_usage(char *prg)
+{
+	fprintf(stderr, "\nUsage: %s [options] <tty> [canif-name]\n\n", prg);
+	fprintf(stderr, "Options: -o         (send open command 'O\\r')\n");
+	fprintf(stderr, "         -c         (send close command 'C\\r')\n");
+	fprintf(stderr, "         -f         (read status flags with 'F\\r' to reset error states)\n");
+	fprintf(stderr, "         -s <speed> (set CAN speed 0..8)\n");
+	fprintf(stderr, "         -S <speed> (set UART speed)\n");
+	fprintf(stderr, "         -b <btr>   (set bit time register value)\n");
+	fprintf(stderr, "         -F         (stay in foreground; no daemonize)\n");
+	fprintf(stderr, "         -h         (show this help page)\n");
+	fprintf(stderr, "\nExamples:\n");
+	fprintf(stderr, "slcan2d -o -c -f -s6 ttyslcan0\n");
+	fprintf(stderr, "slcan2d -o -c -f -s6 ttyslcan0 can0\n");
+	fprintf(stderr, "\n");
+	exit(EXIT_FAILURE);
+}
+
+
+static int slcan2d_running = 0;
+static int exit_code = 0;
+static char ttypath[TTYPATH_LENGTH];
+static char pidfile[PIDFILE_LENGTH];
+
+
+static void child_handler (int signum)
+{
+	switch (signum)
+	{
+	case SIGUSR1:
+		/* exit parent */
+		exit(EXIT_SUCCESS);
+		break;
+	case SIGALRM:
+	case SIGCHLD:
+		syslog (LOG_NOTICE, "received signal %i on %s", signum, ttypath);
+		exit_code = EXIT_FAILURE;
+		slcan2d_running = 0;
+		break;
+	case SIGINT:
+	case SIGTERM:
+		syslog (LOG_NOTICE, "received signal %i on %s", signum, ttypath);
+		exit_code = EXIT_SUCCESS;
+		slcan2d_running = 0;
+		break;
+	}
+}
+
+static int look_up_uart_speed(int s)
+{
+	switch (s) {
+	case 9600:
+		return B9600;
+	case 19200:
+		return B19200;
+	case 38400:
+		return B38400;
+	case 57600:
+		return B57600;
+	case 115200:
+		return B115200;
+	case 230400:
+		return B230400;
+	case 460800:
+		return B460800;
+	case 500000:
+		return B500000;
+	case 576000:
+		return B576000;
+	case 921600:
+		return B921600;
+	case 1000000:
+		return B1000000;
+	case 1152000:
+		return B1152000;
+	case 1500000:
+		return B1500000;
+	case 2000000:
+		return B2000000;
+#ifdef B2500000
+	case 2500000:
+		return B2500000;
+#endif
+#ifdef B3000000
+	case 3000000:
+		return B3000000;
+#endif
+#ifdef B3500000
+	case 3500000:
+		return B3500000;
+#endif
+#ifdef B3710000
+	case 3710000
+		return B3710000;
+#endif
+#ifdef B4000000
+	case 4000000:
+		return B4000000;
+#endif
+	default:
+		return B57600;
+	}
+}
+
+static pid_t daemonize (const char *lockfile, char *tty, char *name)
+{
+	pid_t pid, sid, parent;
+	int lfp = -1;
+	FILE * pFile;
+	FILE * dummyFile;
+	char const *pidprefix = "/var/run/";
+	char const *pidsuffix = ".pid";
+
+	snprintf(pidfile, PIDFILE_LENGTH, "%s%s-%s%s", pidprefix, DAEMON_NAME, tty, pidsuffix);
+
+	/* already a daemon */
+	if (getppid () == 1)
+		return 0;
+
+	/* Create the lock file as the current user */
+	if (lockfile && lockfile[0])
+	{
+		lfp = open (lockfile, O_RDWR | O_CREAT, 0640);
+		if (lfp < 0)
+		{
+			syslog (LOG_ERR, "unable to create lock file %s, code=%d (%s)",
+				lockfile, errno, strerror (errno));
+			exit (EXIT_FAILURE);
+		}
+	}
+
+	/* Drop user if there is one, and we were run as root */
+	if (getuid () == 0 || geteuid () == 0)
+	{
+		struct passwd *pw = getpwnam (RUN_AS_USER);
+		if (pw)
+		{
+			//syslog (LOG_NOTICE, "setting user to " RUN_AS_USER);
+			setuid (pw->pw_uid);
+		}
+	}
+
+	/* Trap signals that we expect to receive */
+	signal (SIGINT, child_handler);
+	signal (SIGTERM, child_handler);
+	signal (SIGCHLD, child_handler);
+	signal (SIGUSR1, child_handler);
+	signal (SIGALRM, child_handler);
+
+	/* Fork off the parent process */
+	pid = fork ();
+	if (pid < 0)
+	{
+		syslog (LOG_ERR, "unable to fork daemon, code=%d (%s)",
+			errno, strerror (errno));
+		exit (EXIT_FAILURE);
+	}
+	/* If we got a good PID, then we can exit the parent process. */
+	if (pid > 0)
+	{
+
+		/* Wait for confirmation from the child via SIGTERM or SIGCHLD, or
+		   for two seconds to elapse (SIGALRM).  pause() should not return. */
+		alarm (5);
+		pause ();
+		exit (EXIT_FAILURE);
+	}
+
+	/* At this point we are executing as the child process */
+	parent = getppid ();
+
+	/* Cancel certain signals */
+	signal (SIGCHLD, SIG_DFL);	/* A child process dies */
+	signal (SIGTSTP, SIG_IGN);	/* Various TTY signals */
+	signal (SIGTTOU, SIG_IGN);
+	signal (SIGTTIN, SIG_IGN);
+	signal (SIGHUP, SIG_IGN);	/* Ignore hangup signal */
+	signal (SIGINT, child_handler);
+	signal (SIGTERM, child_handler);
+
+	/* Change the file mode mask */
+	umask (0);
+
+	/* Create a new SID for the child process */
+	sid = setsid ();
+	if (sid < 0)
+	{
+		syslog (LOG_ERR, "unable to create a new session, code %d (%s)",
+			errno, strerror (errno));
+		exit (EXIT_FAILURE);
+	}
+
+	pFile = fopen (pidfile,"w");
+	if (NULL == pFile)
+	{
+		syslog (LOG_ERR, "unable to create pid file %s, code=%d (%s)",
+			pidfile, errno, strerror (errno));
+		exit (EXIT_FAILURE);
+	}
+	fprintf (pFile, "%d\n", sid);
+	fclose (pFile);
+
+	/* Change the current working directory.  This prevents the current
+	   directory from being locked; hence not being able to remove it. */
+	if ((chdir ("/")) < 0)
+	{
+		syslog (LOG_ERR, "unable to change directory to %s, code %d (%s)",
+			"/", errno, strerror (errno));
+		exit (EXIT_FAILURE);
+	}
+
+	/* Redirect standard files to /dev/null */
+	dummyFile = freopen ("/dev/null", "r", stdin);
+	dummyFile = freopen ("/dev/null", "w", stdout);
+	dummyFile = freopen ("/dev/null", "w", stderr);
+
+	/* Tell the parent process that we are A-okay */
+	//kill (parent, SIGUSR1);
+	return parent;
+}
+
+int main (int argc, char *argv[])
+{
+	char *tty = NULL;
+	char const *devprefix = "/dev/";
+	char *name = NULL;
+	char buf[IFNAMSIZ+1];
+	struct termios tios;
+	speed_t old_ispeed;
+	speed_t old_ospeed;
+
+	int opt;
+	int detach = 1;
+	int send_open = 0;
+	int send_close = 0;
+	int send_read_status_flags = 0;
+	char *speed = NULL;
+	char *uart_speed_str = NULL;
+	long int uart_speed = 0;
+	char *btr = NULL;
+	int run_as_daemon = 1;
+	pid_t parent_pid = 0;
+
+	ttypath[0] = '\0';
+
+	while ((opt = getopt(argc, argv, "ocfs:S:b:?hF")) != -1) {
+		switch (opt) {
+		case 'o':
+			send_open = 1;
+			break;
+		case 'c':
+			send_close = 1;
+			break;
+		case 'f':
+			send_read_status_flags = 1;
+			break;
+		case 's':
+			speed = optarg;
+			if (strlen(speed) > 1)
+				print_usage(argv[0]);
+			break;
+		case 'S':
+			uart_speed_str = optarg;
+			errno = 0;
+			uart_speed = strtol(uart_speed_str, NULL, 10);
+			if (errno)
+				print_usage(argv[0]);
+			break;
+		case 'b':
+			btr = optarg;
+			if (strlen(btr) > 6)
+				print_usage(argv[0]);
+			break;
+		case 'F':
+			run_as_daemon = 0;
+			break;
+		case 'h':
+		case '?':
+		default:
+			print_usage(argv[0]);
+			//exit(EXIT_SUCCESS);
+			break;
+		}
+	}
+
+	/* Initialize the logging interface */
+	openlog (DAEMON_NAME, LOG_PID, LOG_LOCAL5);
+
+	/* Parse serial device name and optional can interface name */
+	tty = argv[optind];
+	if(NULL == tty) {
+		print_usage(argv[0]);
+	}
+	name = argv[optind + 1];
+
+	/* Prepare the tty device name string */
+	char * pch;
+	pch = strstr (tty, devprefix);
+	if (pch == tty) {
+		print_usage(argv[0]);
+	}
+
+	snprintf (ttypath, TTYPATH_LENGTH, "%s%s", devprefix, tty);
+	syslog (LOG_INFO, "starting on TTY device %s", ttypath);
+
+	/* Daemonize */
+	if(run_as_daemon) {
+		parent_pid = daemonize ("/var/lock/" DAEMON_NAME, tty, name);
+	}
+	else {
+		/* Trap signals that we expect to receive */
+		signal (SIGINT, child_handler);
+		signal (SIGTERM, child_handler);
+	}
+
+	/* */
+	slcan2d_running = 1;
+
+	/* Now we are a daemon -- do the work for which we were paid */
+	int fd;
+	int ldisc = LDISC_N_SLCAN;
+
+	if ((fd = open (ttypath, O_RDWR | O_NONBLOCK | O_NOCTTY )) < 0) {
+	    syslog (LOG_NOTICE, "failed to open TTY device %s\n", ttypath);
+		perror(ttypath);
+		exit(EXIT_FAILURE);
+	}
+
+    /* Configure baud rate */
+    memset(&tios, 0, sizeof(struct termios));
+    if(tcgetattr(fd, &tios) < 0) {
+    	syslog (LOG_NOTICE, "failed to get attributes for TTY device %s: %s\n", ttypath, strerror(errno));
+		exit (EXIT_FAILURE);
+    }
+
+    /* Get old values for later restore */
+    old_ispeed = cfgetispeed(&tios);
+    old_ospeed = cfgetospeed(&tios);
+
+    /* Baud Rate */
+    cfsetispeed(&tios, look_up_uart_speed(uart_speed));
+    cfsetospeed(&tios, look_up_uart_speed(uart_speed));
+
+    /* apply changes */
+    if(tcsetattr(fd, TCSADRAIN, &tios) < 0) {
+    	syslog(LOG_NOTICE, "Cannot set attributes for device \"%s\": %s!\n", ttypath, strerror(errno));
+    }
+
+	if (speed) {
+		sprintf(buf, "C\rS%s\r", speed);
+		if(write(fd, buf, strlen(buf)) < 0) {
+			//syslog (LO, "failed to get attributes for TTY device %s: %s\n", ttypath, strerror(errno));
+
+		}
+	}
+
+	if (btr) {
+		sprintf(buf, "C\rs%s\r", btr);
+		write(fd, buf, strlen(buf));
+	}
+
+	if (send_read_status_flags) {
+		sprintf(buf, "F\r");
+		write(fd, buf, strlen(buf));
+	}
+
+	if (send_open) {
+		sprintf(buf, "O\r");
+		write(fd, buf, strlen(buf));
+	}
+
+	/* set slcan like discipline on given tty */
+	if (ioctl (fd, TIOCSETD, &ldisc) < 0) {
+		perror("ioctl TIOCSETD");
+		exit(1);
+	}
+	
+	/* retrieve the name of the created CAN netdevice */
+	if (ioctl (fd, SIOCGIFNAME, buf) < 0) {
+		perror("ioctl SIOCGIFNAME");
+		exit(1);
+	}
+
+	syslog (LOG_NOTICE, "attached TTY %s to netdevice %s\n", ttypath, buf);
+	
+	/* try to rename the created netdevice */
+	if (name) {
+		struct ifreq ifr;
+		int s = socket(PF_INET, SOCK_DGRAM, 0);
+		if (s < 0)
+			perror("socket for interface rename");
+		else {
+			strncpy (ifr.ifr_name, buf, IFNAMSIZ);
+			strncpy (ifr.ifr_newname, name, IFNAMSIZ);
+
+			if (ioctl(s, SIOCSIFNAME, &ifr) < 0) {
+				syslog (LOG_NOTICE, "netdevice %s rename to %s failed\n", buf, name);
+				perror("ioctl SIOCSIFNAME rename");
+                exit(1);
+			} else
+				syslog (LOG_NOTICE, "netdevice %s renamed to %s\n", buf, name);
+
+			close(s);
+		}	
+	}
+	if(parent_pid > 0) {
+		kill(parent_pid, SIGUSR1);
+	}
+
+	/* The Big Loop */
+	while (slcan2d_running) {
+		sleep(1); /* wait 1 second */
+	}
+
+	/* Reset line discipline */
+	syslog (LOG_INFO, "stopping on TTY device %s", ttypath);
+	ldisc = N_TTY;
+	if (ioctl (fd, TIOCSETD, &ldisc) < 0) {
+		perror("ioctl TIOCSETD");
+		exit(1);
+	}
+
+	if (send_close) {
+		sprintf(buf, "C\r");
+		write(fd, buf, strlen(buf));
+	}
+
+    /* Reset old rates */
+    cfsetispeed(&tios, old_ispeed);
+    cfsetospeed(&tios, old_ospeed);
+
+    /* apply changes */
+    if(tcsetattr(fd, TCSADRAIN, &tios) < 0) {
+    	syslog(LOG_NOTICE, "Cannot set attributes for device \"%s\": %s!\n", ttypath, strerror(errno));
+    }
+
+    /* Remove pidfile */
+    if(run_as_daemon) {
+    	unlink(pidfile);
+    }
+
+	/* Finish up */
+	syslog (LOG_NOTICE, "terminated on %s", ttypath);
+	closelog ();
+	return exit_code;
+}
-- 
1.7.7


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] slcan2d: add new slcan daemon
  2013-07-11  9:54 [PATCH] slcan2d: add new slcan daemon yegorslists
@ 2013-07-24 12:01 ` Yegor Yefremov
  2013-08-17 19:01   ` Yegor Yefremov
  0 siblings, 1 reply; 5+ messages in thread
From: Yegor Yefremov @ 2013-07-24 12:01 UTC (permalink / raw)
  To: linux-can; +Cc: Yegor Yefremov, Oliver Hartkopp, Marc Kleine-Budde

Hi Marc, Oliver,

On Thu, Jul 11, 2013 at 11:54 AM,  <yegorslists@googlemail.com> wrote:
> From: Yegor Yefremov <yegorslists@googlemail.com>
>
> Cleaned up version of Oliver Hartkopp's effort with addition of
> UART speed configuration.
>
> Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com>

any comments/suggestions?

Yegor

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] slcan2d: add new slcan daemon
  2013-07-24 12:01 ` Yegor Yefremov
@ 2013-08-17 19:01   ` Yegor Yefremov
  2013-08-21 17:46     ` Oliver Hartkopp
  0 siblings, 1 reply; 5+ messages in thread
From: Yegor Yefremov @ 2013-08-17 19:01 UTC (permalink / raw)
  To: linux-can; +Cc: Yegor Yefremov, Oliver Hartkopp, Marc Kleine-Budde

On Wed, Jul 24, 2013 at 2:01 PM, Yegor Yefremov
<yegorslists@googlemail.com> wrote:
> Hi Marc, Oliver,
>
> On Thu, Jul 11, 2013 at 11:54 AM,  <yegorslists@googlemail.com> wrote:
>> From: Yegor Yefremov <yegorslists@googlemail.com>
>>
>> Cleaned up version of Oliver Hartkopp's effort with addition of
>> UART speed configuration.
>>
>> Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com>
>
> any comments/suggestions?

ping

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] slcan2d: add new slcan daemon
  2013-08-17 19:01   ` Yegor Yefremov
@ 2013-08-21 17:46     ` Oliver Hartkopp
  2013-08-22  7:12       ` Yegor Yefremov
  0 siblings, 1 reply; 5+ messages in thread
From: Oliver Hartkopp @ 2013-08-21 17:46 UTC (permalink / raw)
  To: Yegor Yefremov; +Cc: linux-can, Marc Kleine-Budde

On 17.08.2013 21:01, Yegor Yefremov wrote:
> On Wed, Jul 24, 2013 at 2:01 PM, Yegor Yefremov
> <yegorslists@googlemail.com> wrote:
>> Hi Marc, Oliver,
>>
>> On Thu, Jul 11, 2013 at 11:54 AM,  <yegorslists@googlemail.com> wrote:
>>> From: Yegor Yefremov <yegorslists@googlemail.com>
>>>
>>> Cleaned up version of Oliver Hartkopp's effort with addition of
>>> UART speed configuration.
>>>
>>> Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com>
>>
>> any comments/suggestions?
> 
> ping
> 

Hi Yegor,

sorry for my delayed response.

I just got through your slcan2d by diffing it with the existing slcand.

It's a cool cleanup and it adds all relevant command line options we know from
slcan_attach.c & UART settings - i think that was the idea, right?

As i can see there's no change of the functionality when the 'optional
options' are not given on the command line.

So why don't you just post a patch which makes the slcand your 'slcan2d' code?

IMHO having both the slcand and the slcan2d in the same repository does not
make sense if they behave identical when having the same (empty) options.

Or did I miss anything that slcand <tty> behaves different to slcan2d <tty> ??

Thanks & BR,
Oliver


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] slcan2d: add new slcan daemon
  2013-08-21 17:46     ` Oliver Hartkopp
@ 2013-08-22  7:12       ` Yegor Yefremov
  0 siblings, 0 replies; 5+ messages in thread
From: Yegor Yefremov @ 2013-08-22  7:12 UTC (permalink / raw)
  To: Oliver Hartkopp; +Cc: linux-can, Marc Kleine-Budde

On Wed, Aug 21, 2013 at 7:46 PM, Oliver Hartkopp <socketcan@hartkopp.net> wrote:
> On 17.08.2013 21:01, Yegor Yefremov wrote:
>> On Wed, Jul 24, 2013 at 2:01 PM, Yegor Yefremov
>> <yegorslists@googlemail.com> wrote:
>>> Hi Marc, Oliver,
>>>
>>> On Thu, Jul 11, 2013 at 11:54 AM,  <yegorslists@googlemail.com> wrote:
>>>> From: Yegor Yefremov <yegorslists@googlemail.com>
>>>>
>>>> Cleaned up version of Oliver Hartkopp's effort with addition of
>>>> UART speed configuration.
>>>>
>>>> Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com>
>>>
>>> any comments/suggestions?
>>
>> ping
>>
>
> Hi Yegor,
>
> sorry for my delayed response.
>
> I just got through your slcan2d by diffing it with the existing slcand.
>
> It's a cool cleanup and it adds all relevant command line options we know from
> slcan_attach.c & UART settings - i think that was the idea, right?

Yes. slcan_attach.c is almost obsolete now.

> As i can see there's no change of the functionality when the 'optional
> options' are not given on the command line.
>
> So why don't you just post a patch which makes the slcand your 'slcan2d' code?

You're right. I've reposted the patch as slcand with detailed
description, of what has really changed.

> IMHO having both the slcand and the slcan2d in the same repository does not
> make sense if they behave identical when having the same (empty) options.
>
> Or did I miss anything that slcand <tty> behaves different to slcan2d <tty> ??

ACK.

Yegor

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2013-08-22  7:12 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-07-11  9:54 [PATCH] slcan2d: add new slcan daemon yegorslists
2013-07-24 12:01 ` Yegor Yefremov
2013-08-17 19:01   ` Yegor Yefremov
2013-08-21 17:46     ` Oliver Hartkopp
2013-08-22  7:12       ` Yegor Yefremov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.