imobiledevice.pyx 9.4 KB

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