uvt: ctx: add major/minor helpers
authorDavid Herrmann <dh.herrmann@gmail.com>
Tue, 5 Mar 2013 00:29:10 +0000 (01:29 +0100)
committerDavid Herrmann <dh.herrmann@gmail.com>
Tue, 5 Mar 2013 00:31:27 +0000 (01:31 +0100)
Two new functions to retrieve the current major number and dynamically
allocate minor numbers.
This can be used by clients that allocate more than one CDEV for VTs to
dynamically retrieve a new minor number.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
docs/sym/libuvt.sym
src/uvt.h
src/uvt_ctx.c
src/uvt_internal.h

index a747c43..c2bc069 100644 (file)
@@ -30,6 +30,9 @@ global:
        uvt_ctx_unref;
        uvt_ctx_get_fd;
        uvt_ctx_dispatch;
+       uvt_ctx_get_major;
+       uvt_ctx_new_minor;
+       uvt_ctx_free_minor;
 
        uvt_cdev_new;
        uvt_cdev_ref;
index e1b0efe..8c41aa6 100644 (file)
--- a/src/uvt.h
+++ b/src/uvt.h
@@ -261,6 +261,10 @@ void uvt_ctx_unref(struct uvt_ctx *ctx);
 int uvt_ctx_get_fd(struct uvt_ctx *ctx);
 void uvt_ctx_dispatch(struct uvt_ctx *ctx);
 
+unsigned int uvt_ctx_get_major(struct uvt_ctx *ctx);
+int uvt_ctx_new_minor(struct uvt_ctx *ctx, unsigned int *out);
+void uvt_ctx_free_minor(struct uvt_ctx *ctx, unsigned int minor);
+
 /* pty tty implementation */
 
 struct uvt_tty_null;
index 60185ec..ad1e534 100644 (file)
 #include <eloop.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <linux/major.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include "shl_array.h"
+#include "shl_flagset.h"
 #include "shl_llog.h"
 #include "shl_misc.h"
 #include "uvt.h"
@@ -60,6 +63,13 @@ int uvt_ctx_new(struct uvt_ctx **out, uvt_log_t log, void *log_data)
        ctx->llog = log;
        ctx->llog_data = log_data;
 
+       /* Default major/minor uses the TTY_MAJOR number with an offset of 2^15
+        * to avoid ID-clashes with any in-kernel TTY driver. As kernel drivers
+        * use static IDs only, a lower number would be fine, too, but lets be
+        * safe and just use high numbers. */
+       ctx->major = TTY_MAJOR;
+       ctx->minor_offset = 16384;
+
        llog_debug(ctx, "new ctx %p", ctx);
 
        ret = ev_eloop_new(&ctx->eloop, ctx->llog, ctx->llog_data);
@@ -72,9 +82,15 @@ int uvt_ctx_new(struct uvt_ctx **out, uvt_log_t log, void *log_data)
                goto err_eloop;
        }
 
+       ret = shl_flagset_new(&ctx->minors);
+       if (ret)
+               goto err_file;
+
        *out = ctx;
        return 0;
 
+err_file:
+       free(ctx->cuse_file);
 err_eloop:
        ev_eloop_unref(ctx->eloop);
 err_free:
@@ -99,6 +115,7 @@ void uvt_ctx_unref(struct uvt_ctx *ctx)
 
        llog_debug(ctx, "free ctx %p", ctx);
 
+       shl_flagset_free(ctx->minors);
        free(ctx->cuse_file);
        ev_eloop_unref(ctx->eloop);
        free(ctx);
@@ -121,3 +138,31 @@ void uvt_ctx_dispatch(struct uvt_ctx *ctx)
 
        ev_eloop_dispatch(ctx->eloop, 0);
 }
+
+SHL_EXPORT
+unsigned int uvt_ctx_get_major(struct uvt_ctx *ctx)
+{
+       return ctx->major;
+}
+
+SHL_EXPORT
+int uvt_ctx_new_minor(struct uvt_ctx *ctx, unsigned int *out)
+{
+       int ret;
+
+       ret = shl_flagset_alloc(ctx->minors, out);
+       if (ret)
+               return ret;
+
+       *out += ctx->minor_offset;
+       return 0;
+}
+
+SHL_EXPORT
+void uvt_ctx_free_minor(struct uvt_ctx *ctx, unsigned int minor)
+{
+       if (!ctx || minor < ctx->minor_offset)
+               return;
+
+       shl_flagset_unset(ctx->minors, minor - ctx->minor_offset);
+}
index 72d4edd..479cf2b 100644 (file)
@@ -34,6 +34,7 @@
 #include <eloop.h>
 #include <stdlib.h>
 #include <uvt.h>
+#include "shl_array.h"
 #include "shl_dlist.h"
 #include "shl_hook.h"
 #include "shl_llog.h"
@@ -53,6 +54,9 @@ struct uvt_ctx {
        struct ev_eloop *eloop;
 
        char *cuse_file;
+       unsigned int major;
+       unsigned int minor_offset;
+       struct shl_array *minors;
 };
 
 /* character devices */