summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt17
-rw-r--r--daemon/CMakeLists.txt6
-rw-r--r--daemon/client.c198
-rw-r--r--libusbmuxd/CMakeLists.txt6
-rw-r--r--libusbmuxd/libusbmuxd.c201
-rw-r--r--libusbmuxd/usbmuxd-proto.h2
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 "")
set(CMAKE_C_FLAGS "-O2")
endif()
+option(WANT_PLIST "Build with protocol version 1 support using libplist" ON)
+
+set(OPT_INCLUDES "")
+set(OPT_LIBS "")
+if(WANT_PLIST)
+ find_package(PLIST)
+ if(PLIST_FOUND)
+ set(HAVE_PLIST ON)
+ set(OPT_INCLUDES ${OPT_INCLUDES} ${PLIST_INCLUDE_DIRS})
+ set(OPT_LIBS ${OPT_LIBS} ${PLIST_LIBRARIES})
+ else()
+ message("* NOTE: libplist was not found!")
+ message("* libusbmuxd/usbmuxd will be build WITHOUT support for version 1")
+ message("* of the usbmux protocol (plist based).")
+ endif()
+endif()
+
option(WITH_USBMUXD "Build usbmux daemon (usbmuxd)" ON)
if(WIN32 AND WITH_USBMUXD)
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 @@
find_package(USB REQUIRED)
include_directories(${USB_INCLUDE_DIRS})
-set(LIBS ${LIBS} ${USB_LIBRARIES})
-
+set(LIBS ${LIBS} ${USB_LIBRARIES} ${OPT_LIBS})
+if(HAVE_PLIST)
+ message("-- usbmuxd will be built with protocol version 1 support")
+endif()
include_directories (${CMAKE_SOURCE_DIR}/common)
include_directories (${CMAKE_SOURCE_DIR}/daemon)
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
#include <sys/un.h>
#include <arpa/inet.h>
+#ifdef HAVE_PLIST
+#include <plist/plist.h>
+#endif
+
#include "log.h"
#include "usb.h"
#include "client.h"
#include "device.h"
+#ifdef HAVE_PLIST
+#define CMD_BUF_SIZE 1024
+#else
#define CMD_BUF_SIZE 256
+#endif
#define REPLY_BUF_SIZE 1024
enum client_state {
@@ -61,6 +69,7 @@ struct mux_client {
uint32_t connect_tag;
int connect_device;
enum client_state state;
+ uint32_t proto_version;
};
static struct collection client_list;
@@ -155,7 +164,7 @@ void client_get_fds(struct fdlist *list)
static int send_pkt(struct mux_client *client, uint32_t tag, enum usbmuxd_msgtype msg, void *payload, int payload_length)
{
struct usbmuxd_header hdr;
- hdr.version = USBMUXD_PROTOCOL_VERSION;
+ hdr.version = client->proto_version;
hdr.length = sizeof(hdr) + payload_length;
hdr.message = msg;
hdr.tag = tag;
@@ -175,7 +184,30 @@ static int send_pkt(struct mux_client *client, uint32_t tag, enum usbmuxd_msgtyp
static int send_result(struct mux_client *client, uint32_t tag, uint32_t result)
{
- return send_pkt(client, tag, MESSAGE_RESULT, &result, sizeof(uint32_t));
+ int res = -1;
+#ifdef HAVE_PLIST
+ if (client->proto_version == 1) {
+ /* XML plist packet */
+ char *xml = NULL;
+ uint32_t xmlsize = 0;
+ plist_t dict = plist_new_dict();
+ plist_dict_insert_item(dict, "MessageType", plist_new_string("Result"));
+ plist_dict_insert_item(dict, "Number", plist_new_uint(result));
+ plist_to_xml(dict, &xml, &xmlsize);
+ plist_free(dict);
+ if (xml) {
+ res = send_pkt(client, tag, MESSAGE_PLIST, xml, xmlsize);
+ free(xml);
+ } else {
+ usbmuxd_log(LL_ERROR, "%s: Could not convert plist to xml", __func__);
+ }
+ } else
+#endif
+ {
+ /* binary packet */
+ res = send_pkt(client, tag, MESSAGE_RESULT, &result, sizeof(uint32_t));
+ }
+ return res;
}
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)
static int notify_device_add(struct mux_client *client, struct device_info *dev)
{
- struct usbmuxd_device_record dmsg;
- memset(&dmsg, 0, sizeof(dmsg));
- dmsg.device_id = dev->id;
- strncpy(dmsg.serial_number, dev->serial, 256);
- dmsg.serial_number[255] = 0;
- dmsg.location = dev->location;
- dmsg.product_id = dev->pid;
- return send_pkt(client, 0, MESSAGE_DEVICE_ADD, &dmsg, sizeof(dmsg));
+ int res = -1;
+#ifdef HAVE_PLIST
+ if (client->proto_version == 1) {
+ /* XML plist packet */
+ char *xml = NULL;
+ uint32_t xmlsize = 0;
+ plist_t dict = plist_new_dict();
+ plist_dict_insert_item(dict, "MessageType", plist_new_string("Attached"));
+ plist_t props = plist_new_dict();
+ // TODO: get current usb speed
+ plist_dict_insert_item(props, "ConnectionSpeed", plist_new_uint(480000000));
+ plist_dict_insert_item(props, "ConnectionType", plist_new_string("USB"));
+ plist_dict_insert_item(props, "DeviceID", plist_new_uint(dev->id));
+ plist_dict_insert_item(props, "LocationID", plist_new_uint(dev->location));
+ plist_dict_insert_item(props, "ProductID", plist_new_uint(dev->pid));
+ plist_dict_insert_item(props, "SerialNumber", plist_new_string(dev->serial));
+ plist_dict_insert_item(dict, "Properties", props);
+ plist_to_xml(dict, &xml, &xmlsize);
+ plist_free(dict);
+ if (xml) {
+ res = send_pkt(client, 0, MESSAGE_PLIST, xml, xmlsize);
+ free(xml);
+ } else {
+ usbmuxd_log(LL_ERROR, "%s: Could not convert plist to xml", __func__);
+ }
+ } else
+#endif
+ {
+ /* binary packet */
+ struct usbmuxd_device_record dmsg;
+ memset(&dmsg, 0, sizeof(dmsg));
+ dmsg.device_id = dev->id;
+ strncpy(dmsg.serial_number, dev->serial, 256);
+ dmsg.serial_number[255] = 0;
+ dmsg.location = dev->location;
+ dmsg.product_id = dev->pid;
+ res = send_pkt(client, 0, MESSAGE_DEVICE_ADD, &dmsg, sizeof(dmsg));
+ }
+ return res;
}
static int notify_device_remove(struct mux_client *client, uint32_t device_id)
{
- return send_pkt(client, 0, MESSAGE_DEVICE_REMOVE, &device_id, sizeof(uint32_t));
+ int res = -1;
+#ifdef HAVE_PLIST
+ if (client->proto_version == 1) {
+ /* XML plist packet */
+ char *xml = NULL;
+ uint32_t xmlsize = 0;
+ plist_t dict = plist_new_dict();
+ plist_dict_insert_item(dict, "MessageType", plist_new_string("Detached"));
+ plist_dict_insert_item(dict, "DeviceID", plist_new_uint(device_id));
+ plist_to_xml(dict, &xml, &xmlsize);
+ plist_free(dict);
+ if (xml) {
+ res = send_pkt(client, 0, MESSAGE_PLIST, xml, xmlsize);
+ free(xml);
+ } else {
+ usbmuxd_log(LL_ERROR, "%s: Could not convert plist to xml", __func__);
+ }
+ } else
+#endif
+ {
+ /* binary packet */
+ res = send_pkt(client, 0, MESSAGE_DEVICE_REMOVE, &device_id, sizeof(uint32_t));
+ }
+ return res;
}
static int start_listen(struct mux_client *client)
@@ -263,7 +349,92 @@ static int client_command(struct mux_client *client, struct usbmuxd_header *hdr)
}
struct usbmuxd_connect_request *ch;
+#ifdef HAVE_PLIST
+ char *payload;
+ uint32_t payload_size;
+#endif
+
switch(hdr->message) {
+#ifdef HAVE_PLIST
+ case MESSAGE_PLIST:
+ client->proto_version = 1;
+ payload = (char*)(hdr) + sizeof(struct usbmuxd_header);
+ payload_size = hdr->length - sizeof(struct usbmuxd_header);
+ plist_t dict = NULL;
+ plist_from_xml(payload, payload_size, &dict);
+ if (!dict) {
+ usbmuxd_log(LL_ERROR, "Could not parse plist from payload!");
+ return -1;
+ } else {
+ char *message = NULL;
+ plist_t node = plist_dict_get_item(dict, "MessageType");
+ plist_get_string_val(node, &message);
+ if (!message) {
+ usbmuxd_log(LL_ERROR, "Could not extract MessageType from plist!");
+ plist_free(dict);
+ return -1;
+ }
+ if (!strcmp(message, "Listen")) {
+ free(message);
+ plist_free(dict);
+ if (send_result(client, hdr->tag, 0) < 0)
+ return -1;
+ usbmuxd_log(LL_DEBUG, "Client %d now LISTENING", client->fd);
+ return start_listen(client);
+ } else if (!strcmp(message, "Connect")) {
+ uint64_t val;
+ uint16_t portnum = 0;
+ uint32_t device_id = 0;
+ free(message);
+ // get device id
+ node = plist_dict_get_item(dict, "DeviceID");
+ if (!node) {
+ usbmuxd_log(LL_ERROR, "Received connect request without device_id!");
+ plist_free(dict);
+ if (send_result(client, hdr->tag, RESULT_BADDEV) < 0)
+ return -1;
+ return 0;
+ }
+ val = 0;
+ plist_get_uint_val(node, &val);
+ device_id = (uint32_t)val;
+
+ // get port number
+ node = plist_dict_get_item(dict, "PortNumber");
+ if (!node) {
+ usbmuxd_log(LL_ERROR, "Received connect request without port number!");
+ plist_free(dict);
+ if (send_result(client, hdr->tag, RESULT_BADCOMMAND) < 0)
+ return -1;
+ return 0;
+ }
+ val = 0;
+ plist_get_uint_val(node, &val);
+ portnum = (uint16_t)val;
+
+ usbmuxd_log(LL_DEBUG, "Client %d connection request to device %d port %d", client->fd, device_id, ntohs(portnum));
+ res = device_start_connect(device_id, ntohs(portnum), client);
+ if(res < 0) {
+ if (send_result(client, hdr->tag, -res) < 0)
+ return -1;
+ } else {
+ client->connect_tag = hdr->tag;
+ client->connect_device = device_id;
+ client->state = CLIENT_CONNECTING1;
+ }
+ return 0;
+ } else {
+ usbmuxd_log(LL_ERROR, "Unexpected command '%s' received!", message);
+ free(message);
+ plist_free(dict);
+ if (send_result(client, hdr->tag, RESULT_BADCOMMAND) < 0)
+ return -1;
+ return 0;
+ }
+ }
+ // should not be reached?!
+ return -1;
+#endif
case MESSAGE_LISTEN:
if(send_result(client, hdr->tag, 0) < 0)
return -1;
@@ -341,8 +512,13 @@ static void process_recv(struct mux_client *client)
did_read = 1;
}
struct usbmuxd_header *hdr = (void*)client->ib_buf;
+#ifdef HAVE_PLIST
+ if((hdr->version != 0) && (hdr->version != 1)) {
+ usbmuxd_log(LL_INFO, "Client %d version mismatch: expected 0 or 1, got %d", client->fd, hdr->version);
+#else
if(hdr->version != USBMUXD_PROTOCOL_VERSION) {
usbmuxd_log(LL_INFO, "Client %d version mismatch: expected %d, got %d", client->fd, USBMUXD_PROTOCOL_VERSION, hdr->version);
+#endif
client_close(client);
}
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)
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 {