From 65644bab8baf486d3439b339fa69333245f38bed Mon Sep 17 00:00:00 2001 From: Eric Callahan Date: Wed, 16 Aug 2023 19:32:16 -0400 Subject: [PATCH] utils: add ioctl_macros module Signed-off-by: Eric Callahan --- moonraker/utils/ioctl_macros.py | 77 +++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 moonraker/utils/ioctl_macros.py diff --git a/moonraker/utils/ioctl_macros.py b/moonraker/utils/ioctl_macros.py new file mode 100644 index 0000000..148e909 --- /dev/null +++ b/moonraker/utils/ioctl_macros.py @@ -0,0 +1,77 @@ +# Methods to create IOCTL requests +# +# Copyright (C) 2023 Eric Callahan +# +# This file may be distributed under the terms of the GNU GPLv3 license + +from __future__ import annotations +import ctypes +from typing import Union, Type, TYPE_CHECKING + +""" +This module contains of Python port of the macros avaialble in +"/include/uapi/asm-generic/ioctl.h" from the linux kernel. +""" + +if TYPE_CHECKING: + IOCParamSize = Union[int, str, Type[ctypes._SimpleCData]] + +_IOC_NRBITS = 8 +_IOC_TYPEBITS = 8 + +# NOTE: The following could be platform specific. +_IOC_SIZEBITS = 14 +_IOC_DIRBITS = 2 + +_IOC_NRMASK = (1 << _IOC_NRBITS) - 1 +_IOC_TYPEMASK = (1 << _IOC_TYPEBITS) - 1 +_IOC_SIZEMASK = (1 << _IOC_SIZEBITS) - 1 +_IOC_DIRMASK = (1 << _IOC_DIRBITS) - 1 + +_IOC_NRSHIFT = 0 +_IOC_TYPESHIFT = _IOC_NRSHIFT + _IOC_NRBITS +_IOC_SIZESHIFT = _IOC_TYPESHIFT + _IOC_TYPEBITS +_IOC_DIRSHIFT = _IOC_SIZESHIFT + _IOC_SIZEBITS + +# The constants below may also be platform specific +IOC_NONE = 0 +IOC_WRITE = 1 +IOC_READ = 2 + +def _check_value(val: int, name: str, maximum: int): + if val > maximum: + raise ValueError(f"Value '{val}' for '{name}' exceeds max of {maximum}") + +def _IOC_TYPECHECK(param_size: IOCParamSize) -> int: + if isinstance(param_size, int): + return param_size + elif isinstance(param_size, bytearray): + return len(param_size) + elif isinstance(param_size, str): + ctcls = getattr(ctypes, param_size) + return ctypes.sizeof(ctcls) + return ctypes.sizeof(param_size) + +def IOC(direction: int, cmd_type: int, cmd_number: int, param_size: int) -> int: + _check_value(direction, "direction", _IOC_DIRMASK) + _check_value(cmd_type, "cmd_type", _IOC_TYPEMASK) + _check_value(cmd_number, "cmd_number", _IOC_NRMASK) + _check_value(param_size, "ioc_size", _IOC_SIZEMASK) + return ( + (direction << _IOC_DIRSHIFT) | + (param_size << _IOC_SIZESHIFT) | + (cmd_type << _IOC_TYPESHIFT) | + (cmd_number << _IOC_NRSHIFT) + ) + +def IO(cmd_type: int, cmd_number: int) -> int: + return IOC(IOC_NONE, cmd_type, cmd_number, 0) + +def IOR(cmd_type: int, cmd_number: int, param_size: IOCParamSize) -> int: + return IOC(IOC_READ, cmd_type, cmd_number, _IOC_TYPECHECK(param_size)) + +def IOW(cmd_type: int, cmd_number: int, param_size: IOCParamSize) -> int: + return IOC(IOC_WRITE, cmd_type, cmd_number, _IOC_TYPECHECK(param_size)) + +def IOWR(cmd_type: int, cmd_number: int, param_size: IOCParamSize) -> int: + return IOC(IOC_READ | IOC_WRITE, cmd_type, cmd_number, _IOC_TYPECHECK(param_size))