summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2019-11-07 23:25:55 +0100
committerGravatar Nikias Bassen2019-11-07 23:25:55 +0100
commit5390060ec90bed0f565698a389cebc57c09c3ac8 (patch)
treea73a3306a5a0449c7bf7cbe555dcaf2771ebda1c
parent8872aec759699411be45a17798dab40b9539c2ae (diff)
downloadlibimobiledevice-5390060ec90bed0f565698a389cebc57c09c3ac8.tar.gz
libimobiledevice-5390060ec90bed0f565698a389cebc57c09c3ac8.tar.bz2
Add propert support for network (WiFi) devices via new idevice_new_with_options()
-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 @@
* @brief Device/Connection handling and communication
* \internal
*
+ * Copyright (c) 2010-2019 Nikias Bassen All Rights Reserved.
* Copyright (c) 2010-2014 Martin Szulecki All Rights Reserved.
* Copyright (c) 2014 Christophe Fergeau All Rights Reserved.
* Copyright (c) 2008 Jonathan Beck All Rights Reserved.
@@ -51,6 +52,26 @@ typedef idevice_private *idevice_t; /**< The device handle. */
typedef struct idevice_connection_private idevice_connection_private;
typedef idevice_connection_private *idevice_connection_t; /**< The connection handle. */
+/** Options for idevice_new_with_options() */
+enum idevice_options {
+ IDEVICE_LOOKUP_USBMUX = 1 << 1, /**< include USBMUX devices during lookup */
+ IDEVICE_LOOKUP_NETWORK = 1 << 2, /**< include network devices during lookup */
+ IDEVICE_LOOKUP_PREFER_NETWORK = 1 << 3 /**< prefer network connection if device is available via USBMUX *and* network */
+};
+
+/** Type of connection a device is available on */
+enum idevice_connection_type {
+ CONNECTION_USBMUXD = 1,
+ CONNECTION_NETWORK
+};
+
+struct idevice_info {
+ char *udid;
+ enum idevice_connection_type conn_type;
+ void* conn_data;
+};
+typedef struct idevice_info* idevice_info_t;
+
/* discovery (events/asynchronous) */
/** The event type for device add or removal */
enum idevice_event_type {
@@ -64,7 +85,7 @@ enum idevice_event_type {
typedef struct {
enum idevice_event_type event; /**< The event type. */
const char *udid; /**< The device unique id. */
- int conn_type; /**< The connection type. Currently only 1 for usbmuxd. */
+ enum idevice_connection_type conn_type; /**< The connection type. */
} idevice_event_t;
/* event callback function prototype */
@@ -125,11 +146,15 @@ idevice_error_t idevice_device_list_free(char **devices);
/* device structure creation and destruction */
/**
- * Creates an idevice_t structure for the device specified by udid,
- * if the device is available.
+ * Creates an idevice_t structure for the device specified by UDID,
+ * if the device is available (USBMUX devices only).
*
* @note The resulting idevice_t structure has to be freed with
* idevice_free() if it is no longer used.
+ * If you need to connect to a device available via network, use
+ * idevice_new_with_options() and include IDEVICE_LOOKUP_NETWORK in options.
+ *
+ * @see idevice_new_with_options
*
* @param device Upon calling this function, a pointer to a location of type
* idevice_t. On successful return, this location will be populated.
@@ -140,9 +165,30 @@ idevice_error_t idevice_device_list_free(char **devices);
idevice_error_t idevice_new(idevice_t *device, const char *udid);
/**
+ * Creates an idevice_t structure for the device specified by UDID,
+ * if the device is available, with the given lookup options.
+ *
+ * @note The resulting idevice_t structure has to be freed with
+ * idevice_free() if it is no longer used.
+ *
+ * @param device Upon calling this function, a pointer to a location of type
+ * idevice_t. On successful return, this location will be populated.
+ * @param udid The UDID to match.
+ * @param options Specifies what connection types should be considered
+ * when looking up devices. Accepts bitwise or'ed values of idevice_options.
+ * If 0 (no option) is specified it will default to IDEVICE_LOOKUP_USBMUX.
+ * To lookup both USB and network-connected devices, pass
+ * IDEVICE_LOOKUP_USBMUX | IDEVICE_LOOKUP_NETWORK. If a device is available
+ * both via USBMUX *and* network, it will select the USB connection.
+ * This behavior can be changed by adding IDEVICE_LOOKUP_PREFER_NETWORK
+ * to the options in which case it will select the network connection.
+ *
+ * @return IDEVICE_E_SUCCESS if ok, otherwise an error code.
+ */
+idevice_error_t idevice_new_with_options(idevice_t *device, const char *udid, enum idevice_options options);
+
+/**
* Cleans up an idevice structure, then frees the structure itself.
- * This is a library-level function; deals directly with the device to tear
- * down relations, but otherwise is mostly internal.
*
* @param device idevice_t to free.
*/
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)
ev.event = event->event;
ev.udid = event->device.udid;
- ev.conn_type = CONNECTION_USBMUXD;
+ ev.conn_type = 0;
+ if (event->device.conn_type == CONNECTION_TYPE_USB) {
+ ev.conn_type = CONNECTION_USBMUXD;
+ } else if (event->device.conn_type == CONNECTION_TYPE_NETWORK) {
+ ev.conn_type = CONNECTION_NETWORK;
+ } else {
+ debug_info("Unknown connection type %d", event->device.conn_type);
+ }
if (event_cb) {
event_cb(&ev, user_data);
@@ -236,9 +243,11 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_get_device_list(char ***devices, in
int i, newcount = 0;
for (i = 0; dev_list[i].handle > 0; i++) {
- newlist = realloc(*devices, sizeof(char*) * (newcount+1));
- newlist[newcount++] = strdup(dev_list[i].udid);
- *devices = newlist;
+ if (dev_list[i].conn_type == CONNECTION_TYPE_USB) {
+ newlist = realloc(*devices, sizeof(char*) * (newcount+1));
+ newlist[newcount++] = strdup(dev_list[i].udid);
+ *devices = newlist;
+ }
}
usbmuxd_device_list_free(&dev_list);
@@ -268,25 +277,66 @@ LIBIMOBILEDEVICE_API void idevice_set_debug_level(int level)
internal_set_debug_level(level);
}
-LIBIMOBILEDEVICE_API idevice_error_t idevice_new(idevice_t * device, const char *udid)
+static idevice_t idevice_from_mux_device(usbmuxd_device_info_t *muxdev)
+{
+ if (!muxdev)
+ return NULL;
+
+ idevice_t device = (idevice_t)malloc(sizeof(struct idevice_private));
+ if (!device)
+ return NULL;
+
+ device->udid = strdup(muxdev->udid);
+ device->mux_id = muxdev->handle;
+ device->version = 0;
+ switch (muxdev->conn_type) {
+ case CONNECTION_TYPE_USB:
+ device->conn_type = CONNECTION_USBMUXD;
+ device->conn_data = NULL;
+ break;
+ case CONNECTION_TYPE_NETWORK:
+ device->conn_type = CONNECTION_NETWORK;
+ size_t len = ((uint8_t*)muxdev->conn_data)[0];
+ device->conn_data = malloc(len);
+ memcpy(device->conn_data, muxdev->conn_data, len);
+ break;
+ default:
+ device->conn_type = 0;
+ device->conn_data = NULL;
+ break;
+ }
+ return device;
+}
+
+LIBIMOBILEDEVICE_API idevice_error_t idevice_new_with_options(idevice_t * device, const char *udid, enum idevice_options options)
{
usbmuxd_device_info_t muxdev;
- int res = usbmuxd_get_device_by_udid(udid, &muxdev);
+ int usbmux_options = 0;
+ if (options & IDEVICE_LOOKUP_USBMUX) {
+ usbmux_options |= DEVICE_LOOKUP_USBMUX;
+ }
+ if (options & IDEVICE_LOOKUP_NETWORK) {
+ usbmux_options |= DEVICE_LOOKUP_NETWORK;
+ }
+ if (options & IDEVICE_LOOKUP_PREFER_NETWORK) {
+ usbmux_options |= DEVICE_LOOKUP_PREFER_NETWORK;
+ }
+ int res = usbmuxd_get_device(udid, &muxdev, usbmux_options);
if (res > 0) {
- idevice_t dev = (idevice_t) malloc(sizeof(struct idevice_private));
- dev->udid = strdup(muxdev.udid);
- dev->mux_id = muxdev.handle;
- dev->conn_type = CONNECTION_USBMUXD;
- dev->conn_data = NULL;
- dev->version = 0;
- *device = dev;
+ *device = idevice_from_mux_device(&muxdev);
+ if (!*device) {
+ return IDEVICE_E_UNKNOWN_ERROR;
+ }
return IDEVICE_E_SUCCESS;
}
- /* other connection types could follow here */
-
return IDEVICE_E_NO_DEVICE;
}
+LIBIMOBILEDEVICE_API idevice_error_t idevice_new(idevice_t * device, const char *udid)
+{
+ return idevice_new_with_options(device, udid, 0);
+}
+
LIBIMOBILEDEVICE_API idevice_error_t idevice_free(idevice_t device)
{
if (!device)
@@ -310,7 +360,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connect(idevice_t device, uint16_t
return IDEVICE_E_INVALID_ARG;
}
- if (device->conn_type == CONNECTION_USBMUXD) {
+ if (device->conn_type == CONNECTION_USBMUXD || device->conn_type == CONNECTION_NETWORK) {
int sfd = usbmuxd_connect(device->mux_id, port);
if (sfd < 0) {
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
idevice_connection_disable_ssl(connection);
}
idevice_error_t result = IDEVICE_E_UNKNOWN_ERROR;
- if (connection->type == CONNECTION_USBMUXD) {
+ if (connection->type == CONNECTION_USBMUXD || connection->type == CONNECTION_NETWORK) {
usbmuxd_disconnect((int)(long)connection->data);
connection->data = NULL;
result = IDEVICE_E_SUCCESS;
@@ -363,7 +413,7 @@ static idevice_error_t internal_connection_send(idevice_connection_t connection,
return IDEVICE_E_INVALID_ARG;
}
- if (connection->type == CONNECTION_USBMUXD) {
+ if (connection->type == CONNECTION_USBMUXD || connection->type == CONNECTION_NETWORK) {
int res = usbmuxd_send((int)(long)connection->data, data, len, sent_bytes);
if (res < 0) {
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
return IDEVICE_E_INVALID_ARG;
}
- if (connection->type == CONNECTION_USBMUXD) {
+ if (connection->type == CONNECTION_USBMUXD || connection->type == CONNECTION_NETWORK) {
int conn_error = usbmuxd_recv_timeout((int)(long)connection->data, data, len, recv_bytes, timeout);
idevice_error_t error = socket_recv_to_idevice_error(conn_error, len, *recv_bytes);
@@ -510,7 +560,7 @@ static idevice_error_t internal_connection_receive(idevice_connection_t connecti
return IDEVICE_E_INVALID_ARG;
}
- if (connection->type == CONNECTION_USBMUXD) {
+ if (connection->type == CONNECTION_USBMUXD || connection->type == CONNECTION_NETWORK) {
int res = usbmuxd_recv((int)(long)connection->data, data, len, recv_bytes);
if (res < 0) {
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
}
idevice_error_t result = IDEVICE_E_UNKNOWN_ERROR;
- if (connection->type == CONNECTION_USBMUXD) {
+ if (connection->type == CONNECTION_USBMUXD || connection->type == CONNECTION_NETWORK) {
*fd = (int)(long)connection->data;
result = IDEVICE_E_SUCCESS;
} 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 @@
#define DEVICE_VERSION(maj, min, patch) (((maj & 0xFF) << 16) | ((min & 0xFF) << 8) | (patch & 0xFF))
-enum connection_type {
- CONNECTION_USBMUXD = 1
-};
-
struct ssl_data_private {
#ifdef HAVE_OPENSSL
SSL *session;
@@ -69,7 +65,7 @@ typedef struct ssl_data_private *ssl_data_t;
struct idevice_connection_private {
idevice_t device;
- enum connection_type type;
+ enum idevice_connection_type type;
void *data;
ssl_data_t ssl_data;
};
@@ -77,7 +73,7 @@ struct idevice_connection_private {
struct idevice_private {
char *udid;
uint32_t mux_id;
- enum connection_type conn_type;
+ enum idevice_connection_type conn_type;
void *conn_data;
int version;
};