diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/uvt.h | 4 | ||||
-rw-r--r-- | src/uvt_ctx.c | 45 | ||||
-rw-r--r-- | src/uvt_internal.h | 4 |
3 files changed, 53 insertions, 0 deletions
@@ -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; diff --git a/src/uvt_ctx.c b/src/uvt_ctx.c index 60185ec..ad1e534 100644 --- a/src/uvt_ctx.c +++ b/src/uvt_ctx.c @@ -33,9 +33,12 @@ #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); +} diff --git a/src/uvt_internal.h b/src/uvt_internal.h index 72d4edd..479cf2b 100644 --- a/src/uvt_internal.h +++ b/src/uvt_internal.h @@ -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 */ |