console-server: Specify devices by kernel names
This change adds a little lookup code to find the device path in sysfs,
so changing the --device syntax to give just the raw kname (ie, without
the /dev/ prefix).
We'll use this later to interact with the extended properties of a
VUART.
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
diff --git a/console-server.c b/console-server.c
index de6a34a..005af60 100644
--- a/console-server.c
+++ b/console-server.c
@@ -4,6 +4,8 @@
* Copyright © 2016 IBM Corporation <jk@ozlabs.org>
*/
+#define _GNU_SOURCE
+
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
@@ -14,6 +16,7 @@
#include <termios.h>
#include <string.h>
#include <getopt.h>
+#include <limits.h>
#include <sys/types.h>
#include <sys/poll.h>
@@ -23,7 +26,9 @@
static const char esc_str[] = { '\r', '~', '.' };
struct console_ctx {
- const char *tty_dev;
+ const char *tty_kname;
+ char *tty_sysfs_devnode;
+ char *tty_dev;
int tty_fd;
int console_fd_in;
int console_fd_out;
@@ -38,16 +43,65 @@
"usage: %s [options]\n"
"\n"
"Options:\n"
-" --device <TTY> Use serial device TTY\n"
+" --device <TTY> Use serial device TTY (eg, ttyS0)\n"
"",
progname);
}
+/* populates tty_dev and tty_sysfs_devnode, using the tty kernel name */
+static int tty_find_device(struct console_ctx *ctx)
+{
+ char *tty_class_device_link;
+ char *tty_device_tty_dir;
+ char *tty_device_reldir;
+ int rc;
+
+ rc = -1;
+ tty_class_device_link = NULL;
+ tty_device_tty_dir = NULL;
+ tty_device_reldir = NULL;
+
+ rc = asprintf(&tty_class_device_link,
+ "/sys/class/tty/%s", ctx->tty_kname);
+ if (rc < 0)
+ return -1;
+
+ tty_device_tty_dir = realpath(tty_class_device_link, NULL);
+ if (rc < 0) {
+ warn("Can't query sysfs for device %s", ctx->tty_kname);
+ goto out_free;
+ }
+
+ rc = asprintf(&tty_device_reldir, "%s/../../", tty_device_tty_dir);
+ if (rc < 0)
+ goto out_free;
+
+ ctx->tty_sysfs_devnode = realpath(tty_device_reldir, NULL);
+ if (!ctx->tty_sysfs_devnode)
+ warn("Can't find parent device for %s", ctx->tty_kname);
+
+
+ /* todo: lookup from major/minor info in sysfs, in case udev has
+ * renamed us */
+ rc = asprintf(&ctx->tty_dev, "/dev/%s", ctx->tty_kname);
+ if (rc < 0)
+ goto out_free;
+
+ rc = 0;
+
+out_free:
+ free(tty_class_device_link);
+ free(tty_device_tty_dir);
+ free(tty_device_reldir);
+ return rc;
+}
+
/**
* Open and initialise the serial device
*/
static int tty_init_io(struct console_ctx *ctx)
{
+
ctx->tty_fd = open(ctx->tty_dev, O_RDWR);
if (ctx->tty_fd <= 0) {
warn("Can't open tty %s", ctx->tty_dev);
@@ -212,7 +266,7 @@
switch (c) {
case 'd':
- ctx->tty_dev = optarg;
+ ctx->tty_kname = optarg;
break;
case 'h':
@@ -222,12 +276,18 @@
}
}
- if (!ctx->tty_dev) {
+ if (!ctx->tty_kname) {
fprintf(stderr,
"Error: No TTY device specified (use --device)\n");
return EXIT_FAILURE;
}
+ rc = tty_find_device(ctx);
+ if (rc)
+ return EXIT_FAILURE;
+
+ return EXIT_SUCCESS;
+
rc = tty_init_io(ctx);
if (rc)
return EXIT_FAILURE;
@@ -240,6 +300,8 @@
console_restore_termios(ctx);
+ free(ctx->tty_sysfs_devnode);
+ free(ctx->tty_dev);
free(ctx);
return rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE;