# How the openlogi-permissions Crate Checks macOS TCC and Linux Device Permissions

> Discover how the openlogi-permissions crate unifies macOS TCC and Linux device permission checks using read-only APIs and /dev probing for seamless application integration.

- Repository: [Xuan Zhang/OpenLogi](https://github.com/AprilNEA/OpenLogi)
- Tags: how-to-guide
- Published: 2026-09-13

---

**The openlogi-permissions crate provides a non-prompting abstraction layer that queries macOS TCC permissions via read-only system APIs and validates Linux device access by probing `/dev/uinput` and Logitech hidraw nodes, returning a unified `PermissionStatus` enum across both platforms.**

The `openlogi-permissions` crate in the AprilNEA/OpenLogi repository standardizes privacy permission detection for the OpenLogi agent. It enables silent status checks without triggering system consent dialogs, while supporting deep-link navigation to macOS System Settings when users need to manually grant access.

## macOS TCC Permission Handling

The macOS implementation in [`src/macos.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/src/macos.rs) focuses on **Transparency, Consent, and Control (TCC)** permissions, specifically covering Accessibility, Input Monitoring, CoreBluetooth, and Camera access. All query functions use read-only APIs—such as `IOHIDCheckAccess`—to ensure the crate never triggers a permission prompt; the owning process presents the prompt only when first accessing the resource.

### Querying Input Monitoring and Accessibility

The `input_monitoring()` function determines authorization status by calling `IOHIDCheckAccess(IOHIDRequestType::ListenEvent)` and mapping the result to `PermissionStatus::{Granted, Denied, Unknown}`. As implemented in [`src/macos.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/src/macos.rs) lines 22-30, this approach reads the current TCC database state without modifying it or alerting the user.

### Bluetooth Authorization Status

For Bluetooth permissions, the `bluetooth()` function instantiates the Objective-C class `CBCentralManager` via the `objc2` crate to read the `authorization` property. According to [`src/macos.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/src/macos.rs) lines 32-48, the implementation translates the integer authorization codes into the crate's `PermissionStatus` enum, allowing the agent to detect whether the user has granted CoreBluetooth access.

### Camera Access Detection

The `camera()` function delegates to the `openlogi-camera` crate's `camera_authorization()` function, then maps the returned enum to `PermissionStatus`. This integration, found in [`src/macos.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/src/macos.rs) lines 51-59, ensures consistent status reporting across the OpenLogi ecosystem while respecting the camera subsystem's specific implementation.

### Deep-Linking to System Settings

When the application needs to direct users to grant permissions manually, the `open_pane(permission)` function constructs deep-link URLs such as `x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility` based on the `Permission` enum variant. As defined in [`src/macos.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/src/macos.rs) lines 62-75, this helper uses the `opener` crate to launch the specific privacy pane in System Settings.

## Linux Device Permission Validation

Linux platforms lack consent dialogs; instead, access depends on udev rules granting read/write rights to device files. The implementation in [`src/linux.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/src/linux.rs) probes these filesystem permissions to determine if the user can access input devices.

### Probing /dev/uinput and HID-Raw Devices

The `input_device_access()` function performs two distinct probes:

- **Uinput check** – Attempts to open `/dev/uinput` for writing; success indicates the user has permissions to create virtual input devices ([`src/linux.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/src/linux.rs) lines 62-68).
- **Logitech HID-raw scan** – Iterates through `/dev` entries matching `hidraw*`, filters devices belonging to Logitech using the vendor ID defined in `openlogi_core`, and attempts read/write access. The results populate the internal `HidrawProbe` enum ([`src/linux.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/src/linux.rs) lines 70-88).

### Permission Status Logic

The combined probe results convert to `PermissionStatus` via the `From<Probes>` implementation in [`src/linux.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/src/linux.rs) lines 54-58:

- **Granted** – Both uinput is writable and at least one Logitech hidraw device is accessible.
- **Denied** – Either uinput is not writable or hidraw access is denied.
- **Unknown** – Uinput is writable but no Logitech hidraw devices are present (hardware may be disconnected).

Because Linux lacks a settings pane equivalent, the `open_pane` function is a no-op on non-macOS platforms ([`src/lib.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/src/lib.rs) lines 72-76).

## Cross-Platform API Usage

The crate exposes platform-specific functions conditionally compiled via `#[cfg]`. Applications can query permissions without handling platform differences manually:

```rust
use openlogi_permissions::{Permission, PermissionStatus, open_pane};

#[cfg(target_os = "macos")]
fn check_macos_permissions() {
    // Query current status without prompting
    let im = openlogi_permissions::input_monitoring();
    println!("Input Monitoring: {:?}", im);
    
    // Open System Settings if access is denied
    if im != PermissionStatus::Granted {
        open_pane(Permission::Accessibility);
    }
}

#[cfg(target_os = "linux")]
fn check_linux_permissions() {
    // Returns Granted, Denied, or Unknown based on device file probes
    let dev = openlogi_permissions::input_device_access();
    println!("Linux input-device access: {:?}", dev);
}

```

## Summary

- The `openlogi-permissions` crate provides a unified `PermissionStatus` abstraction across macOS TCC and Linux udev permission models.
- macOS checks use read-only APIs (`IOHIDCheckAccess`, `CBCentralManager`) in [`src/macos.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/src/macos.rs) to avoid triggering prompts, while supporting deep-links to System Settings.
- Linux validation probes `/dev/uinput` and Logitech `hidraw` device files in [`src/linux.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/src/linux.rs) to determine access rights without requiring consent dialogs.
- The `open_pane` helper only functions on macOS, providing URLs like `x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility` for manual permission configuration.

## Frequently Asked Questions

### How does openlogi-permissions avoid triggering macOS permission prompts?

The crate exclusively uses read-only APIs such as `IOHIDCheckAccess` for Input Monitoring and property reads on `CBCentralManager` for Bluetooth. These functions query the TCC database without requesting access, ensuring `input_monitoring()` and `bluetooth()` calls remain silent. The owning process—typically the OpenLogi agent—triggers the actual prompt only when first attempting to use the protected resource.

### What determines PermissionStatus::Unknown on Linux?

According to the `From<Probes>` implementation in [`src/linux.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/src/linux.rs) lines 57-58, the status returns `Unknown` when the user has write access to `/dev/uinput` but no Logitech hidraw devices are detected in `/dev`. This typically indicates that the user has sufficient permissions but the hardware is disconnected or not yet enumerated by the kernel.

### Why is the open_pane function unavailable on Linux?

Linux lacks a centralized consent management interface equivalent to macOS System Settings TCC panes. As implemented in [`src/lib.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/src/lib.rs) lines 72-76, the `open_pane` function compiles to a no-op on non-macOS targets, allowing cross-platform code to call it unconditionally without runtime errors.

### Which specific device files does the Linux implementation check?

The Linux module in [`src/linux.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/src/linux.rs) validates two resources: `/dev/uinput` for virtual input device creation, and `/dev/hidraw*` nodes specifically filtered for Logitech vendor IDs (defined in `openlogi_core`). The implementation attempts read/write opens on these files to determine effective permissions, returning `Granted` only when both resources are accessible.