summaryrefslogtreecommitdiffstats
path: root/libusbmuxd/libusbmuxd.c
diff options
context:
space:
mode:
Diffstat (limited to 'libusbmuxd/libusbmuxd.c')
-rw-r--r--libusbmuxd/libusbmuxd.c201
1 files changed, 188 insertions, 13 deletions
diff --git a/libusbmuxd/libusbmuxd.c b/libusbmuxd/libusbmuxd.c
index f5e5d1b..f465deb 100644
--- a/libusbmuxd/libusbmuxd.c
+++ b/libusbmuxd/libusbmuxd.c
@@ -32,6 +32,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include <signal.h>
#include <pthread.h>
+#ifdef HAVE_PLIST
+#include <plist/plist.h>
+#define PLIST_BUNDLE_ID "com.marcansoft.usbmuxd"
+#define PLIST_CLIENT_VERSION_STRING "usbmuxd built for freedom"
+#define PLIST_PROGNAME "libusbmuxd"
+#endif
+
// usbmuxd public interface
#include "usbmuxd.h"
// usbmuxd protocol
@@ -47,6 +54,7 @@ pthread_t devmon;
static int listenfd = -1;
static int use_tag = 0;
+static int proto_version = 0;
/**
* Finds a device info record by its handle.
@@ -104,7 +112,95 @@ static int receive_packet(int sfd, struct usbmuxd_header *header, void **payload
}
}
- *payload = payload_loc;
+#ifdef HAVE_PLIST
+ if (hdr.message == MESSAGE_PLIST) {
+ char *message = NULL;
+ plist_t plist = NULL;
+ plist_from_xml(payload_loc, payload_size, &plist);
+ free(payload_loc);
+
+ if (!plist) {
+ fprintf(stderr, "%s: Error getting plist from payload!\n", __func__);
+ return -EBADMSG;
+ }
+
+ plist_t node = plist_dict_get_item(plist, "MessageType");
+ if (plist_get_node_type(node) != PLIST_STRING) {
+ fprintf(stderr, "%s: Error getting message type from plist!\n", __func__);
+ free(plist);
+ return -EBADMSG;
+ }
+
+ plist_get_string_val(node, &message);
+ if (message) {
+ uint64_t val = 0;
+ if (strcmp(message, "Result") == 0) {
+ /* result message */
+ uint32_t dwval = 0;
+ plist_t n = plist_dict_get_item(plist, "Number");
+ plist_get_uint_val(n, &val);
+ *payload = malloc(sizeof(uint32_t));
+ dwval = val;
+ memcpy(*payload, &dwval, sizeof(dwval));
+ hdr.length = sizeof(hdr) + sizeof(dwval);
+ hdr.message = MESSAGE_RESULT;
+ } else if (strcmp(message, "Attached") == 0) {
+ /* device add message */
+ struct usbmuxd_device_record *dev = NULL;
+ plist_t props = plist_dict_get_item(plist, "Properties");
+ if (!props) {
+ fprintf(stderr, "%s: Could not get properties for message '%s' from plist!\n", __func__, message);
+ plist_free(plist);
+ return -EBADMSG;
+ }
+ dev = (struct usbmuxd_device_record*)malloc(sizeof(struct usbmuxd_device_record));
+ memset(dev, 0, sizeof(struct usbmuxd_device_record));
+
+ plist_t n = plist_dict_get_item(props, "DeviceID");
+ plist_get_uint_val(n, &val);
+ dev->device_id = (uint32_t)val;
+
+ n = plist_dict_get_item(props, "ProductID");
+ plist_get_uint_val(n, &val);
+ dev->product_id = (uint32_t)val;
+
+ n = plist_dict_get_item(props, "SerialNumber");
+ char *strval = NULL;
+ plist_get_string_val(n, &strval);
+ if (strval) {
+ strcpy(dev->serial_number, strval);
+ free(strval);
+ }
+ n = plist_dict_get_item(props, "LocationID");
+ plist_get_uint_val(n, &val);
+ dev->location = (uint32_t)val;
+ *payload = (void*)dev;
+ hdr.length = sizeof(hdr) + sizeof(struct usbmuxd_device_record);
+ hdr.message = MESSAGE_DEVICE_ADD;
+ } else if (strcmp(message, "Detached") == 0) {
+ /* device remove message */
+ uint32_t dwval = 0;
+ plist_t n = plist_dict_get_item(plist, "DeviceID");
+ if (n) {
+ plist_get_uint_val(n, &val);
+ *payload = malloc(sizeof(uint32_t));
+ dwval = val;
+ memcpy(*payload, &dwval, sizeof(dwval));
+ hdr.length = sizeof(hdr) + sizeof(dwval);
+ hdr.message = MESSAGE_DEVICE_REMOVE;
+ }
+ } else {
+ fprintf(stderr, "%s: Unexpected message '%s' in plist!\n", __func__, message);
+ plist_free(plist);
+ return -EBADMSG;
+ }
+ }
+ plist_free(plist);
+ } else
+#endif
+ {
+ *payload = payload_loc;
+ }
memcpy(header, &hdr, sizeof(hdr));
@@ -159,7 +255,7 @@ static int send_packet(int sfd, uint32_t message, uint32_t tag, void *payload, u
struct usbmuxd_header header;
header.length = sizeof(struct usbmuxd_header);
- header.version = USBMUXD_PROTOCOL_VERSION;
+ header.version = proto_version;
header.message = message;
header.tag = tag;
if (payload && (payload_size > 0)) {
@@ -183,23 +279,74 @@ static int send_packet(int sfd, uint32_t message, uint32_t tag, void *payload, u
static int send_listen_packet(int sfd, uint32_t tag)
{
- return send_packet(sfd, MESSAGE_LISTEN, tag, NULL, 0);
+ int res = 0;
+#ifdef HAVE_PLIST
+ if (proto_version == 1) {
+ /* plist packet */
+ char *payload = NULL;
+ uint32_t payload_size = 0;
+ plist_t plist;
+
+ /* construct message plist */
+ plist = plist_new_dict();
+ plist_dict_insert_item(plist, "BundleID", plist_new_string(PLIST_BUNDLE_ID));
+ plist_dict_insert_item(plist, "ClientVersionString", plist_new_string(PLIST_CLIENT_VERSION_STRING));
+ plist_dict_insert_item(plist, "MessageType", plist_new_string("Listen"));
+ plist_dict_insert_item(plist, "ProgName", plist_new_string(PLIST_PROGNAME));
+ plist_to_xml(plist, &payload, &payload_size);
+ plist_free(plist);
+
+ res = send_packet(sfd, MESSAGE_PLIST, tag, payload, payload_size);
+ free(payload);
+ } else
+#endif
+ {
+ /* binary packet */
+ res = send_packet(sfd, MESSAGE_LISTEN, tag, NULL, 0);
+ }
+ return res;
}
static int send_connect_packet(int sfd, uint32_t tag, uint32_t device_id, uint16_t port)
{
- struct {
- uint32_t device_id;
- uint16_t port;
- uint16_t reserved;
- } conninfo;
-
- conninfo.device_id = device_id;
- conninfo.port = htons(port);
- conninfo.reserved = 0;
+ int res = 0;
+#ifdef HAVE_PLIST
+ if (proto_version == 1) {
+ /* plist packet */
+ char *payload = NULL;
+ uint32_t payload_size = 0;
+ plist_t plist;
+
+ /* construct message plist */
+ plist = plist_new_dict();
+ plist_dict_insert_item(plist, "BundleID", plist_new_string(PLIST_BUNDLE_ID));
+ plist_dict_insert_item(plist, "ClientVersionString", plist_new_string(PLIST_CLIENT_VERSION_STRING));
+ plist_dict_insert_item(plist, "MessageType", plist_new_string("Connect"));
+ plist_dict_insert_item(plist, "DeviceID", plist_new_uint(device_id));
+ plist_dict_insert_item(plist, "PortNumber", plist_new_uint(port));
+ plist_dict_insert_item(plist, "ProgName", plist_new_string(PLIST_PROGNAME));
+ plist_to_xml(plist, &payload, &payload_size);
+ plist_free(plist);
+
+ res = send_packet(sfd, MESSAGE_PLIST, tag, (void*)payload, payload_size);
+ free(payload);
+ } else
+#endif
+ {
+ /* binary packet */
+ struct {
+ uint32_t device_id;
+ uint16_t port;
+ uint16_t reserved;
+ } conninfo;
- return send_packet(sfd, MESSAGE_CONNECT, tag, &conninfo, sizeof(conninfo));
+ conninfo.device_id = device_id;
+ conninfo.port = htons(port);
+ conninfo.reserved = 0;
+ res = send_packet(sfd, MESSAGE_CONNECT, tag, &conninfo, sizeof(conninfo));
+ }
+ return res;
}
/**
@@ -231,6 +378,9 @@ static int usbmuxd_listen()
int sfd;
uint32_t res = -1;
+#ifdef HAVE_PLIST
+retry:
+#endif
sfd = connect_usbmuxd_socket();
if (sfd < 0) {
while (event_cb) {
@@ -254,6 +404,12 @@ static int usbmuxd_listen()
}
if (usbmuxd_get_result(sfd, use_tag, &res) && (res != 0)) {
close(sfd);
+#ifdef HAVE_PLIST
+ if ((res == RESULT_BADVERSION) && (proto_version != 1)) {
+ proto_version = 1;
+ goto retry;
+ }
+#endif
fprintf(stderr, "%s: ERROR: did not get OK but %d\n", __func__, res);
return -1;
}
@@ -396,6 +552,9 @@ int usbmuxd_get_device_list(usbmuxd_device_info_t **device_list)
int dev_cnt = 0;
void *payload = NULL;
+#ifdef HAVE_PLIST
+retry:
+#endif
sfd = connect_usbmuxd_socket();
if (sfd < 0) {
fprintf(stderr, "%s: error opening socket!\n", __func__);
@@ -410,6 +569,12 @@ int usbmuxd_get_device_list(usbmuxd_device_info_t **device_list)
listen_success = 1;
} else {
close(sfd);
+#ifdef HAVE_PLIST
+ if ((res == RESULT_BADVERSION) && (proto_version != 1)) {
+ proto_version = 1;
+ goto retry;
+ }
+#endif
fprintf(stderr,
"%s: Did not get response to scan request (with result=0)...\n",
__func__);
@@ -521,6 +686,9 @@ int usbmuxd_connect(const int handle, const unsigned short port)
int connected = 0;
uint32_t res = -1;
+#ifdef HAVE_PLIST
+retry:
+#endif
sfd = connect_usbmuxd_socket();
if (sfd < 0) {
fprintf(stderr, "%s: Error: Connection to usbmuxd failed: %s\n",
@@ -539,6 +707,13 @@ int usbmuxd_connect(const int handle, const unsigned short port)
//fprintf(stderr, "%s: Connect success!\n", __func__);
connected = 1;
} else {
+#ifdef HAVE_PLIST
+ if ((res == RESULT_BADVERSION) && (proto_version == 0)) {
+ proto_version = 1;
+ close(sfd);
+ goto retry;
+ }
+#endif
fprintf(stderr, "%s: Connect failed, Error code=%d\n",
__func__, res);
}