diff options
| -rw-r--r-- | CMakeLists.txt | 17 | ||||
| -rw-r--r-- | daemon/CMakeLists.txt | 6 | ||||
| -rw-r--r-- | daemon/client.c | 198 | ||||
| -rw-r--r-- | libusbmuxd/CMakeLists.txt | 6 | ||||
| -rw-r--r-- | libusbmuxd/libusbmuxd.c | 201 | ||||
| -rw-r--r-- | libusbmuxd/usbmuxd-proto.h | 2 |
6 files changed, 402 insertions, 28 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f0a6a8..93fa715 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
| @@ -25,6 +25,23 @@ if(CMAKE_C_FLAGS STREQUAL "") | |||
| 25 | set(CMAKE_C_FLAGS "-O2") | 25 | set(CMAKE_C_FLAGS "-O2") |
| 26 | endif() | 26 | endif() |
| 27 | 27 | ||
| 28 | option(WANT_PLIST "Build with protocol version 1 support using libplist" ON) | ||
| 29 | |||
| 30 | set(OPT_INCLUDES "") | ||
| 31 | set(OPT_LIBS "") | ||
| 32 | if(WANT_PLIST) | ||
| 33 | find_package(PLIST) | ||
| 34 | if(PLIST_FOUND) | ||
| 35 | set(HAVE_PLIST ON) | ||
| 36 | set(OPT_INCLUDES ${OPT_INCLUDES} ${PLIST_INCLUDE_DIRS}) | ||
| 37 | set(OPT_LIBS ${OPT_LIBS} ${PLIST_LIBRARIES}) | ||
| 38 | else() | ||
| 39 | message("* NOTE: libplist was not found!") | ||
| 40 | message("* libusbmuxd/usbmuxd will be build WITHOUT support for version 1") | ||
| 41 | message("* of the usbmux protocol (plist based).") | ||
| 42 | endif() | ||
| 43 | endif() | ||
| 44 | |||
| 28 | option(WITH_USBMUXD "Build usbmux daemon (usbmuxd)" ON) | 45 | option(WITH_USBMUXD "Build usbmux daemon (usbmuxd)" ON) |
| 29 | if(WIN32 AND WITH_USBMUXD) | 46 | if(WIN32 AND WITH_USBMUXD) |
| 30 | message("** NOTE: usbmuxd cannot be built on WIN32 due to missing libusb-1.0 support!") | 47 | message("** NOTE: usbmuxd cannot be built on WIN32 due to missing libusb-1.0 support!") |
diff --git a/daemon/CMakeLists.txt b/daemon/CMakeLists.txt index 6593deb..48ff0c6 100644 --- a/daemon/CMakeLists.txt +++ b/daemon/CMakeLists.txt | |||
| @@ -1,7 +1,9 @@ | |||
| 1 | find_package(USB REQUIRED) | 1 | find_package(USB REQUIRED) |
| 2 | include_directories(${USB_INCLUDE_DIRS}) | 2 | include_directories(${USB_INCLUDE_DIRS}) |
| 3 | set(LIBS ${LIBS} ${USB_LIBRARIES}) | 3 | set(LIBS ${LIBS} ${USB_LIBRARIES} ${OPT_LIBS}) |
| 4 | 4 | if(HAVE_PLIST) | |
| 5 | message("-- usbmuxd will be built with protocol version 1 support") | ||
| 6 | endif() | ||
| 5 | include_directories (${CMAKE_SOURCE_DIR}/common) | 7 | include_directories (${CMAKE_SOURCE_DIR}/common) |
| 6 | include_directories (${CMAKE_SOURCE_DIR}/daemon) | 8 | include_directories (${CMAKE_SOURCE_DIR}/daemon) |
| 7 | include_directories (${CMAKE_SOURCE_DIR}/libusbmuxd) | 9 | include_directories (${CMAKE_SOURCE_DIR}/libusbmuxd) |
diff --git a/daemon/client.c b/daemon/client.c index 194632d..80bc0c7 100644 --- a/daemon/client.c +++ b/daemon/client.c | |||
| @@ -32,12 +32,20 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
| 32 | #include <sys/un.h> | 32 | #include <sys/un.h> |
| 33 | #include <arpa/inet.h> | 33 | #include <arpa/inet.h> |
| 34 | 34 | ||
| 35 | #ifdef HAVE_PLIST | ||
| 36 | #include <plist/plist.h> | ||
| 37 | #endif | ||
| 38 | |||
| 35 | #include "log.h" | 39 | #include "log.h" |
| 36 | #include "usb.h" | 40 | #include "usb.h" |
| 37 | #include "client.h" | 41 | #include "client.h" |
| 38 | #include "device.h" | 42 | #include "device.h" |
| 39 | 43 | ||
| 44 | #ifdef HAVE_PLIST | ||
| 45 | #define CMD_BUF_SIZE 1024 | ||
| 46 | #else | ||
| 40 | #define CMD_BUF_SIZE 256 | 47 | #define CMD_BUF_SIZE 256 |
| 48 | #endif | ||
| 41 | #define REPLY_BUF_SIZE 1024 | 49 | #define REPLY_BUF_SIZE 1024 |
| 42 | 50 | ||
| 43 | enum client_state { | 51 | enum client_state { |
| @@ -61,6 +69,7 @@ struct mux_client { | |||
| 61 | uint32_t connect_tag; | 69 | uint32_t connect_tag; |
| 62 | int connect_device; | 70 | int connect_device; |
| 63 | enum client_state state; | 71 | enum client_state state; |
| 72 | uint32_t proto_version; | ||
| 64 | }; | 73 | }; |
| 65 | 74 | ||
| 66 | static struct collection client_list; | 75 | static struct collection client_list; |
| @@ -155,7 +164,7 @@ void client_get_fds(struct fdlist *list) | |||
| 155 | static int send_pkt(struct mux_client *client, uint32_t tag, enum usbmuxd_msgtype msg, void *payload, int payload_length) | 164 | static int send_pkt(struct mux_client *client, uint32_t tag, enum usbmuxd_msgtype msg, void *payload, int payload_length) |
| 156 | { | 165 | { |
| 157 | struct usbmuxd_header hdr; | 166 | struct usbmuxd_header hdr; |
| 158 | hdr.version = USBMUXD_PROTOCOL_VERSION; | 167 | hdr.version = client->proto_version; |
| 159 | hdr.length = sizeof(hdr) + payload_length; | 168 | hdr.length = sizeof(hdr) + payload_length; |
| 160 | hdr.message = msg; | 169 | hdr.message = msg; |
| 161 | hdr.tag = tag; | 170 | hdr.tag = tag; |
| @@ -175,7 +184,30 @@ static int send_pkt(struct mux_client *client, uint32_t tag, enum usbmuxd_msgtyp | |||
| 175 | 184 | ||
| 176 | static int send_result(struct mux_client *client, uint32_t tag, uint32_t result) | 185 | static int send_result(struct mux_client *client, uint32_t tag, uint32_t result) |
| 177 | { | 186 | { |
| 178 | return send_pkt(client, tag, MESSAGE_RESULT, &result, sizeof(uint32_t)); | 187 | int res = -1; |
| 188 | #ifdef HAVE_PLIST | ||
| 189 | if (client->proto_version == 1) { | ||
| 190 | /* XML plist packet */ | ||
| 191 | char *xml = NULL; | ||
| 192 | uint32_t xmlsize = 0; | ||
| 193 | plist_t dict = plist_new_dict(); | ||
| 194 | plist_dict_insert_item(dict, "MessageType", plist_new_string("Result")); | ||
| 195 | plist_dict_insert_item(dict, "Number", plist_new_uint(result)); | ||
| 196 | plist_to_xml(dict, &xml, &xmlsize); | ||
| 197 | plist_free(dict); | ||
| 198 | if (xml) { | ||
| 199 | res = send_pkt(client, tag, MESSAGE_PLIST, xml, xmlsize); | ||
| 200 | free(xml); | ||
| 201 | } else { | ||
| 202 | usbmuxd_log(LL_ERROR, "%s: Could not convert plist to xml", __func__); | ||
| 203 | } | ||
| 204 | } else | ||
| 205 | #endif | ||
| 206 | { | ||
| 207 | /* binary packet */ | ||
| 208 | res = send_pkt(client, tag, MESSAGE_RESULT, &result, sizeof(uint32_t)); | ||
| 209 | } | ||
| 210 | return res; | ||
| 179 | } | 211 | } |
| 180 | 212 | ||
| 181 | int client_notify_connect(struct mux_client *client, enum usbmuxd_result result) | 213 | int client_notify_connect(struct mux_client *client, enum usbmuxd_result result) |
| @@ -203,19 +235,73 @@ int client_notify_connect(struct mux_client *client, enum usbmuxd_result result) | |||
| 203 | 235 | ||
| 204 | static int notify_device_add(struct mux_client *client, struct device_info *dev) | 236 | static int notify_device_add(struct mux_client *client, struct device_info *dev) |
| 205 | { | 237 | { |
| 206 | struct usbmuxd_device_record dmsg; | 238 | int res = -1; |
| 207 | memset(&dmsg, 0, sizeof(dmsg)); | 239 | #ifdef HAVE_PLIST |
| 208 | dmsg.device_id = dev->id; | 240 | if (client->proto_version == 1) { |
| 209 | strncpy(dmsg.serial_number, dev->serial, 256); | 241 | /* XML plist packet */ |
| 210 | dmsg.serial_number[255] = 0; | 242 | char *xml = NULL; |
| 211 | dmsg.location = dev->location; | 243 | uint32_t xmlsize = 0; |
| 212 | dmsg.product_id = dev->pid; | 244 | plist_t dict = plist_new_dict(); |
| 213 | return send_pkt(client, 0, MESSAGE_DEVICE_ADD, &dmsg, sizeof(dmsg)); | 245 | plist_dict_insert_item(dict, "MessageType", plist_new_string("Attached")); |
| 246 | plist_t props = plist_new_dict(); | ||
| 247 | // TODO: get current usb speed | ||
| 248 | plist_dict_insert_item(props, "ConnectionSpeed", plist_new_uint(480000000)); | ||
| 249 | plist_dict_insert_item(props, "ConnectionType", plist_new_string("USB")); | ||
| 250 | plist_dict_insert_item(props, "DeviceID", plist_new_uint(dev->id)); | ||
| 251 | plist_dict_insert_item(props, "LocationID", plist_new_uint(dev->location)); | ||
| 252 | plist_dict_insert_item(props, "ProductID", plist_new_uint(dev->pid)); | ||
| 253 | plist_dict_insert_item(props, "SerialNumber", plist_new_string(dev->serial)); | ||
| 254 | plist_dict_insert_item(dict, "Properties", props); | ||
| 255 | plist_to_xml(dict, &xml, &xmlsize); | ||
| 256 | plist_free(dict); | ||
| 257 | if (xml) { | ||
| 258 | res = send_pkt(client, 0, MESSAGE_PLIST, xml, xmlsize); | ||
| 259 | free(xml); | ||
| 260 | } else { | ||
| 261 | usbmuxd_log(LL_ERROR, "%s: Could not convert plist to xml", __func__); | ||
| 262 | } | ||
| 263 | } else | ||
| 264 | #endif | ||
| 265 | { | ||
| 266 | /* binary packet */ | ||
| 267 | struct usbmuxd_device_record dmsg; | ||
| 268 | memset(&dmsg, 0, sizeof(dmsg)); | ||
| 269 | dmsg.device_id = dev->id; | ||
| 270 | strncpy(dmsg.serial_number, dev->serial, 256); | ||
| 271 | dmsg.serial_number[255] = 0; | ||
| 272 | dmsg.location = dev->location; | ||
| 273 | dmsg.product_id = dev->pid; | ||
| 274 | res = send_pkt(client, 0, MESSAGE_DEVICE_ADD, &dmsg, sizeof(dmsg)); | ||
| 275 | } | ||
| 276 | return res; | ||
| 214 | } | 277 | } |
| 215 | 278 | ||
| 216 | static int notify_device_remove(struct mux_client *client, uint32_t device_id) | 279 | static int notify_device_remove(struct mux_client *client, uint32_t device_id) |
| 217 | { | 280 | { |
| 218 | return send_pkt(client, 0, MESSAGE_DEVICE_REMOVE, &device_id, sizeof(uint32_t)); | 281 | int res = -1; |
| 282 | #ifdef HAVE_PLIST | ||
| 283 | if (client->proto_version == 1) { | ||
| 284 | /* XML plist packet */ | ||
| 285 | char *xml = NULL; | ||
| 286 | uint32_t xmlsize = 0; | ||
| 287 | plist_t dict = plist_new_dict(); | ||
| 288 | plist_dict_insert_item(dict, "MessageType", plist_new_string("Detached")); | ||
| 289 | plist_dict_insert_item(dict, "DeviceID", plist_new_uint(device_id)); | ||
| 290 | plist_to_xml(dict, &xml, &xmlsize); | ||
| 291 | plist_free(dict); | ||
| 292 | if (xml) { | ||
| 293 | res = send_pkt(client, 0, MESSAGE_PLIST, xml, xmlsize); | ||
| 294 | free(xml); | ||
| 295 | } else { | ||
| 296 | usbmuxd_log(LL_ERROR, "%s: Could not convert plist to xml", __func__); | ||
| 297 | } | ||
| 298 | } else | ||
| 299 | #endif | ||
| 300 | { | ||
| 301 | /* binary packet */ | ||
| 302 | res = send_pkt(client, 0, MESSAGE_DEVICE_REMOVE, &device_id, sizeof(uint32_t)); | ||
| 303 | } | ||
| 304 | return res; | ||
| 219 | } | 305 | } |
| 220 | 306 | ||
| 221 | static int start_listen(struct mux_client *client) | 307 | static int start_listen(struct mux_client *client) |
| @@ -263,7 +349,92 @@ static int client_command(struct mux_client *client, struct usbmuxd_header *hdr) | |||
| 263 | } | 349 | } |
| 264 | 350 | ||
| 265 | struct usbmuxd_connect_request *ch; | 351 | struct usbmuxd_connect_request *ch; |
| 352 | #ifdef HAVE_PLIST | ||
| 353 | char *payload; | ||
| 354 | uint32_t payload_size; | ||
| 355 | #endif | ||
| 356 | |||
| 266 | switch(hdr->message) { | 357 | switch(hdr->message) { |
| 358 | #ifdef HAVE_PLIST | ||
| 359 | case MESSAGE_PLIST: | ||
| 360 | client->proto_version = 1; | ||
| 361 | payload = (char*)(hdr) + sizeof(struct usbmuxd_header); | ||
| 362 | payload_size = hdr->length - sizeof(struct usbmuxd_header); | ||
| 363 | plist_t dict = NULL; | ||
| 364 | plist_from_xml(payload, payload_size, &dict); | ||
| 365 | if (!dict) { | ||
| 366 | usbmuxd_log(LL_ERROR, "Could not parse plist from payload!"); | ||
| 367 | return -1; | ||
| 368 | } else { | ||
| 369 | char *message = NULL; | ||
| 370 | plist_t node = plist_dict_get_item(dict, "MessageType"); | ||
| 371 | plist_get_string_val(node, &message); | ||
| 372 | if (!message) { | ||
| 373 | usbmuxd_log(LL_ERROR, "Could not extract MessageType from plist!"); | ||
| 374 | plist_free(dict); | ||
| 375 | return -1; | ||
| 376 | } | ||
| 377 | if (!strcmp(message, "Listen")) { | ||
| 378 | free(message); | ||
| 379 | plist_free(dict); | ||
| 380 | if (send_result(client, hdr->tag, 0) < 0) | ||
| 381 | return -1; | ||
| 382 | usbmuxd_log(LL_DEBUG, "Client %d now LISTENING", client->fd); | ||
| 383 | return start_listen(client); | ||
| 384 | } else if (!strcmp(message, "Connect")) { | ||
| 385 | uint64_t val; | ||
| 386 | uint16_t portnum = 0; | ||
| 387 | uint32_t device_id = 0; | ||
| 388 | free(message); | ||
| 389 | // get device id | ||
| 390 | node = plist_dict_get_item(dict, "DeviceID"); | ||
| 391 | if (!node) { | ||
| 392 | usbmuxd_log(LL_ERROR, "Received connect request without device_id!"); | ||
| 393 | plist_free(dict); | ||
| 394 | if (send_result(client, hdr->tag, RESULT_BADDEV) < 0) | ||
| 395 | return -1; | ||
| 396 | return 0; | ||
| 397 | } | ||
| 398 | val = 0; | ||
| 399 | plist_get_uint_val(node, &val); | ||
| 400 | device_id = (uint32_t)val; | ||
| 401 | |||
| 402 | // get port number | ||
| 403 | node = plist_dict_get_item(dict, "PortNumber"); | ||
| 404 | if (!node) { | ||
| 405 | usbmuxd_log(LL_ERROR, "Received connect request without port number!"); | ||
| 406 | plist_free(dict); | ||
| 407 | if (send_result(client, hdr->tag, RESULT_BADCOMMAND) < 0) | ||
| 408 | return -1; | ||
| 409 | return 0; | ||
| 410 | } | ||
| 411 | val = 0; | ||
| 412 | plist_get_uint_val(node, &val); | ||
| 413 | portnum = (uint16_t)val; | ||
| 414 | |||
| 415 | usbmuxd_log(LL_DEBUG, "Client %d connection request to device %d port %d", client->fd, device_id, ntohs(portnum)); | ||
| 416 | res = device_start_connect(device_id, ntohs(portnum), client); | ||
| 417 | if(res < 0) { | ||
| 418 | if (send_result(client, hdr->tag, -res) < 0) | ||
| 419 | return -1; | ||
| 420 | } else { | ||
| 421 | client->connect_tag = hdr->tag; | ||
| 422 | client->connect_device = device_id; | ||
| 423 | client->state = CLIENT_CONNECTING1; | ||
| 424 | } | ||
| 425 | return 0; | ||
| 426 | } else { | ||
| 427 | usbmuxd_log(LL_ERROR, "Unexpected command '%s' received!", message); | ||
| 428 | free(message); | ||
| 429 | plist_free(dict); | ||
| 430 | if (send_result(client, hdr->tag, RESULT_BADCOMMAND) < 0) | ||
| 431 | return -1; | ||
| 432 | return 0; | ||
| 433 | } | ||
| 434 | } | ||
| 435 | // should not be reached?! | ||
| 436 | return -1; | ||
| 437 | #endif | ||
| 267 | case MESSAGE_LISTEN: | 438 | case MESSAGE_LISTEN: |
| 268 | if(send_result(client, hdr->tag, 0) < 0) | 439 | if(send_result(client, hdr->tag, 0) < 0) |
| 269 | return -1; | 440 | return -1; |
| @@ -341,8 +512,13 @@ static void process_recv(struct mux_client *client) | |||
| 341 | did_read = 1; | 512 | did_read = 1; |
| 342 | } | 513 | } |
| 343 | struct usbmuxd_header *hdr = (void*)client->ib_buf; | 514 | struct usbmuxd_header *hdr = (void*)client->ib_buf; |
| 515 | #ifdef HAVE_PLIST | ||
| 516 | if((hdr->version != 0) && (hdr->version != 1)) { | ||
| 517 | usbmuxd_log(LL_INFO, "Client %d version mismatch: expected 0 or 1, got %d", client->fd, hdr->version); | ||
| 518 | #else | ||
| 344 | if(hdr->version != USBMUXD_PROTOCOL_VERSION) { | 519 | if(hdr->version != USBMUXD_PROTOCOL_VERSION) { |
| 345 | usbmuxd_log(LL_INFO, "Client %d version mismatch: expected %d, got %d", client->fd, USBMUXD_PROTOCOL_VERSION, hdr->version); | 520 | usbmuxd_log(LL_INFO, "Client %d version mismatch: expected %d, got %d", client->fd, USBMUXD_PROTOCOL_VERSION, hdr->version); |
| 521 | #endif | ||
| 346 | client_close(client); | 522 | client_close(client); |
| 347 | } | 523 | } |
| 348 | if(hdr->length > client->ib_capacity) { | 524 | if(hdr->length > client->ib_capacity) { |
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 { |
