summaryrefslogtreecommitdiffstats
path: root/cython/imobiledevice.pyx
diff options
context:
space:
mode:
Diffstat (limited to 'cython/imobiledevice.pyx')
-rw-r--r--cython/imobiledevice.pyx294
1 files changed, 294 insertions, 0 deletions
diff --git a/cython/imobiledevice.pyx b/cython/imobiledevice.pyx
new file mode 100644
index 0000000..8da2296
--- /dev/null
+++ b/cython/imobiledevice.pyx
@@ -0,0 +1,294 @@
+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) noexcept:
+ 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"