diff options
Diffstat (limited to 'libusbmuxd')
| -rw-r--r-- | libusbmuxd/CMakeLists.txt | 6 | ||||
| -rw-r--r-- | libusbmuxd/libusbmuxd.c | 201 | ||||
| -rw-r--r-- | libusbmuxd/usbmuxd-proto.h | 2 | 
3 files changed, 194 insertions, 15 deletions
| diff --git a/libusbmuxd/CMakeLists.txt b/libusbmuxd/CMakeLists.txt index d275169..236cca3 100644 --- a/libusbmuxd/CMakeLists.txt +++ b/libusbmuxd/CMakeLists.txt @@ -3,7 +3,11 @@ find_package(Threads)  add_library (libusbmuxd SHARED libusbmuxd.c sock_stuff.c ${CMAKE_SOURCE_DIR}/common/utils.c)  find_library (PTHREAD pthread) -target_link_libraries (libusbmuxd ${CMAKE_THREAD_LIBS_INIT}) + +if (HAVE_PLIST) +  message("-- libusbmuxd will be built with protocol version 1 support") +endif() +target_link_libraries (libusbmuxd ${CMAKE_THREAD_LIBS_INIT} ${OPT_LIBS})  # 'lib' is a UNIXism, the proper CMake target is usbmuxd  # But we can't use that due to the conflict with the usbmuxd daemon, 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);  			} diff --git a/libusbmuxd/usbmuxd-proto.h b/libusbmuxd/usbmuxd-proto.h index 0d4596c..11dd3cf 100644 --- a/libusbmuxd/usbmuxd-proto.h +++ b/libusbmuxd/usbmuxd-proto.h @@ -52,7 +52,7 @@ enum usbmuxd_msgtype {  	MESSAGE_DEVICE_REMOVE = 5,  	//???  	//??? -	//MESSAGE_PLIST = 8, +	MESSAGE_PLIST = 8,  };  struct usbmuxd_header { | 
