2 * UVT - Userspace Virtual Terminals
4 * Copyright (c) 2011-2013 David Herrmann <dh.herrmann@gmail.com>
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files
8 * (the "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 * A UVT context is used to provide basic infrastructure for all other UVT
29 * objects. It allows easy integration of multiple UVT objects into a single
36 #include <linux/major.h>
40 #include "shl_array.h"
41 #include "shl_flagset.h"
45 #include "uvt_internal.h"
47 #define LLOG_SUBSYSTEM "uvt_ctx"
50 int uvt_ctx_new(struct uvt_ctx **out, uvt_log_t log, void *log_data)
56 return llog_dEINVAL(log, log_data);
58 ctx = malloc(sizeof(*ctx));
60 return llog_dENOMEM(log, log_data);
61 memset(ctx, 0, sizeof(*ctx));
64 ctx->llog_data = log_data;
66 /* Default major/minor uses the TTY_MAJOR number with an offset of 2^15
67 * to avoid ID-clashes with any in-kernel TTY driver. As kernel drivers
68 * use static IDs only, a lower number would be fine, too, but lets be
69 * safe and just use high numbers. */
70 ctx->major = TTY_MAJOR;
71 ctx->minor_offset = 16384;
73 llog_debug(ctx, "new ctx %p", ctx);
75 ret = ev_eloop_new(&ctx->eloop, ctx->llog, ctx->llog_data);
79 ctx->cuse_file = strdup("/dev/cuse");
80 if (!ctx->cuse_file) {
81 ret = llog_ENOMEM(ctx);
85 ret = shl_flagset_new(&ctx->minors);
95 ev_eloop_unref(ctx->eloop);
102 void uvt_ctx_ref(struct uvt_ctx *ctx)
104 if (!ctx || !ctx->ref)
111 void uvt_ctx_unref(struct uvt_ctx *ctx)
113 if (!ctx || !ctx->ref || --ctx->ref)
116 llog_debug(ctx, "free ctx %p", ctx);
118 shl_flagset_free(ctx->minors);
119 free(ctx->cuse_file);
120 ev_eloop_unref(ctx->eloop);
125 int uvt_ctx_get_fd(struct uvt_ctx *ctx)
130 return ev_eloop_get_fd(ctx->eloop);
134 void uvt_ctx_dispatch(struct uvt_ctx *ctx)
139 ev_eloop_dispatch(ctx->eloop, 0);
143 unsigned int uvt_ctx_get_major(struct uvt_ctx *ctx)
149 int uvt_ctx_new_minor(struct uvt_ctx *ctx, unsigned int *out)
153 ret = shl_flagset_alloc(ctx->minors, out);
157 *out += ctx->minor_offset;
162 void uvt_ctx_free_minor(struct uvt_ctx *ctx, unsigned int minor)
164 if (!ctx || minor < ctx->minor_offset)
167 shl_flagset_unset(ctx->minors, minor - ctx->minor_offset);