blob: 2a125aa1832d023bab6ce388d8ee9c825ed62309 [file] [log] [blame]
cdef class BaseError(Exception):
def __cinit__(self, int16_t errcode):
self._c_errcode = errcode
def __nonzero__(self):
return self._c_errcode != 0
property message:
def __get__(self):
if self._c_errcode in self._lookup_table:
return self._lookup_table[self._c_errcode]
else:
return "Unknown error ({0})".format(self._c_errcode)
property code:
def __get__(self):
return self._c_errcode
def __str__(self):
return '%s (%s)' % (self.message, self.code)
def __repr__(self):
return self.__str__()
cdef class Base:
cdef inline int handle_error(self, int16_t ret) except -1:
if ret == 0:
return 0
cdef BaseError err = self._error(ret)
raise err
cdef BaseError _error(self, int16_t ret): pass
cdef extern from "libimobiledevice/libimobiledevice.h":
ctypedef enum idevice_error_t:
IDEVICE_E_SUCCESS = 0
IDEVICE_E_INVALID_ARG = -1
IDEVICE_E_UNKNOWN_ERROR = -2
IDEVICE_E_NO_DEVICE = -3
IDEVICE_E_NOT_ENOUGH_DATA = -4
IDEVICE_E_SSL_ERROR = -6
IDEVICE_E_TIMEOUT = -7
cdef enum idevice_options:
IDEVICE_LOOKUP_USBMUX = 1 << 1
IDEVICE_LOOKUP_NETWORK = 1 << 2
IDEVICE_LOOKUP_PREFER_NETWORK = 1 << 3
ctypedef void (*idevice_event_cb_t) (const_idevice_event_t event, void *user_data)
cdef extern idevice_error_t idevice_event_subscribe(idevice_event_cb_t callback, void *user_data)
cdef extern idevice_error_t idevice_event_unsubscribe()
idevice_error_t idevice_get_device_list(char ***devices, int *count)
idevice_error_t idevice_device_list_free(char **devices)
void idevice_set_debug_level(int level)
idevice_error_t idevice_new(idevice_t *device, char *udid)
idevice_error_t idevice_new_with_options(idevice_t *device, const char *udid, idevice_options options);
idevice_error_t idevice_free(idevice_t device)
idevice_error_t idevice_get_udid(idevice_t device, char** udid)
idevice_error_t idevice_get_handle(idevice_t device, uint32_t *handle)
idevice_error_t idevice_connect(idevice_t device, uint16_t port, idevice_connection_t *connection)
idevice_error_t idevice_disconnect(idevice_connection_t connection)
idevice_error_t idevice_connection_send(idevice_connection_t connection, char *data, uint32_t len, uint32_t *sent_bytes)
idevice_error_t idevice_connection_receive_timeout(idevice_connection_t connection, char *data, uint32_t len, uint32_t *recv_bytes, unsigned int timeout)
idevice_error_t idevice_connection_receive(idevice_connection_t connection, char *data, uint32_t len, uint32_t *recv_bytes)
cdef class iDeviceError(BaseError):
def __init__(self, *args, **kwargs):
self._lookup_table = {
IDEVICE_E_SUCCESS: 'Success',
IDEVICE_E_INVALID_ARG: 'Invalid argument',
IDEVICE_E_UNKNOWN_ERROR: 'Unknown error',
IDEVICE_E_NO_DEVICE: 'No device',
IDEVICE_E_NOT_ENOUGH_DATA: 'Not enough data',
IDEVICE_E_SSL_ERROR: 'SSL Error',
IDEVICE_E_TIMEOUT: 'Connection timeout'
}
BaseError.__init__(self, *args, **kwargs)
def set_debug_level(int level):
idevice_set_debug_level(level)
cdef class iDeviceEvent:
def __init__(self, *args, **kwargs):
raise TypeError("iDeviceEvent cannot be instantiated")
def __str__(self):
return 'iDeviceEvent: %s (%s)' % (self.event == IDEVICE_DEVICE_ADD and 'Add' or 'Remove', self.udid)
property event:
def __get__(self):
return self._c_event.event
property udid:
def __get__(self):
return self._c_event.udid
property conn_type:
def __get__(self):
return self._c_event.conn_type
cdef void idevice_event_cb(const_idevice_event_t c_event, void *user_data) with gil:
cdef iDeviceEvent event = iDeviceEvent.__new__(iDeviceEvent)
event._c_event = c_event
(<object>user_data)(event)
def event_subscribe(object callback):
cdef iDeviceError err = iDeviceError(idevice_event_subscribe(idevice_event_cb, <void*>callback))
if err: raise err
def event_unsubscribe():
cdef iDeviceError err = iDeviceError(idevice_event_unsubscribe())
if err: raise err
def get_device_list():
cdef:
char** devices = NULL
int count
list result
bytes device
iDeviceError err = iDeviceError(idevice_get_device_list(&devices, &count))
if err:
if devices != NULL:
idevice_device_list_free(devices)
raise err
result = []
for i from 0 <= i < count:
device = devices[i]
result.append(device)
err = iDeviceError(idevice_device_list_free(devices))
if err: raise err
return result
cdef class iDeviceConnection(Base):
def __init__(self, *args, **kwargs):
raise TypeError("iDeviceConnection cannot be instantiated. Please use iDevice.connect()")
cpdef bytes receive_timeout(self, uint32_t max_len, unsigned int timeout):
cdef:
uint32_t bytes_received
char* c_data = <char *>malloc(max_len)
bytes result
try:
self.handle_error(idevice_connection_receive_timeout(self._c_connection, c_data, max_len, &bytes_received, timeout))
result = c_data[:bytes_received]
return result
except BaseError, e:
raise
finally:
free(c_data)
cpdef bytes receive(self, max_len):
cdef:
uint32_t bytes_received
char* c_data = <char *>malloc(max_len)
bytes result
try:
self.handle_error(idevice_connection_receive(self._c_connection, c_data, max_len, &bytes_received))
result = c_data[:bytes_received]
return result
except BaseError, e:
raise
finally:
free(c_data)
cpdef disconnect(self):
cdef idevice_error_t err
err = idevice_disconnect(self._c_connection)
self.handle_error(err)
cdef BaseError _error(self, int16_t ret):
return iDeviceError(ret)
from libc.stdlib cimport *
cdef class iDevice(Base):
def __cinit__(self, object udid=None, *args, **kwargs):
cdef char* c_udid = NULL
if isinstance(udid, (str, bytes)):
c_udid = <bytes>udid
elif udid is not None:
raise TypeError("iDevice's constructor takes a string or None as the udid argument")
self.handle_error(idevice_new(&self._c_dev, c_udid))
def __dealloc__(self):
if self._c_dev is not NULL:
self.handle_error(idevice_free(self._c_dev))
cdef BaseError _error(self, int16_t ret):
return iDeviceError(ret)
cpdef iDeviceConnection connect(self, uint16_t port):
cdef:
idevice_error_t err
idevice_connection_t c_conn = NULL
iDeviceConnection conn
err = idevice_connect(self._c_dev, port, &c_conn)
try:
self.handle_error(err)
conn = iDeviceConnection.__new__(iDeviceConnection)
conn._c_connection = c_conn
return conn
except Exception, e:
if c_conn != NULL:
idevice_disconnect(c_conn)
property udid:
def __get__(self):
cdef:
char* udid
idevice_error_t err
err = idevice_get_udid(self._c_dev, &udid)
try:
self.handle_error(err)
return udid
except Exception, e:
if udid != NULL:
free(udid)
property handle:
def __get__(self):
cdef uint32_t handle
self.handle_error(idevice_get_handle(self._c_dev, &handle))
return handle
cdef extern from *:
ctypedef char* const_char_ptr "const char*"
cdef class BaseService(Base):
__service_name__ = None
cdef class PropertyListService(BaseService):
cpdef send(self, plist.Node node):
self.handle_error(self._send(node._c_node))
cpdef object receive(self):
cdef:
plist.plist_t c_node = NULL
int16_t err
err = self._receive(&c_node)
try:
self.handle_error(err)
return plist.plist_t_to_node(c_node)
except BaseError, e:
if c_node != NULL:
plist.plist_free(c_node)
raise
cpdef object receive_with_timeout(self, int timeout_ms):
cdef:
plist.plist_t c_node = NULL
int16_t err
err = self._receive_with_timeout(&c_node, timeout_ms)
try:
self.handle_error(err)
return plist.plist_t_to_node(c_node)
except BaseError, e:
if c_node != NULL:
plist.plist_free(c_node)
raise
cdef int16_t _send(self, plist.plist_t node):
raise NotImplementedError("send is not implemented")
cdef int16_t _receive(self, plist.plist_t* c_node):
raise NotImplementedError("receive is not implemented")
cdef int16_t _receive_with_timeout(self, plist.plist_t* c_node, int timeout_ms):
raise NotImplementedError("receive_with_timeout is not implemented")
cdef class DeviceLinkService(PropertyListService):
pass
include "lockdown.pxi"
include "mobilesync.pxi"
include "notification_proxy.pxi"
include "sbservices.pxi"
include "mobilebackup.pxi"
include "mobilebackup2.pxi"
include "afc.pxi"
include "file_relay.pxi"
include "screenshotr.pxi"
include "installation_proxy.pxi"
include "mobile_image_mounter.pxi"
include "webinspector.pxi"
include "heartbeat.pxi"
include "diagnostics_relay.pxi"
include "misagent.pxi"
include "house_arrest.pxi"
include "restore.pxi"
include "debugserver.pxi"