#!/usr/bin/env python3 """Диагностика открытия HID-устройства через IOKit напрямую (ctypes). Берёт путь устройства из hidapi (DevSrvsID: = registry entry ID), открывает сервис через IORegistryEntryIDMatching + IOHIDDeviceCreate (как делает сам hidapi) и печатает точный код IOReturn от IOHIDDeviceOpen: - 0x00000000 — успех (права есть, проблема в hidapi) - 0xE00002C1 — kIOReturnNotPrivileged (нет разрешения Input Monitoring) - другой код — иная причина (см. коды IOKit, iokit_common_err). """ import ctypes import ctypes.util import re import sys import hid iokit = ctypes.CDLL(ctypes.util.find_library("IOKit")) cf = ctypes.CDLL(ctypes.util.find_library("CoreFoundation")) # прототипы функций iokit.IOServiceGetMatchingService.argtypes = [ctypes.c_int, ctypes.c_void_p] iokit.IOServiceGetMatchingService.restype = ctypes.c_uint iokit.IORegistryEntryIDMatching.argtypes = [ctypes.c_longlong] iokit.IORegistryEntryIDMatching.restype = ctypes.c_void_p iokit.IOObjectRelease.argtypes = [ctypes.c_uint] iokit.IOObjectRelease.restype = ctypes.c_int iokit.IOHIDDeviceCreate.argtypes = [ctypes.c_void_p, ctypes.c_uint] iokit.IOHIDDeviceCreate.restype = ctypes.c_void_p iokit.IOHIDDeviceOpen.argtypes = [ctypes.c_void_p, ctypes.c_int] iokit.IOHIDDeviceOpen.restype = ctypes.c_int iokit.IOHIDDeviceClose.argtypes = [ctypes.c_void_p, ctypes.c_int] iokit.IOHIDDeviceClose.restype = ctypes.c_int cf.CFRelease.argtypes = [ctypes.c_void_p] def main(): """Найти iface0 клавиатуры через hidapi и открыть её сервис в IOKit.""" paths = [i["path"].decode() for i in hid.enumerate(0x0C45, 0x8006) if i["interface_number"] == 0] if not paths: raise SystemExit("устройство 0C45:8006 не найдено через hidapi") m = re.fullmatch(r"DevSrvsID:(\d+)", paths[0]) if not m: raise SystemExit(f"неожиданный формат пути: {paths[0]!r}") entry_id = int(m.group(1)) service = iokit.IOServiceGetMatchingService( 0, iokit.IORegistryEntryIDMatching(entry_id)) if not service: raise SystemExit(f"сервис с entry_id {entry_id} не найден в реестре") print(f"сервис найден: {service:#x}") dev = iokit.IOHIDDeviceCreate(None, service) iokit.IOObjectRelease(service) if not dev: raise SystemExit("IOHIDDeviceCreate вернул NULL") print("IOHIDDeviceCreate: ok") r = iokit.IOHIDDeviceOpen(dev, 0) # kIOHIDOptionsTypeNone meaning = {0x00000000: "OK (права есть)", 0xE00002C1: "NotPrivileged — нет разрешения Input Monitoring", }.get(r, "см. коды IOKit (iokit_common_err)") print(f"IOHIDDeviceOpen: {r:#010x} ({meaning})") if r == 0: iokit.IOHIDDeviceClose(dev, 0) cf.CFRelease(dev) if __name__ == "__main__": main()