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) | |||
| 3 | 3 | ||
| 4 | add_library (libusbmuxd SHARED libusbmuxd.c sock_stuff.c ${CMAKE_SOURCE_DIR}/common/utils.c) | 4 | add_library (libusbmuxd SHARED libusbmuxd.c sock_stuff.c ${CMAKE_SOURCE_DIR}/common/utils.c) |
| 5 | find_library (PTHREAD pthread) | 5 | find_library (PTHREAD pthread) |
| 6 | target_link_libraries (libusbmuxd ${CMAKE_THREAD_LIBS_INIT}) | 6 | |
| 7 | if (HAVE_PLIST) | ||
| 8 | message("-- libusbmuxd will be built with protocol version 1 support") | ||
| 9 | endif() | ||
| 10 | target_link_libraries (libusbmuxd ${CMAKE_THREAD_LIBS_INIT} ${OPT_LIBS}) | ||
| 7 | 11 | ||
| 8 | # 'lib' is a UNIXism, the proper CMake target is usbmuxd | 12 | # 'lib' is a UNIXism, the proper CMake target is usbmuxd |
| 9 | # But we can't use that due to the conflict with the usbmuxd daemon, | 13 | # 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 | |||
| 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; | |||
| 47 | static int listenfd = -1; | 54 | static int listenfd = -1; |
| 48 | 55 | ||
| 49 | static int use_tag = 0; | 56 | static int use_tag = 0; |
| 57 | static 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 | ||
| 184 | static int send_listen_packet(int sfd, uint32_t tag) | 280 | static 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 | ||
| 189 | static int send_connect_packet(int sfd, uint32_t tag, uint32_t device_id, uint16_t port) | 310 | static 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 | ||
| 382 | retry: | ||
| 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 | ||
| 556 | retry: | ||
| 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 | ||
| 690 | retry: | ||
| 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 | } |
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 { | |||
| 52 | MESSAGE_DEVICE_REMOVE = 5, | 52 | MESSAGE_DEVICE_REMOVE = 5, |
| 53 | //??? | 53 | //??? |
| 54 | //??? | 54 | //??? |
| 55 | //MESSAGE_PLIST = 8, | 55 | MESSAGE_PLIST = 8, |
| 56 | }; | 56 | }; |
| 57 | 57 | ||
| 58 | struct usbmuxd_header { | 58 | struct usbmuxd_header { |
