diff options
-rw-r--r-- | src/uvt.h | 101 | ||||
-rw-r--r-- | src/uvt_client.c | 257 |
2 files changed, 272 insertions, 86 deletions
@@ -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; |