### Build Example Executables Source: https://github.com/jkcoxson/idevice/blob/master/cpp/examples/CMakeLists.txt Iterates through each example source file, creates an executable, sets its include directories, and links it against the 'idevice_cpp' library. ```cmake foreach(EXAMPLE_FILE ${EXAMPLE_SOURCES}) get_filename_component(EXAMPLE_NAME ${EXAMPLE_FILE} NAME_WE) add_executable(${EXAMPLE_NAME} ${EXAMPLE_FILE}) # Examples include public headers and (if they directly include FFI headers) the FFI dir. target_include_directories(${EXAMPLE_NAME} PRIVATE ${IDEVICE_CPP_INCLUDE_DIR} ${IDEVICE_FFI_INCLUDE_DIR} ${PLIST_CPP_INCLUDE_DIR} ) # Link to your C++ wrapper (inherits Rust lib + frameworks/system libs) target_link_libraries(${EXAMPLE_NAME} PRIVATE idevice_cpp) endforeach() ``` -------------------------------- ### Building C Examples Source: https://github.com/jkcoxson/idevice/blob/master/ffi/examples/CMakeLists.txt Iterates through each found C example file, creates an executable, and links necessary libraries and frameworks. ```cmake foreach(EXAMPLE_FILE ${EXAMPLE_SOURCES}) # Extract the filename without the path get_filename_component(EXAMPLE_NAME ${EXAMPLE_FILE} NAME_WE) # Create an executable for this example add_executable(${EXAMPLE_NAME} ${EXAMPLE_FILE}) # Include the generated header target_include_directories(${EXAMPLE_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/..) # Link the static Rust library target_link_libraries(${EXAMPLE_NAME} PRIVATE ${STATIC_LIB}) if(UNIX AND NOT APPLE) target_link_libraries(${EXAMPLE_NAME} PRIVATE m) endif() # Bulk-link common macOS system frameworks if(APPLE) target_link_libraries(${EXAMPLE_NAME} PRIVATE "-framework CoreFoundation" "-framework Security" "-framework SystemConfiguration" "-framework CoreServices" "-framework IOKit" "-framework CFNetwork" ) endif() endforeach() ``` -------------------------------- ### Finding Example Sources Source: https://github.com/jkcoxson/idevice/blob/master/ffi/examples/CMakeLists.txt Uses file globbing to find all C example files within the specified examples directory. ```cmake file(GLOB EXAMPLE_SOURCES ${EXAMPLES_DIR}/*.c) ``` -------------------------------- ### Find Example Source Files Source: https://github.com/jkcoxson/idevice/blob/master/cpp/examples/CMakeLists.txt Finds all .cpp files in the examples directory. ```cmake file(GLOB EXAMPLE_SOURCES ${EXAMPLES_DIR}/*.cpp) ``` -------------------------------- ### LockdownClient Usage Example Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/lockdown.md Demonstrates the typical workflow for initializing and using the LockdownClient to interact with an iOS device. This includes connecting to the service, starting a secure session, retrieving device information, and starting other services like AFC. ```APIDOC ## LockdownClient Workflow ### Description This example illustrates the common steps involved in using the `LockdownClient` to communicate with an iOS device. It covers connecting to the lockdown service, establishing a secure session using pairing information, fetching device details, and launching other device services. ### Method `LockdownClient::connect` `LockdownClient::start_session` `LockdownClient::get_value` `LockdownClient::start_service` ### Parameters #### `LockdownClient::connect` - `provider`: An object implementing `IdeviceService` to establish the connection. #### `LockdownClient::start_session` - `pairing_file`: A `PairingFile` object containing device pairing information. - `legacy`: A boolean indicating whether to use legacy session protocols. #### `LockdownClient::get_value` - `key`: An optional string representing the key for the value to retrieve (e.g., `"DeviceName"`). - `domain`: An optional string representing the domain for the value. #### `LockdownClient::start_service` - `service_name`: The name of the service to start (e.g., `"com.apple.afc"`). ### Request Example ```rust use idevice::services::lockdown::LockdownClient; use idevice::IdeviceService; use idevice::pairing_file::PairingFile; // Assume `provider` is an initialized IdeviceService and `pairing_file` is read from a file. let provider = /* ... */; let pairing_file = PairingFile::read_from_file("/path/to/pairing.plist")?; // 1. Connect to lockdown let mut lockdown = LockdownClient::connect(&provider).await?; // 2. Start a secure session let legacy = lockdown.start_session(&pairing_file).await?; // 3. Get device info let device_name = lockdown.get_value(Some("DeviceName"), None).await?; println!("Device: {:?}", device_name); // 4. Start a service (e.g., AFC) let (port, needs_ssl) = lockdown.start_service("com.apple.afc").await?; let mut service = provider.connect(port).await?; if needs_ssl { service.start_session(&pairing_file, legacy).await?; } ``` ### Response #### `LockdownClient::get_value` Success Response - Returns the requested device value (type depends on the key). #### `LockdownClient::start_service` Success Response - `port` (u16): The TCP port for the started service. - `needs_ssl` (bool): Indicates if SSL is required for the service connection. ### Related Documentation - [Idevice Core Connection](./idevice.md) - [types.md](../types.md) - [Pairing Services](../pairing.md) ``` -------------------------------- ### Basic CMake Project Setup Source: https://github.com/jkcoxson/idevice/blob/master/ffi/examples/CMakeLists.txt Initializes CMake, sets the project name, and enables command export for compilation databases. ```cmake set(CMAKE_EXPORT_COMPILE_COMMANDS ON) cmake_minimum_required(VERSION 3.10) project(IdeviceFFI C) ``` -------------------------------- ### Typical Lockdown Service Workflow Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/lockdown.md Demonstrates a common workflow for initializing and using Lockdown services. This includes connecting to lockdown, starting a secure session, retrieving device information, and starting another service like AFC. ```rust use idevice::services::lockdown::LockdownClient; use idevice::IdeviceService; use idevice::pairing_file::PairingFile; // 1. Connect to lockdown let provider = /* ... */; let mut lockdown = LockdownClient::connect(&provider).await?; // 2. Start a secure session let pairing_file = PairingFile::read_from_file("/path/to/pairing.plist")?; let legacy = lockdown.start_session(&pairing_file).await?; // 3. Get device info let device_name = lockdown.get_value(Some("DeviceName"), None).await?; println!("Device: {:?}", device_name); // 4. Start a service let (port, needs_ssl) = lockdown.start_service("com.apple.afc").await?; let mut service = provider.connect(port).await?; if needs_ssl { service.start_session(&pairing_file, legacy).await?; } ``` -------------------------------- ### Generic Service Connection with Provider Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/README.md Example demonstrating how to connect to a service using a provider, highlighting the abstraction over connection types. ```rust // Works with TcpProvider or UsbmuxdProvider let service = SomeService::connect(&provider).await?; ``` -------------------------------- ### Typical UsbmuxdProvider Setup Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/provider.md Illustrates a common workflow for setting up and using UsbmuxdProvider, including discovering devices and connecting to services like Lockdown. ```APIDOC ## Typical UsbmuxdProvider Setup ### Description This example shows a typical setup process: first, discover available devices using `UsbmuxdConnection`. Then, create a `UsbmuxdProvider` instance using the discovered device's information. Finally, use this provider to establish a connection to a service, such as `LockdownClient`. ### Steps 1. **Discover device via usbmuxd**: Establish a connection to the usbmuxd daemon and retrieve a list of connected devices. 2. **Create provider from discovered device**: Instantiate `UsbmuxdProvider` using details from a discovered device. 3. **Use provider transparently**: Connect to a device service (e.g., Lockdown) using the created provider. ### Example ```rust use idevice::usbmuxd::UsbmuxdConnection; use idevice::provider::UsbmuxdProvider; use idevice::services::lockdown::LockdownClient; use idevice::IdeviceService; // 1. Discover device via usbmuxd let mut usbmuxd = UsbmuxdConnection::default().await?; let devices = usbmuxd.get_devices().await?; let dev = &devices[0]; // 2. Create provider from discovered device let provider = UsbmuxdProvider { addr: UsbmuxdAddr::default(), tag: 0, udid: dev.udid.clone(), device_id: dev.device_id, label: "my-app".into(), }; // 3. Use provider transparently let lockdown = LockdownClient::connect(&provider).await?; ``` ``` -------------------------------- ### Typical UsbmuxdProvider Setup and Connection Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/provider.md Illustrates a common workflow: discovering a device via usbmuxd, creating a UsbmuxdProvider, and then connecting to the Lockdown service. ```rust use idevice::usbmuxd::UsbmuxdConnection; use idevice::provider::UsbmuxdProvider; use idevice::services::lockdown::LockdownClient; use idevice::IdeviceService; // 1. Discover device via usbmuxd let mut usbmuxd = UsbmuxdConnection::default().await?; let devices = usbmuxd.get_devices().await?; let dev = &devices[0]; // 2. Create provider from discovered device let provider = UsbmuxdProvider { addr: UsbmuxdAddr::default(), tag: 0, udid: dev.udid.clone(), device_id: dev.device_id, label: "my-app".into(), }; // 3. Use provider transparently let lockdown = LockdownClient::connect(&provider).await?; ``` -------------------------------- ### Production Cargo.toml Setup (Minimal) Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/configuration.md Optimized for production with essential features for specific services. ```toml [dependencies] idevice = { version = "0.1", features = ["usbmuxd", "afc", "lockdown"] } tokio = { version = "1", features = ["rt", "io-util", "net"] } ``` -------------------------------- ### Minimal Cargo.toml Setup Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/configuration.md Includes essential features for basic idevice functionality. ```toml [dependencies] idevice = { version = "0.1", features = ["tcp", "afc", "pair"] } tokio = { version = "1", features = ["full"] } ``` -------------------------------- ### Development Cargo.toml Setup Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/configuration.md Enables all features for comprehensive development and testing. ```toml [dependencies] idevice = { version = "0.1", features = ["full"] } tokio = { version = "1", features = ["full"] } tracing = "0.1" tracing-subscriber = "0.3" ``` -------------------------------- ### Start a Device Service Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/lockdown.md Initiates a specific service on the device and returns its connection port. Ensure you are in a secure session before calling this method. ```rust pub async fn start_service( &mut self, identifier: impl Into, ) -> Result<(u16, bool), IdeviceError> ``` ```rust let (port, needs_ssl) = lockdown.start_service("com.apple.afc").await?; println!("AFC available on port {}, SSL required: {}", port, needs_ssl); // Connect to the service on the returned port let service_conn = provider.connect(port).await?; if needs_ssl { service_conn.start_session(&pairing_file, legacy).await?; } ``` -------------------------------- ### Setting Project Paths Source: https://github.com/jkcoxson/idevice/blob/master/ffi/examples/CMakeLists.txt Defines variables for header files, static libraries, example directories, and runtime output. ```cmake set(HEADER_FILE ${CMAKE_SOURCE_DIR}/../idevice.h) set(STATIC_LIB ${CMAKE_SOURCE_DIR}/../../target/release/libidevice_ffi.a) set(EXAMPLES_DIR ${CMAKE_SOURCE_DIR}/../examples) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) ``` -------------------------------- ### Load Pairing File and Start Session Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/README.md Demonstrates loading a pairing file from disk and initiating a secure TLS session with the device, essential for authenticated communication. ```rust use idevice::pairing_file::PairingFile; // Load pairing file from disk let pairing = PairingFile::read_from_file("/path/to/pairing.plist")?; // Start TLS session with device idevice.start_session(&pairing, legacy).await?; ``` -------------------------------- ### UsbmuxdDevice Connection Type Example Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/usbmuxd.md Demonstrates how to match against the `Connection` enum to determine how an iOS device is connected. This is useful for conditional logic based on connection method. ```rust match device.connection_type { Connection::Usb => println!("Connected via USB"), Connection::Network(addr) => println!("Wi-Fi at {}", addr), Connection::Unknown(desc) => println!("Unknown: {}", desc), } ``` -------------------------------- ### start_service Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/lockdown.md Requests the device to start a specific service and returns the port where it is accessible. This method must be called within a secure session. ```APIDOC ## `start_service(identifier)` ### Description Requests the device to start a specific service and returns the port where it is accessible. Must be called in a secure session. ### Method `start_service` ### Parameters #### Path Parameters - **identifier** (`impl Into`) - Required - Service identifier (e.g., "com.apple.debugserver") ### Returns Tuple of `(port, requires_ssl)` where: - `port` - TCP port where service is available - `requires_ssl` - Whether the service connection requires TLS upgrade ### Errors - `IdeviceError::ServiceNotFound` - Device doesn't provide this service - `IdeviceError::UnexpectedResponse` - Response malformed ### Common Services - `com.apple.debugserver` - GDB server for debugging - `com.apple.afc` - Apple File Conduit (file system) - `com.apple.afc2` - Apple File Conduit (jailbreak-capable) - `com.apple.mobile.screenshotr` - Screenshot service - `com.apple.mobile.installation_proxy` - App management - `com.apple.mobile.notification_proxy` - Device notifications ### Example ```rust let (port, needs_ssl) = lockdown.start_service("com.apple.afc").await?; println!("AFC available on port {}, SSL required: {}", port, needs_ssl); // Connect to the service on the returned port let service_conn = provider.connect(port).await?; if needs_ssl { service_conn.start_session(&pairing_file, legacy).await?; } ``` ``` -------------------------------- ### Discover and Connect to Services Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/README.md Query the lockdown service to start specific device services like AFC or screenshotr, then establish connections to these services on their assigned ports. This requires prior session establishment. ```rust let mut lockdown = LockdownClient::connect(&provider).await?; let pairing = provider.get_pairing_file().await?; lockdown.start_session(&pairing).await?; // Start multiple services let (afc_port, afc_ssl) = lockdown.start_service("com.apple.afc").await?; let (shot_port, shot_ssl) = lockdown.start_service("com.apple.mobile.screenshotr").await?; // Connect to each let afc_conn = provider.connect(afc_port).await?; let shot_conn = provider.connect(shot_port).await?; ``` -------------------------------- ### Set Device Property using Plist Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/README.md Example of setting a device property, such as enabling Wi-Fi debugging, using the plist protocol. The library handles the serialization. ```rust use plist::Value; // Setting a device property lockdown.set_value( "EnableWifiDebugging", Value::Boolean(true), Some("com.apple.mobile.wireless_lockdown") ).await?; ``` -------------------------------- ### Read Device Property using Plist Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/README.md Example of reading a device property, like the product version, using the plist protocol. Demonstrates deserialization and type checking. ```rust // Reading a property let value = lockdown.get_value(Some("ProductVersion"), None).await?; if let Some(version) = value.as_string() { println!("iOS: {}", version); } ``` -------------------------------- ### Define Project Paths Source: https://github.com/jkcoxson/idevice/blob/master/cpp/examples/CMakeLists.txt Sets variables for various include and source directories, including C++ headers, Rust FFI headers, and example sources. ```cmake set(IDEVICE_CPP_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/../include) # public C++ headers set(IDEVICE_CPP_SRC_DIR ${CMAKE_SOURCE_DIR}/../src) # C++ .cpp files set(IDEVICE_FFI_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/../../ffi) # Rust FFI headers (idevice.h) set(PLIST_CPP_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/../plist_ffi/cpp/include) set(PLIST_CPP_SRC_DIR ${CMAKE_SOURCE_DIR}/../plist_ffi/cpp/src) if (MSVC) set(STATIC_LIB ${CMAKE_SOURCE_DIR}/../../target/release/idevice_ffi.lib) else() set(STATIC_LIB ${CMAKE_SOURCE_DIR}/../../target/release/libidevice_ffi.a) endif() set(EXAMPLES_DIR ${CMAKE_SOURCE_DIR}/../examples) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) ``` -------------------------------- ### Direct Manual Connection for Screenshotr Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/screenshotr.md Manually connect to the Screenshotr service by starting the service and then connecting to its port. This pattern is useful for more advanced scenarios or when direct control is needed. ```rust use idevice::services::screenshotr::ScreenshotService; // After setting up provider and lockdown... let mut lockdown = /* ... */; let (port, needs_ssl) = lockdown.start_service("com.apple.mobile.screenshotr").await?; let mut idevice = provider.connect(port).await?; if needs_ssl { idevice.start_session(&pairing_file, legacy).await?; } let mut screenshot_service = ScreenshotService::new(idevice); let data = screenshot_service.take_screenshot().await?; ``` -------------------------------- ### Start TLS Session with Pairing Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/idevice.md Initiates a secure TLS session using device pairing credentials. This is required for services that enforce encrypted communication. Provide the correct path to the pairing file and specify if legacy TLS settings are needed. ```rust let pairing_file = PairingFile::read_from_file("/path/to/pairing.plist")?; idevice.start_session(&pairing_file, false).await?; ``` -------------------------------- ### Explore Device File System with AFC Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/afc.md This Rust code snippet demonstrates how to use the AfcClient to interact with the device's file system. It shows how to get device information, list directory contents, read from a file, and write to a file. Ensure the idevice crate is imported and the async runtime is set up. ```rust use idevice::services::afc::AfcClient; async fn explore_device(mut afc: AfcClient) -> Result<(), Box> { // Get device info let dev_info = afc.get_device_info().await?; println!("Device: {}", dev_info.model); println!("Free space: {} MB", dev_info.free_bytes / (1024 * 1024)); // List home directory let contents = afc.list_dir("/var/mobile").await?; for entry in contents { let path = format!("/var/mobile/{}", entry); let info = afc.get_file_info(&path).await?; println!("{}: {} bytes ({})", entry, info.size, info.st_ifmt); } // Read a file let fd = afc.open_read("/var/mobile/Media/test.txt").await?; let mut content = Vec::new(); loop { let chunk = afc.read_file(fd.fd(), 4096).await?; if chunk.is_empty() { break; } content.extend_from_slice(&chunk); } // Write a file let fd = afc.open_write("/var/mobile/Media/output.txt").await?; afc.write_file(fd.fd(), b"Hello, iOS!").await?; Ok(()) } ``` -------------------------------- ### Enable Tracing in Rust Application Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/configuration.md Initialize the `tracing` subscriber in your `main` function to enable structured logging. This setup uses environment variables to control log levels. ```rust use tracing_subscriber::filter::EnvFilter; // In your main(): tracing_subscriber::fmt() .with_env_filter(EnvFilter::from_default_env()) .init(); ``` -------------------------------- ### Connect to Lockdown Service and Get Device Info (Rust) Source: https://github.com/jkcoxson/idevice/blob/master/README.md Enables the usbmuxd feature to connect to an iOS device via USB. It retrieves device information like product version and starts a session. Ensure usbmuxd is running and a device is connected. ```rust use idevice::{lockdown::LockdowndClient, IdeviceService}; use idevice::usbmuxd::{UsbmuxdAddr, UsbmuxdConnection}; #[tokio::main] async fn main() { // usbmuxd is Apple's daemon for connecting to devices over USB. // We'll ask usbmuxd for a device let mut usbmuxd = UsbmuxdConnection::default() .await .expect("Unable to connect to usbmuxd"); let devs = usbmuxd.get_devices().unwrap(); if devs.is_empty() { eprintln!("No devices connected!"); return; } // Create a provider to automatically create connections to the device. // Many services require opening multiple connections to get where you want. let provider = devs[0].to_provider(UsbmuxdAddr::from_env_var().unwrap(), 0, "example-program") // ``connect`` takes an object with the provider trait let mut lockdown_client = match LockdowndClient::connect(&provider).await { Ok(l) => l, Err(e) => { eprintln!("Unable to connect to lockdown: {e:?}"); return; } }; println!("{:?}", lockdown_client.get_value("ProductVersion").await); println!( "{:?}", lockdown_client .start_session( &provider .get_pairing_file() .await .expect("failed to get pairing file") ) .await ); println!("{:?}", lockdown_client.idevice.get_type().await.unwrap()); println!("{:#?}", lockdown_client.get_all_values().await); } ``` -------------------------------- ### Exclude Windows-Specific Examples Source: https://github.com/jkcoxson/idevice/blob/master/cpp/examples/CMakeLists.txt Removes specific example files from the list on Windows if they rely on POSIX-only APIs. ```cmake if (WIN32) # These examples rely on POSIX-only socket/filesystem APIs and don;t build with MSVC list(REMOVE_ITEM EXAMPLE_SOURCES ${EXAMPLES_DIR}/mobilebackup2.cpp ${EXAMPLES_DIR}/tunnel_app_service.cpp ) endif() ``` -------------------------------- ### Initialize ScreenshotService Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/screenshotr.md Creates a new `ScreenshotService` client. Requires a pre-established connection to the screenshotr service. ```rust use idevice::services::screenshotr::ScreenshotService; let screenshot_service = ScreenshotService::new(idevice); ``` -------------------------------- ### get_device(udid) Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/usbmuxd.md Gets a specific device by UDID. Returns the matching UsbmuxdDevice. ```APIDOC ## get_device(udid) ### Description Gets a specific device by UDID. ### Parameters #### Path Parameters - **udid** (`&str`) - Required - Device UDID to find ### Returns Matching `UsbmuxdDevice` ### Errors - `IdeviceError::DeviceNotFound` - No device with that UDID - Other errors from `get_devices()` ### Example ```rust let device = usbmuxd.get_device("00008030-000D12D80272402E").await?; ``` ``` -------------------------------- ### Instantiate UsbmuxdProvider Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/provider.md Demonstrates how to create an instance of UsbmuxdProvider with specific connection details. ```rust use idevice::provider::UsbmuxdProvider; use idevice::usbmuxd::UsbmuxdAddr; let provider = UsbmuxdProvider { addr: UsbmuxdAddr::default(), tag: 0, udid: "00008030-000D12D80272402E".into(), device_id: 42, label: "device-001".into(), }; ``` -------------------------------- ### Convenience Method to Create UsbmuxdProvider Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/provider.md Shows how to use a potential `to_provider()` method on `UsbmuxdDevice` for a more concise way to create a UsbmuxdProvider. ```rust // Convenience if implemented on UsbmuxdDevice let provider = device.to_provider(UsbmuxdAddr::default(), 0, "my-app")?; let lockdown = LockdownClient::connect(&provider).await?; ``` -------------------------------- ### Get Provider Label Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/provider.md Retrieves a human-readable string that identifies the specific connection provider being used. ```rust fn label(&self) -> &str ``` ```rust println!("Connected via: {}", provider.label()); ``` -------------------------------- ### Create Directory Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/afc.md Creates a new directory at the specified full path on the device. Ensure the parent directories exist. ```rust pub async fn mk_dir(&mut self, path: impl Into) -> Result<(), IdeviceError> af.mk_dir("/var/mobile/test").await?; ``` -------------------------------- ### UsbmuxdProvider Constructor Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/provider.md Demonstrates how to directly instantiate the UsbmuxdProvider struct with necessary device information. ```APIDOC ## UsbmuxdProvider Constructor ### Description Instantiate `UsbmuxdProvider` directly by providing the address of the usbmuxd service, a connection tag, the device's UDID, its assigned device ID, and a connection label. ### Fields * **addr** (`UsbmuxdAddr`) - Required - Address of usbmuxd service. * **tag** (`u32`) - Required - Connection tag (typically 0). * **udid** (`String`) - Required - Device UDID. * **device_id** (`u32`) - Required - Device ID assigned by usbmuxd. * **label** (`String`) - Required - Connection label. ### Example ```rust use idevice::provider::UsbmuxdProvider; use idevice::usbmuxd::UsbmuxdAddr; let provider = UsbmuxdProvider { addr: UsbmuxdAddr::default(), tag: 0, udid: "00008030-000D12D80272402E".into(), device_id: 42, label: "device-001".into(), }; ``` ``` -------------------------------- ### Get Device Information Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/afc.md Retrieves overall storage and filesystem details for the connected device. Useful for monitoring disk usage. ```rust pub async fn get_device_info(&mut self) -> Result let info = afc.get_device_info().await?; println!("Model: {}", info.model); println!("Total storage: {} bytes", info.total_bytes); println!("Free space: {} bytes", info.free_bytes); println!("Block size: {} bytes", info.block_size); let used = info.total_bytes - info.free_bytes; let percent = (used as f64 / info.total_bytes as f64) * 100.0; println!("Usage: {:.1}%", percent); ``` -------------------------------- ### Get File Information Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/afc.md Retrieves detailed metadata for a file or directory. Use this to check file size, modification date, and type. ```rust pub async fn get_file_info(&mut self, path: impl Into) -> Result let info = afc.get_file_info("/var/mobile/Media").await?; println!("Size: {} bytes", info.size); println!("Modified: {}", info.modified); println!("Type: {}", info.st_ifmt); ``` -------------------------------- ### Configure Usbmuxd Provider with Device Enumeration Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/configuration.md Configure a `UsbmuxdProvider` by first establishing a `UsbmuxdConnection` to enumerate available devices and then selecting one. ```rust // usbmuxd provider with device enumeration let mut usbmuxd = idevice::usbmuxd::UsbmuxdConnection::default().await?; let devices = usbmuxd.get_devices().await?; let dev = &devices[0]; let usb_provider = UsbmuxdProvider { addr: idevice::usbmuxd::UsbmuxdAddr::default(), tag: 0, udid: dev.udid.clone(), device_id: dev.device_id, label: dev.udid.clone(), }; ``` -------------------------------- ### UsbmuxdDevice toProvider Helper Method Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/provider.md Shows how to use a potential `to_provider()` convenience method on `UsbmuxdDevice` to create a `UsbmuxdProvider`. ```APIDOC ## UsbmuxdDevice toProvider Helper Method ### Description If the `UsbmuxdDevice` struct implements a `to_provider()` method, this provides a convenient way to create a `UsbmuxdProvider` instance directly from a discovered device object, simplifying the setup process. ### Usage Call the `to_provider()` method on a `UsbmuxdDevice` instance, providing the usbmuxd address, tag, and a connection label. ### Example ```rust // Convenience if implemented on UsbmuxdDevice let provider = device.to_provider(UsbmuxdAddr::default(), 0, "my-app")?; let lockdown = LockdownClient::connect(&provider).await?; ``` ``` -------------------------------- ### Get Device Type Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/idevice.md Queries the connected iOS device for its type (e.g., 'Device'). This method requires an active and established connection. ```rust let device_type = idevice.get_type().await?; println!("Device type: {}", device_type); ``` -------------------------------- ### Handling IDEvice Errors Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/README.md This example demonstrates how to match against the IdeviceError enum to handle specific device-related errors like ServiceNotFound, DeviceLocked, and DeveloperModeNotEnabled. ```rust match operation().await { Ok(result) => println!("Success"), Err(IdeviceError::ServiceNotFound) => println!("Service not available"), Err(IdeviceError::DeviceLocked) => println!("Device locked"), Err(IdeviceError::DeveloperModeNotEnabled) => println!("Enable Developer Mode"), Err(e) => eprintln!("Error: {}", e), } ``` -------------------------------- ### start_session Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/lockdown.md Initiates a secure TLS session with the device using pairing credentials. Must be called before accessing most services. Upgrades the underlying connection to TLS. ```APIDOC ## start_session(pairing_file) ### Description Initiates a secure TLS session with the device using pairing credentials. Must be called before accessing most services. Upgrades the underlying connection to TLS. ### Method `start_session` ### Parameters #### Path Parameters - **pairing_file** (`&PairingFile`) - Required - Device pairing credentials and certificates ### Response #### Success Response - `bool` - Indicating whether legacy (iOS < 5) TLS settings are required ### Errors - `IdeviceError::SessionInactive` - Device rejected session - `IdeviceError::Rustls(_)` or `IdeviceError::Openssl(_)` - TLS handshake failed - `IdeviceError::NoEstablishedConnection` - No connection available - `IdeviceError::UnexpectedResponse` - Unexpected response format ### Request Example ```rust use idevice::pairing_file::PairingFile; let pairing_file = PairingFile::read_from_file("/path/to/pairing.plist")?; let legacy = lockdown.start_session(&pairing_file).await?; if legacy { println!("Device is running legacy iOS version"); } ``` ``` -------------------------------- ### Release Build Profile Settings Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/configuration.md Recommended profile settings for release builds to optimize for size and performance. ```toml [profile.release] opt-level = "z" # Optimize for size codegen-units = 1 # Better optimization lto = true # Link-time optimization panic = "abort" # Smaller panic handling ``` -------------------------------- ### Get System BUID Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/usbmuxd.md Retrieve the System Build Unique Identifier (BUID) from the usbmuxd service. This identifier is unique to the system running usbmuxd. ```rust let buid = usbmuxd.get_buid().await?; println!("System BUID: {}", buid); ``` -------------------------------- ### Complete Device Connection Workflow with Usbmuxd Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/usbmuxd.md Demonstrates the full process of connecting to usbmuxd, retrieving device information, obtaining pairing records, and establishing a connection to an idevice. Ensure a device is connected before running. ```rust use idevice::usbmuxd::{UsbmuxdConnection, UsbmuxdAddr}; use idevice::services::lockdown::LockdownClient; use idevice::IdeviceService; #[tokio::main] async fn main() -> Result<(), Box> { // 1. Connect to usbmuxd let mut usbmuxd = UsbmuxdConnection::default().await?; // 2. Get connected devices let devices = usbmuxd.get_devices().await?; if devices.is_empty() { eprintln!("No devices connected!"); return Ok(()); } let device = &devices[0]; println!("Using device: {}", device.udid); // 3. Get pairing file from usbmuxd cache let pairing_file = usbmuxd.get_pair_record(&device.udid).await?; // 4. Connect to the device (consumes usbmuxd connection) let idevice = usbmuxd.connect_to_device( device.device_id, 62078, // Lockdown port "my-app" ).await?; // 5. Continue with standard service usage println!("Connected! Device type: {}", idevice.get_type().await?); Ok(()) } ``` -------------------------------- ### TcpProvider Usage Pattern with LockdownClient Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/provider.md Illustrates a common usage pattern for TcpProvider, showing how to establish a connection to a device using the provider and then interact with the Lockdown service to retrieve device information. ```rust use idevice::provider::TcpProvider; use idevice::services::lockdown::LockdownClient; use idevice::IdeviceService; let pairing_file = PairingFile::read_from_file("/path/to/pairing.plist")?; let provider = TcpProvider { addr: "192.168.1.100".parse()?, scope_id: None, pairing_file, label: "wifi-device".into(), }; // Use provider with any IdeviceService let lockdown = LockdownClient::connect(&provider).await?; let device_name = lockdown.get_value(Some("DeviceName"), None).await?; ``` -------------------------------- ### Manual TcpProvider Construction Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/provider.md Demonstrates how to manually construct a TcpProvider instance. This is useful for setting up a connection provider with specific network details and pairing information. ```rust let provider = TcpProvider { addr: "192.168.1.100".parse()?, scope_id: None, pairing_file: PairingFile::read_from_file("/path/to/pairing.plist")?, label: "my-device".into(), }; ``` -------------------------------- ### Get Specific Device by UDID Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/usbmuxd.md Retrieve details for a specific iOS device using its unique device identifier (UDID). Ensure the UDID is correctly formatted. ```rust let device = usbmuxd.get_device("00008030-000D12D80272402E").await?; ``` -------------------------------- ### Configure TCP Provider with Pairing File Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/configuration.md Set up a TCP provider with a hardcoded pairing file path. Ensure the pairing file exists at the specified location. ```rust use idevice::provider::{TcpProvider, UsbmuxdProvider}; use idevice::pairing_file::PairingFile; // TCP provider with hardcoded pairing file let pairing = PairingFile::read_from_file( std::path::Path::new("/path/to/pairing.plist") )?; let tcp_provider = TcpProvider { addr: "192.168.1.100".parse()?, scope_id: None, pairing_file: pairing, label: "my-device".into(), }; ``` -------------------------------- ### Create New LockdownClient Instance Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/lockdown.md Creates a new `LockdownClient` from an existing device connection. Ensure a pre-established connection to the lockdown service is provided. ```rust use idevice::services::lockdown::LockdownClient; let lockdown = LockdownClient::new(idevice); ``` -------------------------------- ### mk_dir(path) Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/afc.md Creates a new directory on the device. It takes the full path for the new directory as input. ```APIDOC ## mk_dir(path) ### Description Creates a new directory on the device. ### Method `mk_dir` ### Parameters #### Path Parameters - **path** (`impl Into`) - Required - Full path of the directory to create ### Returns - `Result<(), IdeviceError>` - Unit on success ### Errors - `IdeviceError::UnexpectedResponse` - Directory creation failed ### Example ```rust afc.mk_dir("/var/mobile/test").await?; ``` ``` -------------------------------- ### Lockdown Service Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/INDEX.md The `LockdownClient` provides device management capabilities, interacting with the `com.apple.mobile.lockdown` service. It allows retrieving and setting device properties, starting sessions, and discovering other services. ```APIDOC ## LockdownClient Struct ### Description Primary client for device management through the Lockdown service. ### Service - Name: `com.apple.mobile.lockdown` - Port: `62078` ### Methods - `LockdownClient::connect(provider)`: Connects to the device using a provided provider. - `LockdownClient::new(idevice)`: Creates a `LockdownClient` from an existing `Idevice` connection. - `get_value(key, domain)`: Retrieves a device property identified by `key` within an optional `domain`. - `set_value(key, value, domain)`: Sets a device property identified by `key` to `value` within an optional `domain`. - `start_session(pairing_file)`: Establishes a secure TLS session using pairing credentials. - `start_service(identifier)`: Discovers and starts a specified service on the device. - `pair(host_id, system_buid, host_name)`: Initiates the device pairing process (requires the `pair` feature). ### Constants - `LOCKDOWND_PORT = 62078` ``` -------------------------------- ### Complete IDEvice Configuration Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/README.md Use the 'full' feature set for maximum compatibility, enabling all services. ```toml idevice = { version = "0.1", features = ["full"] } ``` -------------------------------- ### Launch XCTest Runner (Bash) Source: https://github.com/jkcoxson/idevice/blob/master/README.md Launches an XCTest runner on a specified device using its UDID. This command is useful for starting WebDriverAgent-style runners on recent iOS versions. ```bash idevice-tools --udid xctest io.github.kor1k1.WebDriverAgentRunner.xctrunner ``` -------------------------------- ### Idevice::start_session Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/idevice.md Upgrades the connection to TLS using device pairing credentials. Must be called after establishing a connection to a service that requires encryption. ```APIDOC ## `start_session(pairing_file, legacy)` ### Description Upgrades the connection to TLS using device pairing credentials. Must be called after establishing a connection to a service that requires encryption. ### Signature ```rust pub async fn start_session( &mut self, pairing_file: &pairing_file::PairingFile, legacy: bool, ) -> Result<(), IdeviceError> ``` ### Parameters #### Path Parameters - **pairing_file** (&PairingFile) - Required - Device's pairing credentials and certificates - **legacy** (bool) - Required - Whether the device uses legacy (iOS < 5) TLS settings ### Returns Unit on success ### Errors - `IdeviceError::Rustls(_)` or `IdeviceError::Openssl(_)` - TLS handshake failed - Various crypto-related errors - Invalid pairing file - `IdeviceError::NoEstablishedConnection` - No socket available ### Example ```rust let pairing_file = PairingFile::read_from_file("/path/to/pairing.plist")?; idevice.start_session(&pairing_file, false).await?; ``` ``` -------------------------------- ### listen() Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/usbmuxd.md Returns a stream of device connection/disconnection events. Streams are created on demand. ```APIDOC ## listen() ### Description Returns a stream of device connection/disconnection events. Streams are created on demand. ### Returns Stream of `UsbmuxdListenEvent` ### Example ```rust use futures::stream::StreamExt; let mut usbmuxd = UsbmuxdConnection::default().await?; let mut listener = usbmuxd.listen(); while let Some(result) = listener.next().await { match result? { UsbmuxdListenEvent::Connected(dev) => { println!("Device connected: {}", dev.udid); } UsbmuxdListenEvent::Disconnected(mux_id) => { println!("Device disconnected (mux_id: {})", mux_id); } } } ``` ``` -------------------------------- ### Get Device Property Value Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/lockdown.md Retrieves a specific property from the device. Both key and domain are optional. Use this to read device information like name or iOS version. ```rust let device_name = lockdown.get_value(Some("DeviceName"), None).await?; println!("Device: {:?}", device_name); let product_version = lockdown.get_value(Some("ProductVersion"), None).await?; if let Some(version_str) = product_version.as_string() { println!("iOS: {}", version_str); } // WiFi debugging property in specific domain let wifi_debug = lockdown.get_value( Some("EnableWifiDebugging"), Some("com.apple.mobile.wireless_lockdown") ).await?; ``` -------------------------------- ### Build the C++ Wrapper Library Source: https://github.com/jkcoxson/idevice/blob/master/cpp/examples/CMakeLists.txt Creates a static library named 'idevice_cpp' from the collected C++ source files. ```cmake add_library(idevice_cpp STATIC ${IDEVICE_CPP_SOURCES} ${PLIST_CPP_SOURCES}) ``` -------------------------------- ### Get Cached Device UDID Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/idevice.md Retrieves the UDID that was previously set using `set_udid`. Returns an `Option<&str>` which is `Some` if a UDID is cached, and `None` otherwise. This is a synchronous operation. ```rust pub fn udid(&self) -> Option<&str> ``` ```rust if let Some(udid) = idevice.udid() { println!("Device UDID: {}", udid); } ``` -------------------------------- ### Start Secure Lockdown Session Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/lockdown.md Initiates a secure TLS session with the device using pairing credentials. This must be called before accessing most services. It upgrades the underlying connection to TLS. ```rust use idevice::pairing_file::PairingFile; let pairing_file = PairingFile::read_from_file("/path/to/pairing.plist")?; let legacy = lockdown.start_session(&pairing_file).await?; if legacy { println!("Device is running legacy iOS version"); } ``` -------------------------------- ### Basic Device Connection Workflow Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/README.md Connect to an iOS device using usbmuxd, establish a lockdown session, and retrieve device properties. Requires device to be connected and discoverable by usbmuxd. ```rust use idevice::services::lockdown::LockdownClient; use idevice::provider::UsbmuxdProvider; use idevice::usbmuxd::{UsbmuxdConnection, UsbmuxdAddr}; use idevice::IdeviceService; #[tokio::main] async fn main() -> Result<(), Box> { // 1. Discover device via usbmuxd let mut usbmuxd = UsbmuxdConnection::default().await?; let devices = usbmuxd.get_devices().await?; if devices.is_empty() { eprintln!("No devices connected"); return Ok(()) } let device = &devices[0]; println!("Device: {}", device.udid); // 2. Create provider let provider = UsbmuxdProvider { addr: UsbmuxdAddr::default(), tag: 0, udid: device.udid.clone(), device_id: device.device_id, label: "my-app".into(), }; // 3. Connect to lockdown service let mut lockdown = LockdownClient::connect(&provider).await?; // 4. Establish secure session let pairing_file = provider.get_pairing_file().await?; lockdown.start_session(&pairing_file).await?; // 5. Access device properties let device_name = lockdown.get_value(Some("DeviceName"), None).await?; println!("Device name: {:?}", device_name); Ok(()) } ``` -------------------------------- ### AfcClient::new_afc2 Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/afc.md Creates a new AFC2 client directly from a provider, handling all connection setup internally. AFC2 is aware of jailbreak modifications and can access jailbroken file systems. ```APIDOC ## AfcClient::new_afc2 ### Description Creates a new AFC2 client directly from a provider, handling all connection setup internally. AFC2 is aware of jailbreak modifications and can access jailbroken file systems. ### Method `new_afc2` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```rust let afc = AfcClient::new_afc2(&provider).await?; let files = afc.list_dir("/").await?; ``` ### Response #### Success Response Connected `AfcClient` configured for AFC2. #### Response Example ```rust // AfcClient instance ``` ### Errors - `IdeviceError::Socket(_)` - Connection failed - `IdeviceError::ServiceNotFound` - Device doesn't provide AFC2 ``` -------------------------------- ### Enable Tracing for Debugging Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/errors.md Integrate the tracing crate to enable detailed logging of protocol interactions and error conditions. This setup should be called early in your application's main function. ```rust use tracing_subscriber; // In main: tracing_subscriber::fmt().with_max_level(tracing::Level::DEBUG).init(); ``` -------------------------------- ### connect_to_device(device_id, port, label) Source: https://github.com/jkcoxson/idevice/blob/master/_autodocs/api-reference/usbmuxd.md Establishes a connection to a specific port on a device. Consumes the UsbmuxdConnection and returns a connected Idevice instance. ```APIDOC ## connect_to_device(device_id, port, label) ### Description Establishes a connection to a specific port on a device. Consumes the `UsbmuxdConnection`. ### Parameters #### Path Parameters - **device_id** (`u32`) - Required - Device ID from usbmuxd device list - **port** (`u16`) - Required - Device port in host byte order - **label** (`impl Into`) - Required - Connection label for identification ### Returns Connected `Idevice` instance ### Errors - `IdeviceError::Usbmuxd(UsbmuxdError::BadCommand)` - Invalid command - `IdeviceError::Usbmuxd(UsbmuxdError::BadDevice)` - Invalid device ID - `IdeviceError::Usbmuxd(UsbmuxdError::ConnectionRefused)` - Device rejected connection - `IdeviceError::Socket(_)` - Communication error ### Example ```rust let usbmuxd = UsbmuxdConnection::default().await?; let devices = usbmuxd.get_devices().await?; let dev = &devices[0]; // Connect to lockdown service on port 62078 let idevice = usbmuxd.connect_to_device(dev.device_id, 62078, "lockdown").await?; ``` ```