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
32#include <signal.h> 32#include <signal.h>
33#include <pthread.h> 33#include <pthread.h>
34 34
35#ifdef HAVE_PLIST
36#include <plist/plist.h>
37#define PLIST_BUNDLE_ID "com.marcansoft.usbmuxd"
38#define PLIST_CLIENT_VERSION_STRING "usbmuxd built for freedom"
39#define PLIST_PROGNAME "libusbmuxd"
40#endif
41
35// usbmuxd public interface 42// usbmuxd public interface
36#include "usbmuxd.h" 43#include "usbmuxd.h"
37// usbmuxd protocol 44// usbmuxd protocol
@@ -47,6 +54,7 @@ pthread_t devmon;
47static int listenfd = -1; 54static int listenfd = -1;
48 55
49static int use_tag = 0; 56static int use_tag = 0;
57static int proto_version = 0;
50 58
51/** 59/**
52 * Finds a device info record by its handle. 60 * Finds a device info record by its handle.
@@ -104,7 +112,95 @@ static int receive_packet(int sfd, struct usbmuxd_header *header, void **payload
104 } 112 }
105 } 113 }
106 114
107 *payload = payload_loc; 115#ifdef HAVE_PLIST
116 if (hdr.message == MESSAGE_PLIST) {
117 char *message = NULL;
118 plist_t plist = NULL;
119 plist_from_xml(payload_loc, payload_size, &plist);
120 free(payload_loc);
121
122 if (!plist) {
123 fprintf(stderr, "%s: Error getting plist from payload!\n", __func__);
124 return -EBADMSG;
125 }
126
127 plist_t node = plist_dict_get_item(plist, "MessageType");
128 if (plist_get_node_type(node) != PLIST_STRING) {
129 fprintf(stderr, "%s: Error getting message type from plist!\n", __func__);
130 free(plist);
131 return -EBADMSG;
132 }
133
134 plist_get_string_val(node, &message);
135 if (message) {
136 uint64_t val = 0;
137 if (strcmp(message, "Result") == 0) {
138 /* result message */
139 uint32_t dwval = 0;
140 plist_t n = plist_dict_get_item(plist, "Number");
141 plist_get_uint_val(n, &val);
142 *payload = malloc(sizeof(uint32_t));
143 dwval = val;
144 memcpy(*payload, &dwval, sizeof(dwval));
145 hdr.length = sizeof(hdr) + sizeof(dwval);
146 hdr.message = MESSAGE_RESULT;
147 } else if (strcmp(message, "Attached") == 0) {
148 /* device add message */
149 struct usbmuxd_device_record *dev = NULL;
150 plist_t props = plist_dict_get_item(plist, "Properties");
151 if (!props) {
152 fprintf(stderr, "%s: Could not get properties for message '%s' from plist!\n", __func__, message);
153 plist_free(plist);
154 return -EBADMSG;
155 }
156 dev = (struct usbmuxd_device_record*)malloc(sizeof(struct usbmuxd_device_record));
157 memset(dev, 0, sizeof(struct usbmuxd_device_record));
158
159 plist_t n = plist_dict_get_item(props, "DeviceID");
160 plist_get_uint_val(n, &val);
161 dev->device_id = (uint32_t)val;
162
163 n = plist_dict_get_item(props, "ProductID");
164 plist_get_uint_val(n, &val);
165 dev->product_id = (uint32_t)val;
166
167 n = plist_dict_get_item(props, "SerialNumber");
168 char *strval = NULL;
169 plist_get_string_val(n, &strval);
170 if (strval) {
171 strcpy(dev->serial_number, strval);
172 free(strval);
173 }
174 n = plist_dict_get_item(props, "LocationID");
175 plist_get_uint_val(n, &val);
176 dev->location = (uint32_t)val;
177 *payload = (void*)dev;
178 hdr.length = sizeof(hdr) + sizeof(struct usbmuxd_device_record);
179 hdr.message = MESSAGE_DEVICE_ADD;
180 } else if (strcmp(message, "Detached") == 0) {
181 /* device remove message */
182 uint32_t dwval = 0;
183 plist_t n = plist_dict_get_item(plist, "DeviceID");
184 if (n) {
185 plist_get_uint_val(n, &val);
186 *payload = malloc(sizeof(uint32_t));
187 dwval = val;
188 memcpy(*payload, &dwval, sizeof(dwval));
189 hdr.length = sizeof(hdr) + sizeof(dwval);
190 hdr.message = MESSAGE_DEVICE_REMOVE;
191 }
192 } else {
193 fprintf(stderr, "%s: Unexpected message '%s' in plist!\n", __func__, message);
194 plist_free(plist);
195 return -EBADMSG;
196 }
197 }
198 plist_free(plist);
199 } else
200#endif
201 {
202 *payload = payload_loc;
203 }
108 204
109 memcpy(header, &hdr, sizeof(hdr)); 205 memcpy(header, &hdr, sizeof(hdr));
110 206
@@ -159,7 +255,7 @@ static int send_packet(int sfd, uint32_t message, uint32_t tag, void *payload, u
159 struct usbmuxd_header header; 255 struct usbmuxd_header header;
160 256
161 header.length = sizeof(struct usbmuxd_header); 257 header.length = sizeof(struct usbmuxd_header);
162 header.version = USBMUXD_PROTOCOL_VERSION; 258 header.version = proto_version;
163 header.message = message; 259 header.message = message;
164 header.tag = tag; 260 header.tag = tag;
165 if (payload && (payload_size > 0)) { 261 if (payload && (payload_size > 0)) {
@@ -183,23 +279,74 @@ static int send_packet(int sfd, uint32_t message, uint32_t tag, void *payload, u
183 279
184static int send_listen_packet(int sfd, uint32_t tag) 280static int send_listen_packet(int sfd, uint32_t tag)
185{ 281{
186 return send_packet(sfd, MESSAGE_LISTEN, tag, NULL, 0); 282 int res = 0;
283#ifdef HAVE_PLIST
284 if (proto_version == 1) {
285 /* plist packet */
286 char *payload = NULL;
287 uint32_t payload_size = 0;
288 plist_t plist;
289
290 /* construct message plist */
291 plist = plist_new_dict();
292 plist_dict_insert_item(plist, "BundleID", plist_new_string(PLIST_BUNDLE_ID));
293 plist_dict_insert_item(plist, "ClientVersionString", plist_new_string(PLIST_CLIENT_VERSION_STRING));
294 plist_dict_insert_item(plist, "MessageType", plist_new_string("Listen"));
295 plist_dict_insert_item(plist, "ProgName", plist_new_string(PLIST_PROGNAME));
296 plist_to_xml(plist, &payload, &payload_size);
297 plist_free(plist);
298
299 res = send_packet(sfd, MESSAGE_PLIST, tag, payload, payload_size);
300 free(payload);
301 } else
302#endif
303 {
304 /* binary packet */
305 res = send_packet(sfd, MESSAGE_LISTEN, tag, NULL, 0);
306 }
307 return res;
187} 308}
188 309
189static int send_connect_packet(int sfd, uint32_t tag, uint32_t device_id, uint16_t port) 310static int send_connect_packet(int sfd, uint32_t tag, uint32_t device_id, uint16_t port)
190{ 311{
191 struct { 312 int res = 0;
192 uint32_t device_id; 313#ifdef HAVE_PLIST
193 uint16_t port; 314 if (proto_version == 1) {
194 uint16_t reserved; 315 /* plist packet */
195 } conninfo; 316 char *payload = NULL;
196 317 uint32_t payload_size = 0;
197 conninfo.device_id = device_id; 318 plist_t plist;
198 conninfo.port = htons(port); 319
199 conninfo.reserved = 0; 320 /* construct message plist */
321 plist = plist_new_dict();
322 plist_dict_insert_item(plist, "BundleID", plist_new_string(PLIST_BUNDLE_ID));
323 plist_dict_insert_item(plist, "ClientVersionString", plist_new_string(PLIST_CLIENT_VERSION_STRING));
324 plist_dict_insert_item(plist, "MessageType", plist_new_string("Connect"));
325 plist_dict_insert_item(plist, "DeviceID", plist_new_uint(device_id));
326 plist_dict_insert_item(plist, "PortNumber", plist_new_uint(port));
327 plist_dict_insert_item(plist, "ProgName", plist_new_string(PLIST_PROGNAME));
328 plist_to_xml(plist, &payload, &payload_size);
329 plist_free(plist);
330
331 res = send_packet(sfd, MESSAGE_PLIST, tag, (void*)payload, payload_size);
332 free(payload);
333 } else
334#endif
335 {
336 /* binary packet */
337 struct {
338 uint32_t device_id;
339 uint16_t port;
340 uint16_t reserved;
341 } conninfo;
200 342
201 return send_packet(sfd, MESSAGE_CONNECT, tag, &conninfo, sizeof(conninfo)); 343 conninfo.device_id = device_id;
344 conninfo.port = htons(port);
345 conninfo.reserved = 0;
202 346
347 res = send_packet(sfd, MESSAGE_CONNECT, tag, &conninfo, sizeof(conninfo));
348 }
349 return res;
203} 350}
204 351
205/** 352/**
@@ -231,6 +378,9 @@ static int usbmuxd_listen()
231 int sfd; 378 int sfd;
232 uint32_t res = -1; 379 uint32_t res = -1;
233 380
381#ifdef HAVE_PLIST
382retry:
383#endif
234 sfd = connect_usbmuxd_socket(); 384 sfd = connect_usbmuxd_socket();
235 if (sfd < 0) { 385 if (sfd < 0) {
236 while (event_cb) { 386 while (event_cb) {
@@ -254,6 +404,12 @@ static int usbmuxd_listen()
254 } 404 }
255 if (usbmuxd_get_result(sfd, use_tag, &res) && (res != 0)) { 405 if (usbmuxd_get_result(sfd, use_tag, &res) && (res != 0)) {
256 close(sfd); 406 close(sfd);
407#ifdef HAVE_PLIST
408 if ((res == RESULT_BADVERSION) && (proto_version != 1)) {
409 proto_version = 1;
410 goto retry;
411 }
412#endif
257 fprintf(stderr, "%s: ERROR: did not get OK but %d\n", __func__, res); 413 fprintf(stderr, "%s: ERROR: did not get OK but %d\n", __func__, res);
258 return -1; 414 return -1;
259 } 415 }
@@ -396,6 +552,9 @@ int usbmuxd_get_device_list(usbmuxd_device_info_t **device_list)
396 int dev_cnt = 0; 552 int dev_cnt = 0;
397 void *payload = NULL; 553 void *payload = NULL;
398 554
555#ifdef HAVE_PLIST
556retry:
557#endif
399 sfd = connect_usbmuxd_socket(); 558 sfd = connect_usbmuxd_socket();
400 if (sfd < 0) { 559 if (sfd < 0) {
401 fprintf(stderr, "%s: error opening socket!\n", __func__); 560 fprintf(stderr, "%s: error opening socket!\n", __func__);
@@ -410,6 +569,12 @@ int usbmuxd_get_device_list(usbmuxd_device_info_t **device_list)
410 listen_success = 1; 569 listen_success = 1;
411 } else { 570 } else {
412 close(sfd); 571 close(sfd);
572#ifdef HAVE_PLIST
573 if ((res == RESULT_BADVERSION) && (proto_version != 1)) {
574 proto_version = 1;
575 goto retry;
576 }
577#endif
413 fprintf(stderr, 578 fprintf(stderr,
414 "%s: Did not get response to scan request (with result=0)...\n", 579 "%s: Did not get response to scan request (with result=0)...\n",
415 __func__); 580 __func__);
@@ -521,6 +686,9 @@ int usbmuxd_connect(const int handle, const unsigned short port)
521 int connected = 0; 686 int connected = 0;
522 uint32_t res = -1; 687 uint32_t res = -1;
523 688
689#ifdef HAVE_PLIST
690retry:
691#endif
524 sfd = connect_usbmuxd_socket(); 692 sfd = connect_usbmuxd_socket();
525 if (sfd < 0) { 693 if (sfd < 0) {
526 fprintf(stderr, "%s: Error: Connection to usbmuxd failed: %s\n", 694 fprintf(stderr, "%s: Error: Connection to usbmuxd failed: %s\n",
@@ -539,6 +707,13 @@ int usbmuxd_connect(const int handle, const unsigned short port)
539 //fprintf(stderr, "%s: Connect success!\n", __func__); 707 //fprintf(stderr, "%s: Connect success!\n", __func__);
540 connected = 1; 708 connected = 1;
541 } else { 709 } else {
710#ifdef HAVE_PLIST
711 if ((res == RESULT_BADVERSION) && (proto_version == 0)) {
712 proto_version = 1;
713 close(sfd);
714 goto retry;
715 }
716#endif
542 fprintf(stderr, "%s: Connect failed, Error code=%d\n", 717 fprintf(stderr, "%s: Connect failed, Error code=%d\n",
543 __func__, res); 718 __func__, res);
544 } 719 }