# How vphone-cli Handles Touch and Key Input in the Virtual iPhone

> Discover how vphone-cli injects touch and key input into virtual iPhones using a vsock-based HID bridge, integrating keyboard and biometric sensor functionality.

- Repository: [Lakr/vphone-cli](https://github.com/Lakr233/vphone-cli)
- Tags: internals
- Published: 2026-09-10

---

**vphone-cli injects hardware key events and Touch ID gestures into a virtual iOS device through a vsock-based HID bridge, combining the `VPhoneKeyHelper` for keyboard input and `VPhoneTouchIDMonitor` for biometric sensor integration.**

The open-source tool `vphone-cli` by Lakr233 enables macOS users to run a virtual iPhone inside Apple Silicon Macs. Understanding how vphone-cli handles touch and key input reveals the sophisticated machinery that translates host-side interactions—ranging from menu bar clicks to physical Touch ID presses—into valid iOS HID events delivered via a guest daemon.

## Input Architecture Overview

Two complementary Swift classes manage the input pipeline. **`VPhoneKeyHelper`** translates menu bar commands and clipboard text into HID reports, while **`VPhoneTouchIDMonitor`** interfaces with the host's BiometricKit framework to repurpose the Mac's Touch ID sensor as a virtual Home button. Both components rely on **`VPhoneControl`** to marshal these events across a vsock connection to the guest's `vphoned` daemon.

## Keyboard and Hardware Key Input (VPhoneKeyHelper)

Located in [`sources/vphone-cli/VPhoneKeyHelper.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/vphone-cli/VPhoneKeyHelper.swift), this helper class manages all non-touch input to the VM by holding references to the `VZVirtualMachine` and `VPhoneControl` instances.

### Sending HID Consumer Page Events

For hardware buttons like Home, Power, and Volume, the helper uses the Consumer HID usage page (`0x0C`). The `sendHome()` method calls `VPhoneControl.sendHIDPress(page: 0x0C, usage: 0x40)`, encoding the event as JSON before transmission over vsock port 1337. All actions first verify the guest daemon connection via `requireConnection()` to prevent sending events to an unresponsive VM.

### Typing ASCII Text via Virtual Keyboards

When typing strings from the clipboard, `VPhoneKeyHelper` discovers the first available virtual keyboard from the VM's private `_keyboards` array using Swift's **Dynamic** runtime library. It maps each ASCII character to a virtual key code via `asciiToVK`, constructs press/release sequences using `_VZKeyEvent` objects, and dispatches them through `Dynamic(keyboard).sendKeyEvents`.

```swift
let keyHelper = VPhoneKeyHelper(vm: vm, control: control)
keyHelper.typeFromClipboard()   // Reads NSPasteboard, calls typeString(_:)

```

## Touch ID Integration (VPhoneTouchIDMonitor)

The `VPhoneTouchIDMonitor` class in [`sources/vphone-cli/VPhoneTouchIDMonitor.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/vphone-cli/VPhoneTouchIDMonitor.swift) repurposes the host Mac's Touch ID sensor to control the virtual iPhone's Home button behavior through gesture detection.

### BiometricKit Runtime Loading

The monitor loads the private **BiometricKit** framework at runtime using `dlopen`. It obtains the singleton manager via `BiometricKit.manager()` and registers a `VPhoneBiometricDelegate` to receive callbacks including `touchIDButtonPressed` and `presenceStateChanged` for finger-down/up detection.

### Gesture State Machine and Debouncing

A debounced state machine distinguishes between single and double taps. If two `handleFingerDown` events occur within 0.30 seconds (the `doubleTapWindow`), the monitor sends two consecutive Home button presses to trigger the iOS app switcher. A single tap triggers one Home press after the debounce window expires. Both gestures ultimately invoke `control.sendHIDPress(page: 0x0C, usage: 0x40)`.

```swift
// Started when VM window becomes key
touchIDMonitor.start(control: control, window: vmWindow)

```

## The vsock Communication Bridge (VPhoneControl)

Found in [`sources/vphone-cli/VPhoneControl.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/vphone-cli/VPhoneControl.swift), this class provides the actual transport layer. It exposes `sendHIDPress`, `sendHIDDown`, and `sendHIDUp` methods that encode HID reports as JSON and forward them through the vsock connection on port 1337 to the guest-side `vphoned` daemon. The daemon then injects these events directly into the iOS input subsystem, maintaining VM isolation while ensuring responsive input delivery.

## Summary

- **`VPhoneKeyHelper`** converts menu bar commands and clipboard text into HID events using the Consumer usage page (`0x0C`) and virtual keyboard objects discovered via runtime reflection.
- **`VPhoneTouchIDMonitor`** intercepts host Touch ID sensor events via BiometricKit and translates them into Home button presses with single/double-tap gesture support (0.30-second window).
- **`VPhoneControl`** bridges host and guest via vsock port 1337, delivering serialized HID reports to the `vphoned` daemon for injection into the iOS HID subsystem.
- All input paths verify daemon connectivity via `requireConnection()` before transmission to ensure the VM is ready to receive events.

## Frequently Asked Questions

### How does vphone-cli send text input to the virtual iPhone?

`VPhoneKeyHelper` discovers the VM's virtual keyboard through the Dynamic runtime by accessing the private `_keyboards` array. It maps ASCII characters to virtual key codes using `asciiToVK`, constructs `_VZKeyEvent` press/release sequences, and dispatches them via `sendKeyEvents`. This allows typing directly from the macOS clipboard into the virtual iPhone.

### Can I use my Mac's Touch ID to control the virtual iPhone Home button?

Yes. `VPhoneTouchIDMonitor` loads the BiometricKit framework using `dlopen` and registers a `VPhoneBiometricDelegate` to receive finger contact callbacks. Single taps send one Home button press (`usage: 0x40`), while double taps within 0.30 seconds send two presses to open the iOS app switcher.

### What protocol does vphone-cli use to communicate input events to the guest?

All input travels over a **vsock** connection on port 1337. `VPhoneControl` encodes HID reports as JSON and sends them to the guest-side `vphoned` daemon, which handles the actual injection into the iOS HID subsystem through the Virtualization framework.

### Where is the input handling code located in the repository?

The core implementation resides in three files: [`sources/vphone-cli/VPhoneKeyHelper.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/vphone-cli/VPhoneKeyHelper.swift) for keyboard and hardware key input, [`sources/vphone-cli/VPhoneTouchIDMonitor.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/vphone-cli/VPhoneTouchIDMonitor.swift) for Touch ID sensor handling, and [`sources/vphone-cli/VPhoneControl.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/vphone-cli/VPhoneControl.swift) for the vsock communication layer that bridges host and guest.