From ee0ce9bae92836e5bd8df21e2b48784692d56194 Mon Sep 17 00:00:00 2001 From: no92 Date: Fri, 11 Oct 2024 17:08:35 +0200 Subject: [PATCH] sysdeps/managarm: implement EVIOCGMTSLOTS --- sysdeps/managarm/generic/ioctl.cpp | 60 ++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/sysdeps/managarm/generic/ioctl.cpp b/sysdeps/managarm/generic/ioctl.cpp index 9e8fd718d9..b0925e6929 100644 --- a/sysdeps/managarm/generic/ioctl.cpp +++ b/sysdeps/managarm/generic/ioctl.cpp @@ -614,6 +614,66 @@ int sys_ioctl(int fd, unsigned long request, void *arg, int *result) { auto size = _IOC_SIZE(request); memset(arg, 0, size); *result = size; + return 0; + }else if(_IOC_TYPE(request) == 'E' + && _IOC_NR(request) == _IOC_NR(EVIOCGMTSLOTS(0))) { + // this ioctl is completely, utterly undocumented + // the _IOC_SIZE is a buffer size in bytes, which should be a multiple of int32_t + // bytes should be at least sizeof(int32_t) large. + // the argument (the pointer to the buffer) is an array of int32_t + // the first entry is the number of values supplied, followed by the values + // this would have been worthwhile to document ffs + + // the length argument is the buffer size, in bytes + auto bytes = _IOC_SIZE(request); + // the length argument should be a multiple of int32_t + if(!bytes || bytes % sizeof(int32_t)) + return EINVAL; + + // the number of entries the buffer can hold + auto entries = (bytes / sizeof(int32_t)) - 1; + + managarm::fs::EvioGetMultitouchSlotsRequest req(getSysdepsAllocator()); + req.set_code(*reinterpret_cast(arg)); + + auto [offer, send_ioctl_req, send_req, recv_resp] = exchangeMsgsSync( + handle, + helix_ng::offer( + helix_ng::want_lane, + helix_ng::sendBragiHeadOnly(ioctl_req, getSysdepsAllocator()), + helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), + helix_ng::recvInline()) + ); + HEL_CHECK(offer.error()); + auto conversation = offer.descriptor(); + HEL_CHECK(send_ioctl_req.error()); + HEL_CHECK(send_req.error()); + HEL_CHECK(recv_resp.error()); + + auto preamble = bragi::read_preamble(recv_resp); + __ensure(!preamble.error()); + + frg::vector tailBuffer{getSysdepsAllocator()}; + tailBuffer.resize(preamble.tail_size()); + auto [recv_tail] = exchangeMsgsSync( + conversation.getHandle(), + helix_ng::recvBuffer(tailBuffer.data(), tailBuffer.size()) + ); + + HEL_CHECK(recv_tail.error()); + + auto resp = *bragi::parse_head_tail(recv_resp, tailBuffer, getSysdepsAllocator()); + recv_resp.reset(); + __ensure(resp.error() == managarm::fs::Errors::SUCCESS); + + auto param = reinterpret_cast(arg); + + for(size_t i = 0; i < resp.values_size() && i < entries; i++) { + param[i + 1] = resp.values(i); + } + + param[0] = resp.values_size(); + return 0; }else if(_IOC_TYPE(request) == 'E' && _IOC_NR(request) == _IOC_NR(EVIOCGLED(0))) {