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 @@
1cdef class BaseError(Exception):
2 def __cinit__(self, int16_t errcode):
3 self._c_errcode = errcode
4
5 def __nonzero__(self):
6 return self._c_errcode != 0
7
8 property message:
9 def __get__(self):
10 if self._c_errcode in self._lookup_table:
11 return self._lookup_table[self._c_errcode]
12 else:
13 return "Unknown error ({0})".format(self._c_errcode)
14
15 property code:
16 def __get__(self):
17 return self._c_errcode
18
19 def __str__(self):
20 return '%s (%s)' % (self.message, self.code)
21
22 def __repr__(self):
23 return self.__str__()
24
25cdef class Base:
26 cdef inline int handle_error(self, int16_t ret) except -1:
27 if ret == 0:
28 return 0
29 cdef BaseError err = self._error(ret)
30 raise err
31
32 cdef BaseError _error(self, int16_t ret): pass
33
34cdef extern from "libimobiledevice/libimobiledevice.h":
35 ctypedef enum idevice_error_t:
36 IDEVICE_E_SUCCESS = 0
37 IDEVICE_E_INVALID_ARG = -1
38 IDEVICE_E_UNKNOWN_ERROR = -2
39 IDEVICE_E_NO_DEVICE = -3
40 IDEVICE_E_NOT_ENOUGH_DATA = -4
41 IDEVICE_E_SSL_ERROR = -6
42 IDEVICE_E_TIMEOUT = -7
43 cdef enum idevice_options:
44 IDEVICE_LOOKUP_USBMUX = 1 << 1
45 IDEVICE_LOOKUP_NETWORK = 1 << 2
46 IDEVICE_LOOKUP_PREFER_NETWORK = 1 << 3
47 ctypedef void (*idevice_event_cb_t) (const_idevice_event_t event, void *user_data)
48 cdef extern idevice_error_t idevice_event_subscribe(idevice_event_cb_t callback, void *user_data)
49 cdef extern idevice_error_t idevice_event_unsubscribe()
50 idevice_error_t idevice_get_device_list(char ***devices, int *count)
51 idevice_error_t idevice_device_list_free(char **devices)
52 void idevice_set_debug_level(int level)
53 idevice_error_t idevice_new(idevice_t *device, char *udid)
54 idevice_error_t idevice_new_with_options(idevice_t *device, const char *udid, idevice_options options);
55 idevice_error_t idevice_free(idevice_t device)
56 idevice_error_t idevice_get_udid(idevice_t device, char** udid)
57 idevice_error_t idevice_get_handle(idevice_t device, uint32_t *handle)
58 idevice_error_t idevice_connect(idevice_t device, uint16_t port, idevice_connection_t *connection)
59 idevice_error_t idevice_disconnect(idevice_connection_t connection)
60 idevice_error_t idevice_connection_send(idevice_connection_t connection, char *data, uint32_t len, uint32_t *sent_bytes)
61 idevice_error_t idevice_connection_receive_timeout(idevice_connection_t connection, char *data, uint32_t len, uint32_t *recv_bytes, unsigned int timeout)
62 idevice_error_t idevice_connection_receive(idevice_connection_t connection, char *data, uint32_t len, uint32_t *recv_bytes)
63
64cdef class iDeviceError(BaseError):
65 def __init__(self, *args, **kwargs):
66 self._lookup_table = {
67 IDEVICE_E_SUCCESS: 'Success',
68 IDEVICE_E_INVALID_ARG: 'Invalid argument',
69 IDEVICE_E_UNKNOWN_ERROR: 'Unknown error',
70 IDEVICE_E_NO_DEVICE: 'No device',
71 IDEVICE_E_NOT_ENOUGH_DATA: 'Not enough data',
72 IDEVICE_E_SSL_ERROR: 'SSL Error',
73 IDEVICE_E_TIMEOUT: 'Connection timeout'
74 }
75 BaseError.__init__(self, *args, **kwargs)
76
77def set_debug_level(int level):
78 idevice_set_debug_level(level)
79
80cdef class iDeviceEvent:
81 def __init__(self, *args, **kwargs):
82 raise TypeError("iDeviceEvent cannot be instantiated")
83
84 def __str__(self):
85 return 'iDeviceEvent: %s (%s)' % (self.event == IDEVICE_DEVICE_ADD and 'Add' or 'Remove', self.udid)
86
87 property event:
88 def __get__(self):
89 return self._c_event.event
90 property udid:
91 def __get__(self):
92 return self._c_event.udid
93 property conn_type:
94 def __get__(self):
95 return self._c_event.conn_type
96
97cdef void idevice_event_cb(const_idevice_event_t c_event, void *user_data) noexcept:
98 cdef iDeviceEvent event = iDeviceEvent.__new__(iDeviceEvent)
99 event._c_event = c_event
100 (<object>user_data)(event)
101
102def event_subscribe(object callback):
103 cdef iDeviceError err = iDeviceError(idevice_event_subscribe(idevice_event_cb, <void*>callback))
104 if err: raise err
105
106def event_unsubscribe():
107 cdef iDeviceError err = iDeviceError(idevice_event_unsubscribe())
108 if err: raise err
109
110def get_device_list():
111 cdef:
112 char** devices = NULL
113 int count
114 list result
115 bytes device
116 iDeviceError err = iDeviceError(idevice_get_device_list(&devices, &count))
117
118 if err:
119 if devices != NULL:
120 idevice_device_list_free(devices)
121 raise err
122
123 result = []
124 for i from 0 <= i < count:
125 device = devices[i]
126 result.append(device)
127
128 err = iDeviceError(idevice_device_list_free(devices))
129 if err: raise err
130 return result
131
132cdef class iDeviceConnection(Base):
133 def __init__(self, *args, **kwargs):
134 raise TypeError("iDeviceConnection cannot be instantiated. Please use iDevice.connect()")
135
136 cpdef bytes receive_timeout(self, uint32_t max_len, unsigned int timeout):
137 cdef:
138 uint32_t bytes_received
139 char* c_data = <char *>malloc(max_len)
140 bytes result
141
142 try:
143 self.handle_error(idevice_connection_receive_timeout(self._c_connection, c_data, max_len, &bytes_received, timeout))
144 result = c_data[:bytes_received]
145 return result
146 except BaseError, e:
147 raise
148 finally:
149 free(c_data)
150
151 cpdef bytes receive(self, max_len):
152 cdef:
153 uint32_t bytes_received
154 char* c_data = <char *>malloc(max_len)
155 bytes result
156
157 try:
158 self.handle_error(idevice_connection_receive(self._c_connection, c_data, max_len, &bytes_received))
159 result = c_data[:bytes_received]
160 return result
161 except BaseError, e:
162 raise
163 finally:
164 free(c_data)
165
166 cpdef disconnect(self):
167 cdef idevice_error_t err
168 err = idevice_disconnect(self._c_connection)
169 self.handle_error(err)
170
171 cdef BaseError _error(self, int16_t ret):
172 return iDeviceError(ret)
173
174from libc.stdlib cimport *
175
176cdef class iDevice(Base):
177 def __cinit__(self, object udid=None, *args, **kwargs):
178 cdef char* c_udid = NULL
179 if isinstance(udid, (str, bytes)):
180 c_udid = <bytes>udid
181 elif udid is not None:
182 raise TypeError("iDevice's constructor takes a string or None as the udid argument")
183 self.handle_error(idevice_new(&self._c_dev, c_udid))
184
185 def __dealloc__(self):
186 if self._c_dev is not NULL:
187 self.handle_error(idevice_free(self._c_dev))
188
189 cdef BaseError _error(self, int16_t ret):
190 return iDeviceError(ret)
191
192 cpdef iDeviceConnection connect(self, uint16_t port):
193 cdef:
194 idevice_error_t err
195 idevice_connection_t c_conn = NULL
196 iDeviceConnection conn
197 err = idevice_connect(self._c_dev, port, &c_conn)
198 try:
199 self.handle_error(err)
200
201 conn = iDeviceConnection.__new__(iDeviceConnection)
202 conn._c_connection = c_conn
203
204 return conn
205 except Exception, e:
206 if c_conn != NULL:
207 idevice_disconnect(c_conn)
208
209 property udid:
210 def __get__(self):
211 cdef:
212 char* udid
213 idevice_error_t err
214 err = idevice_get_udid(self._c_dev, &udid)
215 try:
216 self.handle_error(err)
217 return udid
218 except Exception, e:
219 if udid != NULL:
220 free(udid)
221 property handle:
222 def __get__(self):
223 cdef uint32_t handle
224 self.handle_error(idevice_get_handle(self._c_dev, &handle))
225 return handle
226
227cdef extern from *:
228 ctypedef char* const_char_ptr "const char*"
229
230cdef class BaseService(Base):
231 __service_name__ = None
232
233cdef class PropertyListService(BaseService):
234 cpdef send(self, plist.Node node):
235 self.handle_error(self._send(node._c_node))
236
237 cpdef object receive(self):
238 cdef:
239 plist.plist_t c_node = NULL
240 int16_t err
241 err = self._receive(&c_node)
242 try:
243 self.handle_error(err)
244
245 return plist.plist_t_to_node(c_node)
246 except BaseError, e:
247 if c_node != NULL:
248 plist.plist_free(c_node)
249 raise
250
251 cpdef object receive_with_timeout(self, int timeout_ms):
252 cdef:
253 plist.plist_t c_node = NULL
254 int16_t err
255 err = self._receive_with_timeout(&c_node, timeout_ms)
256 try:
257 self.handle_error(err)
258
259 return plist.plist_t_to_node(c_node)
260 except BaseError, e:
261 if c_node != NULL:
262 plist.plist_free(c_node)
263 raise
264
265 cdef int16_t _send(self, plist.plist_t node):
266 raise NotImplementedError("send is not implemented")
267
268 cdef int16_t _receive(self, plist.plist_t* c_node):
269 raise NotImplementedError("receive is not implemented")
270
271 cdef int16_t _receive_with_timeout(self, plist.plist_t* c_node, int timeout_ms):
272 raise NotImplementedError("receive_with_timeout is not implemented")
273
274cdef class DeviceLinkService(PropertyListService):
275 pass
276
277include "lockdown.pxi"
278include "mobilesync.pxi"
279include "notification_proxy.pxi"
280include "sbservices.pxi"
281include "mobilebackup.pxi"
282include "mobilebackup2.pxi"
283include "afc.pxi"
284include "file_relay.pxi"
285include "screenshotr.pxi"
286include "installation_proxy.pxi"
287include "mobile_image_mounter.pxi"
288include "webinspector.pxi"
289include "heartbeat.pxi"
290include "diagnostics_relay.pxi"
291include "misagent.pxi"
292include "house_arrest.pxi"
293include "restore.pxi"
294include "debugserver.pxi"