mirror of
https://github.com/jkcoxson/idevice.git
synced 2026-03-02 06:26:15 +01:00
Add missing usbmuxd FFI methods
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
use std::{
|
||||
ffi::{CStr, CString, c_char},
|
||||
pin::Pin,
|
||||
ptr::null_mut,
|
||||
};
|
||||
|
||||
@@ -9,15 +10,19 @@ use crate::{
|
||||
IdeviceFfiError, IdeviceHandle, IdevicePairingFile, RUNTIME, ffi_err,
|
||||
util::{SockAddr, c_socket_to_rust, idevice_sockaddr, idevice_socklen_t},
|
||||
};
|
||||
use futures::{Stream, StreamExt};
|
||||
use idevice::{
|
||||
IdeviceError,
|
||||
usbmuxd::{UsbmuxdAddr, UsbmuxdConnection, UsbmuxdDevice},
|
||||
usbmuxd::{UsbmuxdAddr, UsbmuxdConnection, UsbmuxdDevice, UsbmuxdListenEvent},
|
||||
};
|
||||
use log::error;
|
||||
|
||||
pub struct UsbmuxdConnectionHandle(pub UsbmuxdConnection);
|
||||
pub struct UsbmuxdAddrHandle(pub UsbmuxdAddr);
|
||||
pub struct UsbmuxdDeviceHandle(pub UsbmuxdDevice);
|
||||
pub struct UsbmuxdListenerHandle<'a>(
|
||||
Pin<Box<dyn Stream<Item = Result<UsbmuxdListenEvent, IdeviceError>> + 'a>>,
|
||||
);
|
||||
|
||||
/// Connects to a usbmuxd instance over TCP
|
||||
///
|
||||
@@ -301,6 +306,153 @@ pub unsafe extern "C" fn idevice_usbmuxd_get_pair_record(
|
||||
}
|
||||
}
|
||||
|
||||
/// Saves the pairing record for a given device UDID.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `usbmuxd_conn` - A valid connection to usbmuxd.
|
||||
/// * `device_id` - The muxer ID for the device
|
||||
/// * `udid` - The UDID of the device.
|
||||
/// * `pair_record` - The bytes of the pairing record plist to save
|
||||
/// * `pair_record_len` - the length of the pairing record bytes
|
||||
///
|
||||
/// # Returns
|
||||
/// An `IdeviceFfiError` on error, `null` on success.
|
||||
///
|
||||
/// # Safety
|
||||
/// * `usbmuxd_conn` must be a valid pointer.
|
||||
/// * `udid` must be a valid, null-terminated C string.
|
||||
/// * `pair_record` must be a valid, non-null pointer.
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn idevice_usbmuxd_save_pair_record(
|
||||
usbmuxd_conn: *mut UsbmuxdConnectionHandle,
|
||||
device_id: u32,
|
||||
udid: *const c_char,
|
||||
pair_record: *mut u8,
|
||||
pair_record_len: usize,
|
||||
) -> *mut IdeviceFfiError {
|
||||
if usbmuxd_conn.is_null() || pair_record.is_null() {
|
||||
return ffi_err!(IdeviceError::FfiInvalidArg);
|
||||
}
|
||||
let conn = unsafe { &mut (*usbmuxd_conn).0 };
|
||||
let pair_record =
|
||||
unsafe { std::slice::from_raw_parts_mut(pair_record, pair_record_len) }.to_vec();
|
||||
|
||||
let udid_str = unsafe {
|
||||
match CStr::from_ptr(udid).to_str() {
|
||||
Ok(s) => s,
|
||||
Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg),
|
||||
}
|
||||
};
|
||||
|
||||
let res = RUNTIME.block_on(async {
|
||||
conn.save_pair_record(device_id, udid_str, pair_record)
|
||||
.await
|
||||
});
|
||||
|
||||
match res {
|
||||
Ok(_) => null_mut(),
|
||||
Err(e) => ffi_err!(e),
|
||||
}
|
||||
}
|
||||
|
||||
/// Listens on the socket for connections and disconnections
|
||||
///
|
||||
/// # Safety
|
||||
/// Pass valid pointers. Free the stream with ``idevice_usbmuxd_listener_handle_free``.
|
||||
/// The stream must outlive the usbmuxd connection, and the usbmuxd connection cannot
|
||||
/// be used for other requests.
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn idevice_usbmuxd_listen(
|
||||
usbmuxd_conn: *mut UsbmuxdConnectionHandle,
|
||||
stream_handle: *mut *mut UsbmuxdListenerHandle,
|
||||
) -> *mut IdeviceFfiError {
|
||||
if usbmuxd_conn.is_null() || stream_handle.is_null() {
|
||||
return ffi_err!(IdeviceError::FfiInvalidArg);
|
||||
}
|
||||
let conn = unsafe { &mut (*usbmuxd_conn).0 };
|
||||
|
||||
let res = RUNTIME.block_on(async { conn.listen().await });
|
||||
|
||||
match res {
|
||||
Ok(s) => {
|
||||
unsafe { *stream_handle = Box::into_raw(Box::new(UsbmuxdListenerHandle(s))) };
|
||||
null_mut()
|
||||
}
|
||||
Err(e) => ffi_err!(e),
|
||||
}
|
||||
}
|
||||
|
||||
/// Frees a stream created by ``listen`` or does nothing on null
|
||||
///
|
||||
/// # Safety
|
||||
/// Pass a valid pointer.
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn idevice_usbmuxd_listener_handle_free(
|
||||
stream_handle: *mut UsbmuxdListenerHandle,
|
||||
) {
|
||||
if stream_handle.is_null() {
|
||||
return;
|
||||
}
|
||||
let _ = unsafe { Box::from_raw(stream_handle) };
|
||||
}
|
||||
|
||||
/// Gets the next event from the stream.
|
||||
/// Connect will be set to true if the event is a connection event,
|
||||
/// and the connection_device will be filled with the device information.
|
||||
/// If connection is false, the mux ID of the device will be filled.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `stream_handle` - The handle to the stream returned by listen
|
||||
/// * `connect` - The bool that will be set
|
||||
/// * `connection_device` - The pointer that will be filled on a connect event
|
||||
/// * `disconnection_id` - The mux ID that will be set on a disconnect event
|
||||
///
|
||||
/// # Safety
|
||||
/// Pass valid pointers
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn idevice_usbmuxd_listener_next(
|
||||
stream_handle: *mut UsbmuxdListenerHandle,
|
||||
connect: *mut bool,
|
||||
connection_device: *mut *mut UsbmuxdDeviceHandle,
|
||||
disconnection_id: *mut u32,
|
||||
) -> *mut IdeviceFfiError {
|
||||
if stream_handle.is_null()
|
||||
|| connect.is_null()
|
||||
|| connection_device.is_null()
|
||||
|| disconnection_id.is_null()
|
||||
{
|
||||
return ffi_err!(IdeviceError::FfiInvalidArg);
|
||||
}
|
||||
let stream = unsafe { &mut (*stream_handle).0 };
|
||||
|
||||
let res = RUNTIME.block_on(async { stream.next().await });
|
||||
|
||||
match res {
|
||||
Some(res) => match res {
|
||||
Ok(s) => {
|
||||
match s {
|
||||
UsbmuxdListenEvent::Connected(usbmuxd_device) => {
|
||||
unsafe { *connect = true };
|
||||
unsafe {
|
||||
*connection_device =
|
||||
Box::into_raw(Box::new(UsbmuxdDeviceHandle(usbmuxd_device)))
|
||||
};
|
||||
}
|
||||
UsbmuxdListenEvent::Disconnected(id) => unsafe { *disconnection_id = id },
|
||||
}
|
||||
null_mut()
|
||||
}
|
||||
Err(e) => ffi_err!(e),
|
||||
},
|
||||
None => {
|
||||
ffi_err!(IdeviceError::Socket(std::io::Error::new(
|
||||
std::io::ErrorKind::BrokenPipe,
|
||||
"end of stream"
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Reads the BUID (Boot-Unique ID) from usbmuxd.
|
||||
///
|
||||
/// The returned string must be freed with `idevice_string_free`.
|
||||
|
||||
Reference in New Issue
Block a user