summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/uvt.h101
-rw-r--r--src/uvt_client.c257
2 files changed, 272 insertions, 86 deletions
diff --git a/src/uvt.h b/src/uvt.h
index b9f49f6..a69dd6f 100644
--- a/src/uvt.h
+++ b/src/uvt.h
@@ -70,28 +70,6 @@ struct uvt_tty_ops {
int (*read) (void *data, uint8_t *mem, size_t len);
int (*write) (void *data, const uint8_t *mem, size_t len);
unsigned int (*poll) (void *data);
-
-/*
- int (*ioctl_TIOCPKT) (void *data, ...);
- int (*ioctl_TCFLSH) (void *data, long arg);
- int (*ioctl_TCXONC) (void *data, ...);
- int (*ioctl_TCGETS) (void *data, struct termios *arg);
- int (*ioctl_TCSETS) (void *data, const struct termios *arg);
- int (*ioctl_TCSETSF) (void *data, const struct termios *arg);
- int (*ioctl_TCSETSW) (void *data, const struct termios *arg);
- int (*ioctl_TCGETA) (void *data, ...);
- int (*ioctl_TCSETA) (void *data, ...);
- int (*ioctl_TCSETAF) (void *data, ...);
- int (*ioctl_TCSETAW) (void *data, ...);
- int (*ioctl_TIOCGLCKTRMIOS) (void *data, ...);
- int (*ioctl_TIOCSLCKTRMIOS) (void *data, ...);
- int (*ioctl_TCGETX) (void *data, ...);
- int (*ioctl_TCSETX) (void *data, ...);
- int (*ioctl_TCSETXW) (void *data, ...);
- int (*ioctl_TCSETXF) (void *data, ...);
- int (*ioctl_TIOCGSOFTCAR) (void *data, ...);
- int (*ioctl_TIOCSSOFTCAR) (void *data, ...);
-*/
};
/* virtual terminals */
@@ -121,7 +99,55 @@ struct uvt_vt_ops {
int (*write) (void *data, const uint8_t *mem, size_t len);
unsigned int (*poll) (void *data);
+ /* TTY ioctls */
+ int (*ioctl_TCFLSH) (void *data, unsigned long arg);
+
+ /* VT ioctls */
+ int (*ioctl_VT_ACTIVATE) (void *data, unsigned long arg);
+ int (*ioctl_VT_WAITACTIVE) (void *data, unsigned long arg);
+ int (*ioctl_VT_GETSTATE) (void *data, struct vt_stat *arg);
+ int (*ioctl_VT_OPENQRY) (void *data, unsigned int *arg);
+ int (*ioctl_VT_GETMODE) (void *data, struct vt_mode *arg);
+ int (*ioctl_VT_SETMODE) (void *data, const struct vt_mode *arg);
+ int (*ioctl_VT_RELDISP) (void *data, unsigned long arg);
+ int (*ioctl_KDGETMODE) (void *data, unsigned int *arg);
+ int (*ioctl_KDSETMODE) (void *data, unsigned int arg);
+ int (*ioctl_KDGKBMODE) (void *data, unsigned int *arg);
+ int (*ioctl_KDSKBMODE) (void *data, unsigned int arg);
+
/*
+ Complete list of all ioctls that the kernel supports. The internal handler
+ returns -EOPNOTSUPP for all of them as they haven't been implemented, yet.
+ We need to check if they are actually required or whether it's not worth the
+ effort.
+ Please implement them only if you know a client that requires them. Also
+ consider implementing them as a no-op if the client doesn't depend on the
+ call to actually do something. We want to keep the actual callbacks at a
+ minimum.
+
+ TTY ioctls
+
+ int (*ioctl_TIOCPKT) (void *data, ...);
+ int (*ioctl_TCXONC) (void *data, ...);
+ int (*ioctl_TCGETS) (void *data, struct termios *arg);
+ int (*ioctl_TCSETS) (void *data, const struct termios *arg);
+ int (*ioctl_TCSETSF) (void *data, const struct termios *arg);
+ int (*ioctl_TCSETSW) (void *data, const struct termios *arg);
+ int (*ioctl_TCGETA) (void *data, ...);
+ int (*ioctl_TCSETA) (void *data, ...);
+ int (*ioctl_TCSETAF) (void *data, ...);
+ int (*ioctl_TCSETAW) (void *data, ...);
+ int (*ioctl_TIOCGLCKTRMIOS) (void *data, ...);
+ int (*ioctl_TIOCSLCKTRMIOS) (void *data, ...);
+ int (*ioctl_TCGETX) (void *data, ...);
+ int (*ioctl_TCSETX) (void *data, ...);
+ int (*ioctl_TCSETXW) (void *data, ...);
+ int (*ioctl_TCSETXF) (void *data, ...);
+ int (*ioctl_TIOCGSOFTCAR) (void *data, ...);
+ int (*ioctl_TIOCSSOFTCAR) (void *data, ...);
+
+ VT ioctls
+
int (*ioctl_TIOCLINUX) (void *data, ...);
int (*ioctl_KIOCSOUND) (void *data, ...);
int (*ioctl_KDMKTONE) (void *data, ...);
@@ -131,12 +157,8 @@ struct uvt_vt_ops {
int (*ioctl_KDENABIO) (void *data);
int (*ioctl_KDDISABIO) (void *data);
int (*ioctl_KDKBDREP) (void *data, struct kbd_repeat *arg);
- int (*ioctl_KDGETMODE) (void *data, long *arg);
- int (*ioctl_KDSETMODE) (void *data, long arg);
int (*ioctl_KDMAPDISP) (void *data);
int (*ioctl_KDUNMAPDISP) (void *data);
- int (*ioctl_KDGKBMODE) (void *data, long *arg);
- int (*ioctl_KDSKBMODE) (void *data, long arg);
int (*ioctl_KDGKBMETA) (void *data, long *arg);
int (*ioctl_KDSKBMETA) (void *data, long arg);
int (*ioctl_KDGETKEYCODE) (void *data, ...);
@@ -154,14 +176,7 @@ struct uvt_vt_ops {
int (*ioctl_KDGKBLED) (void *data, char *arg);
int (*ioctl_KDSKBLED) (void *data, long arg);
int (*ioctl_KDSIGACCEPT) (void *data, ...);
- int (*ioctl_VT_GETMODE) (void *data, struct vt_mode *arg);
- int (*ioctl_VT_SETMODE) (void *data, const struct vt_mode *arg);
- int (*ioctl_VT_GETSTATE) (void *data, struct vt_stat *arg);
- int (*ioctl_VT_OPENQRY) (void *data, int *arg);
- int (*ioctl_VT_ACTIVATE) (void *data, long arg);
int (*ioctl_VT_SETACTIVATE) (void *data, ...);
- int (*ioctl_VT_WAITACTIVE) (void *data, long arg);
- int (*ioctl_VT_RELDISP) (void *data, long arg);
int (*ioctl_VT_DISALLOCATE) (void *data, ...);
int (*ioctl_VT_RESIZE) (void *data, ...);
int (*ioctl_VT_RESIZEX) (void *data, ...);
@@ -184,26 +199,6 @@ struct uvt_vt_ops {
int (*ioctl_VT_UNLOCKSWITCH) (void *data);
int (*ioctl_VT_GETHIFONTMASK) (void *data, ...);
int (*ioctl_VT_WAITEVENT) (void *data, ...);
-
- int (*ioctl_TIOCPKT) (void *data, ...);
- int (*ioctl_TCFLSH) (void *data, long arg);
- int (*ioctl_TCXONC) (void *data, ...);
- int (*ioctl_TCGETS) (void *data, struct termios *arg);
- int (*ioctl_TCSETS) (void *data, const struct termios *arg);
- int (*ioctl_TCSETSF) (void *data, const struct termios *arg);
- int (*ioctl_TCSETSW) (void *data, const struct termios *arg);
- int (*ioctl_TCGETA) (void *data, ...);
- int (*ioctl_TCSETA) (void *data, ...);
- int (*ioctl_TCSETAF) (void *data, ...);
- int (*ioctl_TCSETAW) (void *data, ...);
- int (*ioctl_TIOCGLCKTRMIOS) (void *data, ...);
- int (*ioctl_TIOCSLCKTRMIOS) (void *data, ...);
- int (*ioctl_TCGETX) (void *data, ...);
- int (*ioctl_TCSETX) (void *data, ...);
- int (*ioctl_TCSETXW) (void *data, ...);
- int (*ioctl_TCSETXF) (void *data, ...);
- int (*ioctl_TIOCGSOFTCAR) (void *data, ...);
- int (*ioctl_TIOCSSOFTCAR) (void *data, ...);
*/
};
diff --git a/src/uvt_client.c b/src/uvt_client.c
index b58eb0b..d31a35b 100644
--- a/src/uvt_client.c
+++ b/src/uvt_client.c
@@ -814,7 +814,12 @@ void uvt_client_ll_ioctl(fuse_req_t req, int cmd, void *arg,
const void *in_buf, size_t in_bufsz, size_t out_bufsz)
{
struct uvt_client *client = (void*)(uintptr_t)fi->fh;
+ uintptr_t uarg = (uintptr_t)arg;
bool compat;
+ int ret;
+ struct vt_stat vtstat;
+ struct vt_mode vtmode;
+ unsigned int uval;
if (!client) {
fuse_reply_err(req, EINVAL);
@@ -835,6 +840,225 @@ void uvt_client_ll_ioctl(fuse_req_t req, int cmd, void *arg,
}
switch (cmd) {
+
+ /* TTY ioctls */
+
+ case TCFLSH:
+ if (ioctl_param(req, arg, 0, in_bufsz, 0, out_bufsz))
+ return;
+ if (!client->vt->ioctl_TCFLSH) {
+ fuse_reply_err(req, EOPNOTSUPP);
+ } else {
+ ret = client->vt->ioctl_TCFLSH(client->vt_data,
+ (unsigned long)uarg);
+ if (ret)
+ fuse_reply_err(req, abs(ret));
+ else
+ fuse_reply_ioctl(req, 0, NULL, 0);
+ }
+ break;
+
+ case TIOCPKT:
+ case TCXONC:
+ case TCGETS:
+ case TCSETS:
+ case TCSETSF:
+ case TCSETSW:
+ case TCGETA:
+ case TCSETA:
+ case TCSETAF:
+ case TCSETAW:
+ case TIOCGLCKTRMIOS:
+ case TIOCSLCKTRMIOS:
+ case TCGETX:
+ case TCSETX:
+ case TCSETXW:
+ case TCSETXF:
+ case TIOCGSOFTCAR:
+ case TIOCSSOFTCAR:
+ fuse_reply_err(req, EOPNOTSUPP);
+ break;
+
+ /* VT ioctls */
+
+ case VT_ACTIVATE:
+ if (ioctl_param(req, arg, 0, in_bufsz, 0, out_bufsz))
+ return;
+ if (!client->vt->ioctl_VT_ACTIVATE) {
+ fuse_reply_err(req, EOPNOTSUPP);
+ } else {
+ ret = client->vt->ioctl_VT_ACTIVATE(client->vt_data,
+ (unsigned long)uarg);
+ if (ret)
+ fuse_reply_err(req, abs(ret));
+ else
+ fuse_reply_ioctl(req, 0, NULL, 0);
+ }
+ break;
+
+ case VT_WAITACTIVE:
+ if (ioctl_param(req, arg, 0, in_bufsz, 0, out_bufsz))
+ return;
+ if (!client->vt->ioctl_VT_WAITACTIVE) {
+ fuse_reply_err(req, EOPNOTSUPP);
+ } else {
+ ret = client->vt->ioctl_VT_WAITACTIVE(client->vt_data,
+ (unsigned long)uarg);
+ if (ret)
+ fuse_reply_err(req, abs(ret));
+ else
+ fuse_reply_ioctl(req, 0, NULL, 0);
+ }
+ break;
+
+ case VT_GETSTATE:
+ if (ioctl_param(req, arg, 0, in_bufsz,
+ sizeof(struct vt_stat), out_bufsz))
+ return;
+ if (!client->vt->ioctl_VT_GETSTATE) {
+ fuse_reply_err(req, EOPNOTSUPP);
+ } else {
+ memset(&vtstat, 0, sizeof(vtstat));
+ ret = client->vt->ioctl_VT_GETSTATE(client->vt_data,
+ &vtstat);
+ if (ret)
+ fuse_reply_err(req, abs(ret));
+ else
+ fuse_reply_ioctl(req, 0, &vtstat,
+ sizeof(vtstat));
+ }
+ break;
+
+ case VT_OPENQRY:
+ if (ioctl_param(req, arg, 0, in_bufsz,
+ sizeof(unsigned int), out_bufsz))
+ return;
+ if (!client->vt->ioctl_VT_OPENQRY) {
+ fuse_reply_err(req, EOPNOTSUPP);
+ } else {
+ uval = 0;
+ ret = client->vt->ioctl_VT_OPENQRY(client->vt_data,
+ &uval);
+ if (ret)
+ fuse_reply_err(req, abs(ret));
+ else
+ fuse_reply_ioctl(req, 0, &uval, sizeof(uval));
+ }
+ break;
+
+ case VT_GETMODE:
+ if (ioctl_param(req, arg, 0, in_bufsz,
+ sizeof(struct vt_mode), out_bufsz))
+ return;
+ if (!client->vt->ioctl_VT_GETMODE) {
+ fuse_reply_err(req, EOPNOTSUPP);
+ } else {
+ memset(&vtmode, 0, sizeof(vtmode));
+ ret = client->vt->ioctl_VT_GETMODE(client->vt_data,
+ &vtmode);
+ if (ret)
+ fuse_reply_err(req, abs(ret));
+ else
+ fuse_reply_ioctl(req, 0, &vtmode,
+ sizeof(vtmode));
+ }
+ break;
+
+ case VT_SETMODE:
+ if (ioctl_param(req, arg, sizeof(struct vt_mode), in_bufsz,
+ 0, out_bufsz))
+ return;
+ if (!client->vt->ioctl_VT_SETMODE) {
+ fuse_reply_err(req, EOPNOTSUPP);
+ } else {
+ ret = client->vt->ioctl_VT_SETMODE(client->vt_data,
+ (const struct vt_mode*)in_buf);
+ if (ret)
+ fuse_reply_err(req, abs(ret));
+ else
+ fuse_reply_ioctl(req, 0, NULL, 0);
+ }
+ break;
+
+ case VT_RELDISP:
+ if (ioctl_param(req, arg, 0, in_bufsz, 0, out_bufsz))
+ return;
+ if (!client->vt->ioctl_VT_RELDISP) {
+ fuse_reply_err(req, EOPNOTSUPP);
+ } else {
+ ret = client->vt->ioctl_VT_RELDISP(client->vt_data,
+ (unsigned long)uarg);
+ if (ret)
+ fuse_reply_err(req, abs(ret));
+ else
+ fuse_reply_ioctl(req, 0, NULL, 0);
+ }
+ break;
+
+ case KDGETMODE:
+ if (ioctl_param(req, arg, 0, in_bufsz,
+ sizeof(unsigned int), out_bufsz))
+ return;
+ if (!client->vt->ioctl_KDGETMODE) {
+ fuse_reply_err(req, EOPNOTSUPP);
+ } else {
+ uval = 0;
+ ret = client->vt->ioctl_KDGETMODE(client->vt_data,
+ &uval);
+ if (ret)
+ fuse_reply_err(req, abs(ret));
+ else
+ fuse_reply_ioctl(req, 0, &uval, sizeof(uval));
+ }
+ break;
+
+ case KDSETMODE:
+ if (ioctl_param(req, arg, 0, in_bufsz, 0, out_bufsz))
+ return;
+ if (!client->vt->ioctl_KDSETMODE) {
+ fuse_reply_err(req, EOPNOTSUPP);
+ } else {
+ ret = client->vt->ioctl_KDSETMODE(client->vt_data,
+ (unsigned int)uarg);
+ if (ret)
+ fuse_reply_err(req, abs(ret));
+ else
+ fuse_reply_ioctl(req, 0, NULL, 0);
+ }
+ break;
+
+ case KDGKBMODE:
+ if (ioctl_param(req, arg, 0, in_bufsz,
+ sizeof(unsigned int), out_bufsz))
+ return;
+ if (!client->vt->ioctl_KDGKBMODE) {
+ fuse_reply_err(req, EOPNOTSUPP);
+ } else {
+ uval = 0;
+ ret = client->vt->ioctl_KDGKBMODE(client->vt_data,
+ &uval);
+ if (ret)
+ fuse_reply_err(req, abs(ret));
+ else
+ fuse_reply_ioctl(req, 0, &uval, sizeof(uval));
+ }
+ break;
+
+ case KDSKBMODE:
+ if (ioctl_param(req, arg, 0, in_bufsz, 0, out_bufsz))
+ return;
+ if (!client->vt->ioctl_KDSKBMODE) {
+ fuse_reply_err(req, EOPNOTSUPP);
+ } else {
+ ret = client->vt->ioctl_KDSKBMODE(client->vt_data,
+ (unsigned int)uarg);
+ if (ret)
+ fuse_reply_err(req, abs(ret));
+ else
+ fuse_reply_ioctl(req, 0, NULL, 0);
+ }
+ break;
+
case TIOCLINUX:
case KIOCSOUND:
case KDMKTONE:
@@ -844,12 +1068,8 @@ void uvt_client_ll_ioctl(fuse_req_t req, int cmd, void *arg,
case KDENABIO:
case KDDISABIO:
case KDKBDREP:
- case KDGETMODE:
- case KDSETMODE:
case KDMAPDISP:
case KDUNMAPDISP:
- case KDGKBMODE:
- case KDSKBMODE:
case KDGKBMETA:
case KDSKBMETA:
case KDGETKEYCODE:
@@ -867,14 +1087,7 @@ void uvt_client_ll_ioctl(fuse_req_t req, int cmd, void *arg,
case KDGKBLED:
case KDSKBLED:
case KDSIGACCEPT:
- case VT_GETMODE:
- case VT_SETMODE:
- case VT_GETSTATE:
- case VT_OPENQRY:
- case VT_ACTIVATE:
case VT_SETACTIVATE:
- case VT_WAITACTIVE:
- case VT_RELDISP:
case VT_DISALLOCATE:
case VT_RESIZE:
case VT_RESIZEX:
@@ -899,28 +1112,6 @@ void uvt_client_ll_ioctl(fuse_req_t req, int cmd, void *arg,
case VT_WAITEVENT:
fuse_reply_err(req, EOPNOTSUPP);
break;
-
- case TIOCPKT:
- case TCFLSH:
- case TCXONC:
- case TCGETS:
- case TCSETS:
- case TCSETSF:
- case TCSETSW:
- case TCGETA:
- case TCSETA:
- case TCSETAF:
- case TCSETAW:
- case TIOCGLCKTRMIOS:
- case TIOCSLCKTRMIOS:
- case TCGETX:
- case TCSETX:
- case TCSETXW:
- case TCSETXF:
- case TIOCGSOFTCAR:
- case TIOCSSOFTCAR:
- fuse_reply_err(req, EOPNOTSUPP);
- break;
default:
fuse_reply_err(req, EINVAL);
break;