summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/libimobiledevice/libimobiledevice.h56
-rw-r--r--src/idevice.c92
-rw-r--r--src/idevice.h8
3 files changed, 124 insertions, 32 deletions
diff --git a/include/libimobiledevice/libimobiledevice.h b/include/libimobiledevice/libimobiledevice.h
index 8f8589d..c1d5460 100644
--- a/include/libimobiledevice/libimobiledevice.h
+++ b/include/libimobiledevice/libimobiledevice.h
@@ -3,6 +3,7 @@
3 * @brief Device/Connection handling and communication 3 * @brief Device/Connection handling and communication
4 * \internal 4 * \internal
5 * 5 *
6 * Copyright (c) 2010-2019 Nikias Bassen All Rights Reserved.
6 * Copyright (c) 2010-2014 Martin Szulecki All Rights Reserved. 7 * Copyright (c) 2010-2014 Martin Szulecki All Rights Reserved.
7 * Copyright (c) 2014 Christophe Fergeau All Rights Reserved. 8 * Copyright (c) 2014 Christophe Fergeau All Rights Reserved.
8 * Copyright (c) 2008 Jonathan Beck All Rights Reserved. 9 * Copyright (c) 2008 Jonathan Beck All Rights Reserved.
@@ -51,6 +52,26 @@ typedef idevice_private *idevice_t; /**< The device handle. */
51typedef struct idevice_connection_private idevice_connection_private; 52typedef struct idevice_connection_private idevice_connection_private;
52typedef idevice_connection_private *idevice_connection_t; /**< The connection handle. */ 53typedef idevice_connection_private *idevice_connection_t; /**< The connection handle. */
53 54
55/** Options for idevice_new_with_options() */
56enum idevice_options {
57 IDEVICE_LOOKUP_USBMUX = 1 << 1, /**< include USBMUX devices during lookup */
58 IDEVICE_LOOKUP_NETWORK = 1 << 2, /**< include network devices during lookup */
59 IDEVICE_LOOKUP_PREFER_NETWORK = 1 << 3 /**< prefer network connection if device is available via USBMUX *and* network */
60};
61
62/** Type of connection a device is available on */
63enum idevice_connection_type {
64 CONNECTION_USBMUXD = 1,
65 CONNECTION_NETWORK
66};
67
68struct idevice_info {
69 char *udid;
70 enum idevice_connection_type conn_type;
71 void* conn_data;
72};
73typedef struct idevice_info* idevice_info_t;
74
54/* discovery (events/asynchronous) */ 75/* discovery (events/asynchronous) */
55/** The event type for device add or removal */ 76/** The event type for device add or removal */
56enum idevice_event_type { 77enum idevice_event_type {
@@ -64,7 +85,7 @@ enum idevice_event_type {
64typedef struct { 85typedef struct {
65 enum idevice_event_type event; /**< The event type. */ 86 enum idevice_event_type event; /**< The event type. */
66 const char *udid; /**< The device unique id. */ 87 const char *udid; /**< The device unique id. */
67 int conn_type; /**< The connection type. Currently only 1 for usbmuxd. */ 88 enum idevice_connection_type conn_type; /**< The connection type. */
68} idevice_event_t; 89} idevice_event_t;
69 90
70/* event callback function prototype */ 91/* event callback function prototype */
@@ -125,11 +146,15 @@ idevice_error_t idevice_device_list_free(char **devices);
125/* device structure creation and destruction */ 146/* device structure creation and destruction */
126 147
127/** 148/**
128 * Creates an idevice_t structure for the device specified by udid, 149 * Creates an idevice_t structure for the device specified by UDID,
129 * if the device is available. 150 * if the device is available (USBMUX devices only).
130 * 151 *
131 * @note The resulting idevice_t structure has to be freed with 152 * @note The resulting idevice_t structure has to be freed with
132 * idevice_free() if it is no longer used. 153 * idevice_free() if it is no longer used.
154 * If you need to connect to a device available via network, use
155 * idevice_new_with_options() and include IDEVICE_LOOKUP_NETWORK in options.
156 *
157 * @see idevice_new_with_options
133 * 158 *
134 * @param device Upon calling this function, a pointer to a location of type 159 * @param device Upon calling this function, a pointer to a location of type
135 * idevice_t. On successful return, this location will be populated. 160 * idevice_t. On successful return, this location will be populated.
@@ -140,9 +165,30 @@ idevice_error_t idevice_device_list_free(char **devices);
140idevice_error_t idevice_new(idevice_t *device, const char *udid); 165idevice_error_t idevice_new(idevice_t *device, const char *udid);
141 166
142/** 167/**
168 * Creates an idevice_t structure for the device specified by UDID,
169 * if the device is available, with the given lookup options.
170 *
171 * @note The resulting idevice_t structure has to be freed with
172 * idevice_free() if it is no longer used.
173 *
174 * @param device Upon calling this function, a pointer to a location of type
175 * idevice_t. On successful return, this location will be populated.
176 * @param udid The UDID to match.
177 * @param options Specifies what connection types should be considered
178 * when looking up devices. Accepts bitwise or'ed values of idevice_options.
179 * If 0 (no option) is specified it will default to IDEVICE_LOOKUP_USBMUX.
180 * To lookup both USB and network-connected devices, pass
181 * IDEVICE_LOOKUP_USBMUX | IDEVICE_LOOKUP_NETWORK. If a device is available
182 * both via USBMUX *and* network, it will select the USB connection.
183 * This behavior can be changed by adding IDEVICE_LOOKUP_PREFER_NETWORK
184 * to the options in which case it will select the network connection.
185 *
186 * @return IDEVICE_E_SUCCESS if ok, otherwise an error code.
187 */
188idevice_error_t idevice_new_with_options(idevice_t *device, const char *udid, enum idevice_options options);
189
190/**
143 * Cleans up an idevice structure, then frees the structure itself. 191 * Cleans up an idevice structure, then frees the structure itself.
144 * This is a library-level function; deals directly with the device to tear
145 * down relations, but otherwise is mostly internal.
146 * 192 *
147 * @param device idevice_t to free. 193 * @param device idevice_t to free.
148 */ 194 */
diff --git a/src/idevice.c b/src/idevice.c
index 06991c5..d23c5b5 100644
--- a/src/idevice.c
+++ b/src/idevice.c
@@ -190,7 +190,14 @@ static void usbmux_event_cb(const usbmuxd_event_t *event, void *user_data)
190 190
191 ev.event = event->event; 191 ev.event = event->event;
192 ev.udid = event->device.udid; 192 ev.udid = event->device.udid;
193 ev.conn_type = CONNECTION_USBMUXD; 193 ev.conn_type = 0;
194 if (event->device.conn_type == CONNECTION_TYPE_USB) {
195 ev.conn_type = CONNECTION_USBMUXD;
196 } else if (event->device.conn_type == CONNECTION_TYPE_NETWORK) {
197 ev.conn_type = CONNECTION_NETWORK;
198 } else {
199 debug_info("Unknown connection type %d", event->device.conn_type);
200 }
194 201
195 if (event_cb) { 202 if (event_cb) {
196 event_cb(&ev, user_data); 203 event_cb(&ev, user_data);
@@ -236,9 +243,11 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_get_device_list(char ***devices, in
236 int i, newcount = 0; 243 int i, newcount = 0;
237 244
238 for (i = 0; dev_list[i].handle > 0; i++) { 245 for (i = 0; dev_list[i].handle > 0; i++) {
239 newlist = realloc(*devices, sizeof(char*) * (newcount+1)); 246 if (dev_list[i].conn_type == CONNECTION_TYPE_USB) {
240 newlist[newcount++] = strdup(dev_list[i].udid); 247 newlist = realloc(*devices, sizeof(char*) * (newcount+1));
241 *devices = newlist; 248 newlist[newcount++] = strdup(dev_list[i].udid);
249 *devices = newlist;
250 }
242 } 251 }
243 usbmuxd_device_list_free(&dev_list); 252 usbmuxd_device_list_free(&dev_list);
244 253
@@ -268,25 +277,66 @@ LIBIMOBILEDEVICE_API void idevice_set_debug_level(int level)
268 internal_set_debug_level(level); 277 internal_set_debug_level(level);
269} 278}
270 279
271LIBIMOBILEDEVICE_API idevice_error_t idevice_new(idevice_t * device, const char *udid) 280static idevice_t idevice_from_mux_device(usbmuxd_device_info_t *muxdev)
281{
282 if (!muxdev)
283 return NULL;
284
285 idevice_t device = (idevice_t)malloc(sizeof(struct idevice_private));
286 if (!device)
287 return NULL;
288
289 device->udid = strdup(muxdev->udid);
290 device->mux_id = muxdev->handle;
291 device->version = 0;
292 switch (muxdev->conn_type) {
293 case CONNECTION_TYPE_USB:
294 device->conn_type = CONNECTION_USBMUXD;
295 device->conn_data = NULL;
296 break;
297 case CONNECTION_TYPE_NETWORK:
298 device->conn_type = CONNECTION_NETWORK;
299 size_t len = ((uint8_t*)muxdev->conn_data)[0];
300 device->conn_data = malloc(len);
301 memcpy(device->conn_data, muxdev->conn_data, len);
302 break;
303 default:
304 device->conn_type = 0;
305 device->conn_data = NULL;
306 break;
307 }
308 return device;
309}
310
311LIBIMOBILEDEVICE_API idevice_error_t idevice_new_with_options(idevice_t * device, const char *udid, enum idevice_options options)
272{ 312{
273 usbmuxd_device_info_t muxdev; 313 usbmuxd_device_info_t muxdev;
274 int res = usbmuxd_get_device_by_udid(udid, &muxdev); 314 int usbmux_options = 0;
315 if (options & IDEVICE_LOOKUP_USBMUX) {
316 usbmux_options |= DEVICE_LOOKUP_USBMUX;
317 }
318 if (options & IDEVICE_LOOKUP_NETWORK) {
319 usbmux_options |= DEVICE_LOOKUP_NETWORK;
320 }
321 if (options & IDEVICE_LOOKUP_PREFER_NETWORK) {
322 usbmux_options |= DEVICE_LOOKUP_PREFER_NETWORK;
323 }
324 int res = usbmuxd_get_device(udid, &muxdev, usbmux_options);
275 if (res > 0) { 325 if (res > 0) {
276 idevice_t dev = (idevice_t) malloc(sizeof(struct idevice_private)); 326 *device = idevice_from_mux_device(&muxdev);
277 dev->udid = strdup(muxdev.udid); 327 if (!*device) {
278 dev->mux_id = muxdev.handle; 328 return IDEVICE_E_UNKNOWN_ERROR;
279 dev->conn_type = CONNECTION_USBMUXD; 329 }
280 dev->conn_data = NULL;
281 dev->version = 0;
282 *device = dev;
283 return IDEVICE_E_SUCCESS; 330 return IDEVICE_E_SUCCESS;
284 } 331 }
285 /* other connection types could follow here */
286
287 return IDEVICE_E_NO_DEVICE; 332 return IDEVICE_E_NO_DEVICE;
288} 333}
289 334
335LIBIMOBILEDEVICE_API idevice_error_t idevice_new(idevice_t * device, const char *udid)
336{
337 return idevice_new_with_options(device, udid, 0);
338}
339
290LIBIMOBILEDEVICE_API idevice_error_t idevice_free(idevice_t device) 340LIBIMOBILEDEVICE_API idevice_error_t idevice_free(idevice_t device)
291{ 341{
292 if (!device) 342 if (!device)
@@ -310,7 +360,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connect(idevice_t device, uint16_t
310 return IDEVICE_E_INVALID_ARG; 360 return IDEVICE_E_INVALID_ARG;
311 } 361 }
312 362
313 if (device->conn_type == CONNECTION_USBMUXD) { 363 if (device->conn_type == CONNECTION_USBMUXD || device->conn_type == CONNECTION_NETWORK) {
314 int sfd = usbmuxd_connect(device->mux_id, port); 364 int sfd = usbmuxd_connect(device->mux_id, port);
315 if (sfd < 0) { 365 if (sfd < 0) {
316 debug_info("ERROR: Connecting to usbmuxd failed: %d (%s)", sfd, strerror(-sfd)); 366 debug_info("ERROR: Connecting to usbmuxd failed: %d (%s)", sfd, strerror(-sfd));
@@ -340,7 +390,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_disconnect(idevice_connection_t con
340 idevice_connection_disable_ssl(connection); 390 idevice_connection_disable_ssl(connection);
341 } 391 }
342 idevice_error_t result = IDEVICE_E_UNKNOWN_ERROR; 392 idevice_error_t result = IDEVICE_E_UNKNOWN_ERROR;
343 if (connection->type == CONNECTION_USBMUXD) { 393 if (connection->type == CONNECTION_USBMUXD || connection->type == CONNECTION_NETWORK) {
344 usbmuxd_disconnect((int)(long)connection->data); 394 usbmuxd_disconnect((int)(long)connection->data);
345 connection->data = NULL; 395 connection->data = NULL;
346 result = IDEVICE_E_SUCCESS; 396 result = IDEVICE_E_SUCCESS;
@@ -363,7 +413,7 @@ static idevice_error_t internal_connection_send(idevice_connection_t connection,
363 return IDEVICE_E_INVALID_ARG; 413 return IDEVICE_E_INVALID_ARG;
364 } 414 }
365 415
366 if (connection->type == CONNECTION_USBMUXD) { 416 if (connection->type == CONNECTION_USBMUXD || connection->type == CONNECTION_NETWORK) {
367 int res = usbmuxd_send((int)(long)connection->data, data, len, sent_bytes); 417 int res = usbmuxd_send((int)(long)connection->data, data, len, sent_bytes);
368 if (res < 0) { 418 if (res < 0) {
369 debug_info("ERROR: usbmuxd_send returned %d (%s)", res, strerror(-res)); 419 debug_info("ERROR: usbmuxd_send returned %d (%s)", res, strerror(-res));
@@ -434,7 +484,7 @@ static idevice_error_t internal_connection_receive_timeout(idevice_connection_t
434 return IDEVICE_E_INVALID_ARG; 484 return IDEVICE_E_INVALID_ARG;
435 } 485 }
436 486
437 if (connection->type == CONNECTION_USBMUXD) { 487 if (connection->type == CONNECTION_USBMUXD || connection->type == CONNECTION_NETWORK) {
438 int conn_error = usbmuxd_recv_timeout((int)(long)connection->data, data, len, recv_bytes, timeout); 488 int conn_error = usbmuxd_recv_timeout((int)(long)connection->data, data, len, recv_bytes, timeout);
439 idevice_error_t error = socket_recv_to_idevice_error(conn_error, len, *recv_bytes); 489 idevice_error_t error = socket_recv_to_idevice_error(conn_error, len, *recv_bytes);
440 490
@@ -510,7 +560,7 @@ static idevice_error_t internal_connection_receive(idevice_connection_t connecti
510 return IDEVICE_E_INVALID_ARG; 560 return IDEVICE_E_INVALID_ARG;
511 } 561 }
512 562
513 if (connection->type == CONNECTION_USBMUXD) { 563 if (connection->type == CONNECTION_USBMUXD || connection->type == CONNECTION_NETWORK) {
514 int res = usbmuxd_recv((int)(long)connection->data, data, len, recv_bytes); 564 int res = usbmuxd_recv((int)(long)connection->data, data, len, recv_bytes);
515 if (res < 0) { 565 if (res < 0) {
516 debug_info("ERROR: usbmuxd_recv returned %d (%s)", res, strerror(-res)); 566 debug_info("ERROR: usbmuxd_recv returned %d (%s)", res, strerror(-res));
@@ -554,7 +604,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_get_fd(idevice_connectio
554 } 604 }
555 605
556 idevice_error_t result = IDEVICE_E_UNKNOWN_ERROR; 606 idevice_error_t result = IDEVICE_E_UNKNOWN_ERROR;
557 if (connection->type == CONNECTION_USBMUXD) { 607 if (connection->type == CONNECTION_USBMUXD || connection->type == CONNECTION_NETWORK) {
558 *fd = (int)(long)connection->data; 608 *fd = (int)(long)connection->data;
559 result = IDEVICE_E_SUCCESS; 609 result = IDEVICE_E_SUCCESS;
560 } else { 610 } else {
diff --git a/src/idevice.h b/src/idevice.h
index f403c55..8709c9a 100644
--- a/src/idevice.h
+++ b/src/idevice.h
@@ -48,10 +48,6 @@
48 48
49#define DEVICE_VERSION(maj, min, patch) (((maj & 0xFF) << 16) | ((min & 0xFF) << 8) | (patch & 0xFF)) 49#define DEVICE_VERSION(maj, min, patch) (((maj & 0xFF) << 16) | ((min & 0xFF) << 8) | (patch & 0xFF))
50 50
51enum connection_type {
52 CONNECTION_USBMUXD = 1
53};
54
55struct ssl_data_private { 51struct ssl_data_private {
56#ifdef HAVE_OPENSSL 52#ifdef HAVE_OPENSSL
57 SSL *session; 53 SSL *session;
@@ -69,7 +65,7 @@ typedef struct ssl_data_private *ssl_data_t;
69 65
70struct idevice_connection_private { 66struct idevice_connection_private {
71 idevice_t device; 67 idevice_t device;
72 enum connection_type type; 68 enum idevice_connection_type type;
73 void *data; 69 void *data;
74 ssl_data_t ssl_data; 70 ssl_data_t ssl_data;
75}; 71};
@@ -77,7 +73,7 @@ struct idevice_connection_private {
77struct idevice_private { 73struct idevice_private {
78 char *udid; 74 char *udid;
79 uint32_t mux_id; 75 uint32_t mux_id;
80 enum connection_type conn_type; 76 enum idevice_connection_type conn_type;
81 void *conn_data; 77 void *conn_data;
82 int version; 78 int version;
83}; 79};