|
Packit |
f228a3 |
/*
|
|
Packit |
f228a3 |
* libusbmuxd.c
|
|
Packit |
f228a3 |
*
|
|
Packit |
f228a3 |
* Copyright (C) 2009-2014 Martin Szulecki <m.szulecki@libimobiledevice.org>
|
|
Packit |
f228a3 |
* Copyright (C) 2009-2014 Nikias Bassen <nikias@gmx.li>
|
|
Packit |
f228a3 |
* Copyright (C) 2009 Paul Sladen <libiphone@paul.sladen.org>
|
|
Packit |
f228a3 |
*
|
|
Packit |
f228a3 |
* This library is free software; you can redistribute it and/or
|
|
Packit |
f228a3 |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
f228a3 |
* License as published by the Free Software Foundation; either
|
|
Packit |
f228a3 |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
f228a3 |
*
|
|
Packit |
f228a3 |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
f228a3 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
f228a3 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
f228a3 |
* Lesser General Public License for more details.
|
|
Packit |
f228a3 |
*
|
|
Packit |
f228a3 |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
f228a3 |
* License along with this library; if not, write to the Free Software
|
|
Packit |
f228a3 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
Packit |
f228a3 |
*/
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
#include <stdint.h>
|
|
Packit |
f228a3 |
#include <stdlib.h>
|
|
Packit |
f228a3 |
#include <errno.h>
|
|
Packit |
f228a3 |
#include <stdio.h>
|
|
Packit |
f228a3 |
#include <string.h>
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
f228a3 |
#include <config.h>
|
|
Packit |
f228a3 |
#endif
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
#ifdef WIN32
|
|
Packit |
f228a3 |
#define USBMUXD_API __declspec( dllexport )
|
|
Packit |
f228a3 |
#else
|
|
Packit |
f228a3 |
#ifdef HAVE_FVISIBILITY
|
|
Packit |
f228a3 |
#define USBMUXD_API __attribute__((visibility("default")))
|
|
Packit |
f228a3 |
#else
|
|
Packit |
f228a3 |
#define USBMUXD_API
|
|
Packit |
f228a3 |
#endif
|
|
Packit |
f228a3 |
#endif
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
#ifdef WIN32
|
|
Packit |
f228a3 |
#include <windows.h>
|
|
Packit |
f228a3 |
#include <winsock2.h>
|
|
Packit |
f228a3 |
#define sleep(x) Sleep(x*1000)
|
|
Packit |
f228a3 |
#ifndef EPROTO
|
|
Packit |
f228a3 |
#define EPROTO 134
|
|
Packit |
f228a3 |
#endif
|
|
Packit |
f228a3 |
#ifndef EBADMSG
|
|
Packit |
f228a3 |
#define EBADMSG 104
|
|
Packit |
f228a3 |
#endif
|
|
Packit |
f228a3 |
#else
|
|
Packit |
f228a3 |
#include <sys/socket.h>
|
|
Packit |
f228a3 |
#include <arpa/inet.h>
|
|
Packit |
f228a3 |
#include <pthread.h>
|
|
Packit |
f228a3 |
#endif
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
#ifdef HAVE_INOTIFY
|
|
Packit |
f228a3 |
#include <sys/inotify.h>
|
|
Packit |
f228a3 |
#define EVENT_SIZE (sizeof (struct inotify_event))
|
|
Packit |
f228a3 |
#define EVENT_BUF_LEN (1024 * (EVENT_SIZE + 16))
|
|
Packit |
f228a3 |
#define USBMUXD_DIRNAME "/var/run"
|
|
Packit |
f228a3 |
#define USBMUXD_SOCKET_NAME "usbmuxd"
|
|
Packit |
f228a3 |
#endif /* HAVE_INOTIFY */
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
#include <unistd.h>
|
|
Packit |
f228a3 |
#include <signal.h>
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
#include <plist/plist.h>
|
|
Packit |
f228a3 |
#define PLIST_BUNDLE_ID "org.libimobiledevice.usbmuxd"
|
|
Packit |
f228a3 |
#define PLIST_CLIENT_VERSION_STRING "usbmuxd built for freedom"
|
|
Packit |
f228a3 |
#define PLIST_PROGNAME "libusbmuxd"
|
|
Packit |
f228a3 |
#define PLIST_LIBUSBMUX_VERSION 3
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
// usbmuxd public interface
|
|
Packit |
f228a3 |
#include "usbmuxd.h"
|
|
Packit |
f228a3 |
// usbmuxd protocol
|
|
Packit |
f228a3 |
#include "usbmuxd-proto.h"
|
|
Packit |
f228a3 |
// socket utility functions
|
|
Packit |
f228a3 |
#include "socket.h"
|
|
Packit |
f228a3 |
// misc utility functions
|
|
Packit |
f228a3 |
#include "collection.h"
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
static int libusbmuxd_debug = 0;
|
|
Packit |
f228a3 |
#define DEBUG(x, y, ...) if (x <= libusbmuxd_debug) fprintf(stderr, (y), __VA_ARGS__); fflush(stderr);
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
static struct collection devices;
|
|
Packit |
f228a3 |
static usbmuxd_event_cb_t event_cb = NULL;
|
|
Packit |
f228a3 |
#ifdef WIN32
|
|
Packit |
f228a3 |
HANDLE devmon = NULL;
|
|
Packit |
f228a3 |
#else
|
|
Packit |
f228a3 |
pthread_t devmon;
|
|
Packit |
f228a3 |
#endif
|
|
Packit |
f228a3 |
static int listenfd = -1;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
static volatile int use_tag = 0;
|
|
Packit |
f228a3 |
static volatile int proto_version = 1;
|
|
Packit |
f228a3 |
static volatile int try_list_devices = 1;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
/**
|
|
Packit |
f228a3 |
* Finds a device info record by its handle.
|
|
Packit |
f228a3 |
* if the record is not found, NULL is returned.
|
|
Packit |
f228a3 |
*/
|
|
Packit |
f228a3 |
static usbmuxd_device_info_t *devices_find(uint32_t handle)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
FOREACH(usbmuxd_device_info_t *dev, &devices) {
|
|
Packit |
f228a3 |
if (dev && dev->handle == handle) {
|
|
Packit |
f228a3 |
return dev;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
} ENDFOREACH
|
|
Packit |
f228a3 |
return NULL;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
/**
|
|
Packit |
f228a3 |
* Creates a socket connection to usbmuxd.
|
|
Packit |
f228a3 |
* For Mac/Linux it is a unix domain socket,
|
|
Packit |
f228a3 |
* for Windows it is a tcp socket.
|
|
Packit |
f228a3 |
*/
|
|
Packit |
f228a3 |
static int connect_usbmuxd_socket()
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
#if defined(WIN32) || defined(__CYGWIN__)
|
|
Packit |
f228a3 |
return socket_connect("127.0.0.1", USBMUXD_SOCKET_PORT);
|
|
Packit |
f228a3 |
#else
|
|
Packit |
f228a3 |
return socket_connect_unix(USBMUXD_SOCKET_FILE);
|
|
Packit |
f228a3 |
#endif
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
static struct usbmuxd_device_record* device_record_from_plist(plist_t props)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
struct usbmuxd_device_record* dev = NULL;
|
|
Packit |
f228a3 |
plist_t n = NULL;
|
|
Packit |
f228a3 |
uint64_t val = 0;
|
|
Packit |
f228a3 |
char *strval = NULL;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
dev = (struct usbmuxd_device_record*)malloc(sizeof(struct usbmuxd_device_record));
|
|
Packit |
f228a3 |
if (!dev)
|
|
Packit |
f228a3 |
return NULL;
|
|
Packit |
f228a3 |
memset(dev, 0, sizeof(struct usbmuxd_device_record));
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
n = plist_dict_get_item(props, "DeviceID");
|
|
Packit |
f228a3 |
if (n && plist_get_node_type(n) == PLIST_UINT) {
|
|
Packit |
f228a3 |
plist_get_uint_val(n, &val;;
|
|
Packit |
f228a3 |
dev->device_id = (uint32_t)val;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
n = plist_dict_get_item(props, "ProductID");
|
|
Packit |
f228a3 |
if (n && plist_get_node_type(n) == PLIST_UINT) {
|
|
Packit |
f228a3 |
plist_get_uint_val(n, &val;;
|
|
Packit |
f228a3 |
dev->product_id = (uint32_t)val;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
n = plist_dict_get_item(props, "SerialNumber");
|
|
Packit |
f228a3 |
if (n && plist_get_node_type(n) == PLIST_STRING) {
|
|
Packit |
f228a3 |
plist_get_string_val(n, &strval);
|
|
Packit |
f228a3 |
if (strval) {
|
|
Packit |
f228a3 |
strncpy(dev->serial_number, strval, 255);
|
|
Packit |
f228a3 |
free(strval);
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
n = plist_dict_get_item(props, "LocationID");
|
|
Packit |
f228a3 |
if (n && plist_get_node_type(n) == PLIST_UINT) {
|
|
Packit |
f228a3 |
plist_get_uint_val(n, &val;;
|
|
Packit |
f228a3 |
dev->location = (uint32_t)val;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
return dev;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
static int receive_packet(int sfd, struct usbmuxd_header *header, void **payload, int timeout)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
int recv_len;
|
|
Packit |
f228a3 |
struct usbmuxd_header hdr;
|
|
Packit |
f228a3 |
char *payload_loc = NULL;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
header->length = 0;
|
|
Packit |
f228a3 |
header->version = 0;
|
|
Packit |
f228a3 |
header->message = 0;
|
|
Packit |
f228a3 |
header->tag = 0;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
recv_len = socket_receive_timeout(sfd, &hdr, sizeof(hdr), 0, timeout);
|
|
Packit |
f228a3 |
if (recv_len < 0) {
|
|
Packit |
f228a3 |
return recv_len;
|
|
Packit |
f228a3 |
} else if ((size_t)recv_len < sizeof(hdr)) {
|
|
Packit |
f228a3 |
return recv_len;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
uint32_t payload_size = hdr.length - sizeof(hdr);
|
|
Packit |
f228a3 |
if (payload_size > 0) {
|
|
Packit |
f228a3 |
payload_loc = (char*)malloc(payload_size);
|
|
Packit |
f228a3 |
uint32_t rsize = 0;
|
|
Packit |
f228a3 |
do {
|
|
Packit |
f228a3 |
int res = socket_receive_timeout(sfd, payload_loc + rsize, payload_size - rsize, 0, 5000);
|
|
Packit |
f228a3 |
if (res < 0) {
|
|
Packit |
f228a3 |
break;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
rsize += res;
|
|
Packit |
f228a3 |
} while (rsize < payload_size);
|
|
Packit |
f228a3 |
if (rsize != payload_size) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Error receiving payload of size %d (bytes received: %d)\n", __func__, payload_size, rsize);
|
|
Packit |
f228a3 |
free(payload_loc);
|
|
Packit |
f228a3 |
return -EBADMSG;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
if (hdr.message == MESSAGE_PLIST) {
|
|
Packit |
f228a3 |
char *message = NULL;
|
|
Packit |
f228a3 |
plist_t plist = NULL;
|
|
Packit |
f228a3 |
plist_from_xml(payload_loc, payload_size, &plist);
|
|
Packit |
f228a3 |
free(payload_loc);
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
if (!plist) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Error getting plist from payload!\n", __func__);
|
|
Packit |
f228a3 |
return -EBADMSG;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
plist_t node = plist_dict_get_item(plist, "MessageType");
|
|
Packit |
f228a3 |
if (!node || plist_get_node_type(node) != PLIST_STRING) {
|
|
Packit |
f228a3 |
*payload = plist;
|
|
Packit |
f228a3 |
hdr.length = sizeof(hdr);
|
|
Packit |
f228a3 |
memcpy(header, &hdr, sizeof(hdr));
|
|
Packit |
f228a3 |
return hdr.length;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
plist_get_string_val(node, &message);
|
|
Packit |
f228a3 |
if (message) {
|
|
Packit |
f228a3 |
uint64_t val = 0;
|
|
Packit |
f228a3 |
if (strcmp(message, "Result") == 0) {
|
|
Packit |
f228a3 |
/* result message */
|
|
Packit |
f228a3 |
uint32_t dwval = 0;
|
|
Packit |
f228a3 |
plist_t n = plist_dict_get_item(plist, "Number");
|
|
Packit |
f228a3 |
plist_get_uint_val(n, &val;;
|
|
Packit |
f228a3 |
*payload = malloc(sizeof(uint32_t));
|
|
Packit |
f228a3 |
dwval = val;
|
|
Packit |
f228a3 |
memcpy(*payload, &dwval, sizeof(dwval));
|
|
Packit |
f228a3 |
hdr.length = sizeof(hdr) + sizeof(dwval);
|
|
Packit |
f228a3 |
hdr.message = MESSAGE_RESULT;
|
|
Packit |
f228a3 |
} else if (strcmp(message, "Attached") == 0) {
|
|
Packit |
f228a3 |
/* device add message */
|
|
Packit |
f228a3 |
struct usbmuxd_device_record *dev = NULL;
|
|
Packit |
f228a3 |
plist_t props = plist_dict_get_item(plist, "Properties");
|
|
Packit |
f228a3 |
if (!props) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Could not get properties for message '%s' from plist!\n", __func__, message);
|
|
Packit |
f228a3 |
free(message);
|
|
Packit |
f228a3 |
plist_free(plist);
|
|
Packit |
f228a3 |
return -EBADMSG;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
dev = device_record_from_plist(props);
|
|
Packit |
f228a3 |
if (!dev) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Could not create device record object from properties!\n", __func__);
|
|
Packit |
f228a3 |
free(message);
|
|
Packit |
f228a3 |
plist_free(plist);
|
|
Packit |
f228a3 |
return -EBADMSG;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
*payload = (void*)dev;
|
|
Packit |
f228a3 |
hdr.length = sizeof(hdr) + sizeof(struct usbmuxd_device_record);
|
|
Packit |
f228a3 |
hdr.message = MESSAGE_DEVICE_ADD;
|
|
Packit |
f228a3 |
} else if (strcmp(message, "Detached") == 0) {
|
|
Packit |
f228a3 |
/* device remove message */
|
|
Packit |
f228a3 |
uint32_t dwval = 0;
|
|
Packit |
f228a3 |
plist_t n = plist_dict_get_item(plist, "DeviceID");
|
|
Packit |
f228a3 |
if (n) {
|
|
Packit |
f228a3 |
plist_get_uint_val(n, &val;;
|
|
Packit |
f228a3 |
*payload = malloc(sizeof(uint32_t));
|
|
Packit |
f228a3 |
dwval = val;
|
|
Packit |
f228a3 |
memcpy(*payload, &dwval, sizeof(dwval));
|
|
Packit |
f228a3 |
hdr.length = sizeof(hdr) + sizeof(dwval);
|
|
Packit |
f228a3 |
hdr.message = MESSAGE_DEVICE_REMOVE;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
} else {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Unexpected message '%s' in plist!\n", __func__, message);
|
|
Packit |
f228a3 |
free(message);
|
|
Packit |
f228a3 |
plist_free(plist);
|
|
Packit |
f228a3 |
return -EBADMSG;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
free(message);
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
plist_free(plist);
|
|
Packit |
f228a3 |
} else {
|
|
Packit |
f228a3 |
*payload = payload_loc;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
memcpy(header, &hdr, sizeof(hdr));
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
return hdr.length;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
/**
|
|
Packit |
f228a3 |
* Retrieves the result code to a previously sent request.
|
|
Packit |
f228a3 |
*/
|
|
Packit |
f228a3 |
static int usbmuxd_get_result(int sfd, uint32_t tag, uint32_t *result, void **result_plist)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
struct usbmuxd_header hdr;
|
|
Packit |
f228a3 |
int recv_len;
|
|
Packit |
f228a3 |
uint32_t *res = NULL;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
if (!result) {
|
|
Packit |
f228a3 |
return -EINVAL;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
*result = -1;
|
|
Packit |
f228a3 |
if (result_plist) {
|
|
Packit |
f228a3 |
*result_plist = NULL;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
if ((recv_len = receive_packet(sfd, &hdr, (void**)&res, 5000)) < 0) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Error receiving packet: %d\n", __func__, recv_len);
|
|
Packit |
f228a3 |
if (res)
|
|
Packit |
f228a3 |
free(res);
|
|
Packit |
f228a3 |
return recv_len;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
if ((size_t)recv_len < sizeof(hdr)) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Received packet is too small!\n", __func__);
|
|
Packit |
f228a3 |
if (res)
|
|
Packit |
f228a3 |
free(res);
|
|
Packit |
f228a3 |
return -EPROTO;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
if (hdr.message == MESSAGE_RESULT) {
|
|
Packit |
f228a3 |
int ret = 0;
|
|
Packit |
f228a3 |
if (hdr.tag != tag) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: WARNING: tag mismatch (%d != %d). Proceeding anyway.\n", __func__, hdr.tag, tag);
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
if (res) {
|
|
Packit |
f228a3 |
memcpy(result, res, sizeof(uint32_t));
|
|
Packit |
f228a3 |
ret = 1;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
if (res)
|
|
Packit |
f228a3 |
free(res);
|
|
Packit |
f228a3 |
return ret;
|
|
Packit |
f228a3 |
} else if (hdr.message == MESSAGE_PLIST) {
|
|
Packit |
f228a3 |
if (!result_plist) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: MESSAGE_PLIST result but result_plist pointer is NULL!\n", __func__);
|
|
Packit |
f228a3 |
return -1;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
*result_plist = (plist_t)res;
|
|
Packit |
f228a3 |
*result = RESULT_OK;
|
|
Packit |
f228a3 |
return 1;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Unexpected message of type %d received!\n", __func__, hdr.message);
|
|
Packit |
f228a3 |
if (res)
|
|
Packit |
f228a3 |
free(res);
|
|
Packit |
f228a3 |
return -EPROTO;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
static int send_packet(int sfd, uint32_t message, uint32_t tag, void *payload, uint32_t payload_size)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
struct usbmuxd_header header;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
header.length = sizeof(struct usbmuxd_header);
|
|
Packit |
f228a3 |
header.version = proto_version;
|
|
Packit |
f228a3 |
header.message = message;
|
|
Packit |
f228a3 |
header.tag = tag;
|
|
Packit |
f228a3 |
if (payload && (payload_size > 0)) {
|
|
Packit |
f228a3 |
header.length += payload_size;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
int sent = socket_send(sfd, &header, sizeof(header));
|
|
Packit |
f228a3 |
if (sent != sizeof(header)) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: ERROR: could not send packet header\n", __func__);
|
|
Packit |
f228a3 |
return -1;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
if (payload && (payload_size > 0)) {
|
|
Packit |
f228a3 |
uint32_t ssize = 0;
|
|
Packit |
f228a3 |
do {
|
|
Packit |
f228a3 |
int res = socket_send(sfd, (char*)payload + ssize, payload_size - ssize);
|
|
Packit |
f228a3 |
if (res < 0) {
|
|
Packit |
f228a3 |
break;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
ssize += res;
|
|
Packit |
f228a3 |
} while (ssize < payload_size);
|
|
Packit |
f228a3 |
sent += ssize;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
if (sent != (int)header.length) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: ERROR: could not send whole packet (sent %d of %d)\n", __func__, sent, header.length);
|
|
Packit |
f228a3 |
socket_close(sfd);
|
|
Packit |
f228a3 |
return -1;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
return sent;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
static int send_plist_packet(int sfd, uint32_t tag, plist_t message)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
int res;
|
|
Packit |
f228a3 |
char *payload = NULL;
|
|
Packit |
f228a3 |
uint32_t payload_size = 0;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
plist_to_xml(message, &payload, &payload_size);
|
|
Packit |
f228a3 |
res = send_packet(sfd, MESSAGE_PLIST, tag, payload, payload_size);
|
|
Packit |
f228a3 |
free(payload);
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
return res;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
static plist_t create_plist_message(const char* message_type)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
plist_t plist = plist_new_dict();
|
|
Packit |
f228a3 |
plist_dict_set_item(plist, "BundleID", plist_new_string(PLIST_BUNDLE_ID));
|
|
Packit |
f228a3 |
plist_dict_set_item(plist, "ClientVersionString", plist_new_string(PLIST_CLIENT_VERSION_STRING));
|
|
Packit |
f228a3 |
plist_dict_set_item(plist, "MessageType", plist_new_string(message_type));
|
|
Packit |
f228a3 |
plist_dict_set_item(plist, "ProgName", plist_new_string(PLIST_PROGNAME));
|
|
Packit |
f228a3 |
plist_dict_set_item(plist, "kLibUSBMuxVersion", plist_new_uint(PLIST_LIBUSBMUX_VERSION));
|
|
Packit |
f228a3 |
return plist;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
static int send_listen_packet(int sfd, uint32_t tag)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
int res = 0;
|
|
Packit |
f228a3 |
if (proto_version == 1) {
|
|
Packit |
f228a3 |
/* construct message plist */
|
|
Packit |
f228a3 |
plist_t plist = create_plist_message("Listen");
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
res = send_plist_packet(sfd, tag, plist);
|
|
Packit |
f228a3 |
plist_free(plist);
|
|
Packit |
f228a3 |
} else {
|
|
Packit |
f228a3 |
/* binary packet */
|
|
Packit |
f228a3 |
res = send_packet(sfd, MESSAGE_LISTEN, tag, NULL, 0);
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
return res;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
static int send_connect_packet(int sfd, uint32_t tag, uint32_t device_id, uint16_t port)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
int res = 0;
|
|
Packit |
f228a3 |
if (proto_version == 1) {
|
|
Packit |
f228a3 |
/* construct message plist */
|
|
Packit |
f228a3 |
plist_t plist = create_plist_message("Connect");
|
|
Packit |
f228a3 |
plist_dict_set_item(plist, "DeviceID", plist_new_uint(device_id));
|
|
Packit |
f228a3 |
plist_dict_set_item(plist, "PortNumber", plist_new_uint(htons(port)));
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
res = send_plist_packet(sfd, tag, plist);
|
|
Packit |
f228a3 |
plist_free(plist);
|
|
Packit |
f228a3 |
} else {
|
|
Packit |
f228a3 |
/* binary packet */
|
|
Packit |
f228a3 |
struct {
|
|
Packit |
f228a3 |
uint32_t device_id;
|
|
Packit |
f228a3 |
uint16_t port;
|
|
Packit |
f228a3 |
uint16_t reserved;
|
|
Packit |
f228a3 |
} conninfo;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
conninfo.device_id = device_id;
|
|
Packit |
f228a3 |
conninfo.port = htons(port);
|
|
Packit |
f228a3 |
conninfo.reserved = 0;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
res = send_packet(sfd, MESSAGE_CONNECT, tag, &conninfo, sizeof(conninfo));
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
return res;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
static int send_list_devices_packet(int sfd, uint32_t tag)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
int res = -1;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
/* construct message plist */
|
|
Packit |
f228a3 |
plist_t plist = create_plist_message("ListDevices");
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
res = send_plist_packet(sfd, tag, plist);
|
|
Packit |
f228a3 |
plist_free(plist);
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
return res;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
static int send_read_buid_packet(int sfd, uint32_t tag)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
int res = -1;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
/* construct message plist */
|
|
Packit |
f228a3 |
plist_t plist = create_plist_message("ReadBUID");
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
res = send_plist_packet(sfd, tag, plist);
|
|
Packit |
f228a3 |
plist_free(plist);
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
return res;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
static int send_pair_record_packet(int sfd, uint32_t tag, const char* msgtype, const char* pair_record_id, plist_t data)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
int res = -1;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
/* construct message plist */
|
|
Packit |
f228a3 |
plist_t plist = create_plist_message(msgtype);
|
|
Packit |
f228a3 |
plist_dict_set_item(plist, "PairRecordID", plist_new_string(pair_record_id));
|
|
Packit |
f228a3 |
if (data) {
|
|
Packit |
f228a3 |
plist_dict_set_item(plist, "PairRecordData", plist_copy(data));
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
res = send_plist_packet(sfd, tag, plist);
|
|
Packit |
f228a3 |
plist_free(plist);
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
return res;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
/**
|
|
Packit |
f228a3 |
* Generates an event, i.e. calls the callback function.
|
|
Packit |
f228a3 |
* A reference to a populated usbmuxd_event_t with information about the event
|
|
Packit |
f228a3 |
* and the corresponding device will be passed to the callback function.
|
|
Packit |
f228a3 |
*/
|
|
Packit |
f228a3 |
static void generate_event(usbmuxd_event_cb_t callback, const usbmuxd_device_info_t *dev, enum usbmuxd_event_type event, void *user_data)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
usbmuxd_event_t ev;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
if (!callback || !dev) {
|
|
Packit |
f228a3 |
return;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
ev.event = event;
|
|
Packit |
f228a3 |
memcpy(&ev.device, dev, sizeof(usbmuxd_device_info_t));
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
callback(&ev, user_data);
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
static int usbmuxd_listen_poll()
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
int sfd;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
sfd = connect_usbmuxd_socket();
|
|
Packit |
f228a3 |
if (sfd < 0) {
|
|
Packit |
f228a3 |
while (event_cb) {
|
|
Packit |
f228a3 |
if ((sfd = connect_usbmuxd_socket()) >= 0) {
|
|
Packit |
f228a3 |
break;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
sleep(1);
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
return sfd;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
#ifdef HAVE_INOTIFY
|
|
Packit |
f228a3 |
static int use_inotify = 1;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
static int usbmuxd_listen_inotify()
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
int inot_fd;
|
|
Packit |
f228a3 |
int watch_d;
|
|
Packit |
f228a3 |
int sfd;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
if (!use_inotify) {
|
|
Packit |
f228a3 |
return -2;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
sfd = connect_usbmuxd_socket();
|
|
Packit |
f228a3 |
if (sfd >= 0)
|
|
Packit |
f228a3 |
return sfd;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
sfd = -1;
|
|
Packit |
f228a3 |
inot_fd = inotify_init ();
|
|
Packit |
f228a3 |
if (inot_fd < 0) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Failed to setup inotify\n", __func__);
|
|
Packit |
f228a3 |
return -2;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
/* inotify is setup, listen for events that concern us */
|
|
Packit |
f228a3 |
watch_d = inotify_add_watch (inot_fd, USBMUXD_DIRNAME, IN_CREATE);
|
|
Packit |
f228a3 |
if (watch_d < 0) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Failed to setup watch descriptor for socket dir\n", __func__);
|
|
Packit |
f228a3 |
close (inot_fd);
|
|
Packit |
f228a3 |
return -2;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
while (1) {
|
|
Packit |
f228a3 |
ssize_t len, i;
|
|
Packit |
f228a3 |
char buff[EVENT_BUF_LEN] = {0};
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
i = 0;
|
|
Packit |
f228a3 |
len = read (inot_fd, buff, EVENT_BUF_LEN -1);
|
|
Packit |
f228a3 |
if (len < 0)
|
|
Packit |
f228a3 |
goto end;
|
|
Packit |
f228a3 |
while (i < len) {
|
|
Packit |
f228a3 |
struct inotify_event *pevent = (struct inotify_event *) & buff[i];
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
/* check that it's ours */
|
|
Packit |
f228a3 |
if (pevent->mask & IN_CREATE &&
|
|
Packit |
f228a3 |
pevent->len &&
|
|
Packit |
f228a3 |
pevent->name[0] != 0 &&
|
|
Packit |
f228a3 |
strcmp(pevent->name, USBMUXD_SOCKET_NAME) == 0) {
|
|
Packit |
f228a3 |
/* retry if usbmuxd isn't ready yet */
|
|
Packit |
f228a3 |
int retry = 10;
|
|
Packit |
f228a3 |
while (--retry >= 0) {
|
|
Packit |
f228a3 |
if ((sfd = connect_usbmuxd_socket ()) >= 0) {
|
|
Packit |
f228a3 |
break;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
sleep(1);
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
goto end;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
i += EVENT_SIZE + pevent->len;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
end:
|
|
Packit |
f228a3 |
inotify_rm_watch(inot_fd, watch_d);
|
|
Packit |
f228a3 |
close(inot_fd);
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
return sfd;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
#endif /* HAVE_INOTIFY */
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
/**
|
|
Packit |
f228a3 |
* Tries to connect to usbmuxd and wait if it is not running.
|
|
Packit |
f228a3 |
*/
|
|
Packit |
f228a3 |
static int usbmuxd_listen()
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
int sfd;
|
|
Packit |
f228a3 |
uint32_t res = -1;
|
|
Packit |
f228a3 |
int tag;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
retry:
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
#ifdef HAVE_INOTIFY
|
|
Packit |
f228a3 |
sfd = usbmuxd_listen_inotify();
|
|
Packit |
f228a3 |
if (sfd == -2)
|
|
Packit |
f228a3 |
sfd = usbmuxd_listen_poll();
|
|
Packit |
f228a3 |
#else
|
|
Packit |
f228a3 |
sfd = usbmuxd_listen_poll();
|
|
Packit |
f228a3 |
#endif
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
if (sfd < 0) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: ERROR: usbmuxd was supposed to be running here...\n", __func__);
|
|
Packit |
f228a3 |
return sfd;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
tag = ++use_tag;
|
|
Packit |
f228a3 |
if (send_listen_packet(sfd, tag) <= 0) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: ERROR: could not send listen packet\n", __func__);
|
|
Packit |
f228a3 |
socket_close(sfd);
|
|
Packit |
f228a3 |
return -1;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
if ((usbmuxd_get_result(sfd, tag, &res, NULL) == 1) && (res != 0)) {
|
|
Packit |
f228a3 |
socket_close(sfd);
|
|
Packit |
f228a3 |
if ((res == RESULT_BADVERSION) && (proto_version == 1)) {
|
|
Packit |
f228a3 |
proto_version = 0;
|
|
Packit |
f228a3 |
goto retry;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
DEBUG(1, "%s: ERROR: did not get OK but %d\n", __func__, res);
|
|
Packit |
f228a3 |
return -1;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
return sfd;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
/**
|
|
Packit |
f228a3 |
* Waits for an event to occur, i.e. a packet coming from usbmuxd.
|
|
Packit |
f228a3 |
* Calls generate_event to pass the event via callback to the client program.
|
|
Packit |
f228a3 |
*/
|
|
Packit |
f228a3 |
static int get_next_event(int sfd, usbmuxd_event_cb_t callback, void *user_data)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
struct usbmuxd_header hdr;
|
|
Packit |
f228a3 |
void *payload = NULL;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
/* block until we receive something */
|
|
Packit |
f228a3 |
if (receive_packet(sfd, &hdr, &payload, 0) < 0) {
|
|
Packit |
f228a3 |
// when then usbmuxd connection fails,
|
|
Packit |
f228a3 |
// generate remove events for every device that
|
|
Packit |
f228a3 |
// is still present so applications know about it
|
|
Packit |
f228a3 |
FOREACH(usbmuxd_device_info_t *dev, &devices) {
|
|
Packit |
f228a3 |
generate_event(callback, dev, UE_DEVICE_REMOVE, user_data);
|
|
Packit |
f228a3 |
collection_remove(&devices, dev);
|
|
Packit |
f228a3 |
free(dev);
|
|
Packit |
f228a3 |
} ENDFOREACH
|
|
Packit |
f228a3 |
return -EIO;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
if ((hdr.length > sizeof(hdr)) && !payload) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Invalid packet received, payload is missing!\n", __func__);
|
|
Packit |
f228a3 |
return -EBADMSG;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
if (hdr.message == MESSAGE_DEVICE_ADD) {
|
|
Packit |
f228a3 |
struct usbmuxd_device_record *dev = payload;
|
|
Packit |
f228a3 |
usbmuxd_device_info_t *devinfo = (usbmuxd_device_info_t*)malloc(sizeof(usbmuxd_device_info_t));
|
|
Packit |
f228a3 |
if (!devinfo) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Out of memory!\n", __func__);
|
|
Packit |
f228a3 |
free(payload);
|
|
Packit |
f228a3 |
return -1;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
devinfo->handle = dev->device_id;
|
|
Packit |
f228a3 |
devinfo->product_id = dev->product_id;
|
|
Packit |
f228a3 |
memset(devinfo->udid, '\0', sizeof(devinfo->udid));
|
|
Packit |
f228a3 |
memcpy(devinfo->udid, dev->serial_number, sizeof(devinfo->udid));
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
if (strcasecmp(devinfo->udid, "ffffffffffffffffffffffffffffffffffffffff") == 0) {
|
|
Packit |
f228a3 |
sprintf(devinfo->udid + 32, "%08x", devinfo->handle);
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
collection_add(&devices, devinfo);
|
|
Packit |
f228a3 |
generate_event(callback, devinfo, UE_DEVICE_ADD, user_data);
|
|
Packit |
f228a3 |
} else if (hdr.message == MESSAGE_DEVICE_REMOVE) {
|
|
Packit |
f228a3 |
uint32_t handle;
|
|
Packit |
f228a3 |
usbmuxd_device_info_t *devinfo;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
memcpy(&handle, payload, sizeof(uint32_t));
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
devinfo = devices_find(handle);
|
|
Packit |
f228a3 |
if (!devinfo) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: WARNING: got device remove message for handle %d, but couldn't find the corresponding handle in the device list. This event will be ignored.\n", __func__, handle);
|
|
Packit |
f228a3 |
} else {
|
|
Packit |
f228a3 |
generate_event(callback, devinfo, UE_DEVICE_REMOVE, user_data);
|
|
Packit |
f228a3 |
collection_remove(&devices, devinfo);
|
|
Packit |
f228a3 |
free(devinfo);
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
} else if (hdr.length > 0) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Unexpected message type %d length %d received!\n", __func__, hdr.message, hdr.length);
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
if (payload) {
|
|
Packit |
f228a3 |
free(payload);
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
return 0;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
static void device_monitor_cleanup(void* data)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
FOREACH(usbmuxd_device_info_t *dev, &devices) {
|
|
Packit |
f228a3 |
collection_remove(&devices, dev);
|
|
Packit |
f228a3 |
free(dev);
|
|
Packit |
f228a3 |
} ENDFOREACH
|
|
Packit |
f228a3 |
collection_free(&devices);
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
socket_close(listenfd);
|
|
Packit |
f228a3 |
listenfd = -1;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
/**
|
|
Packit |
f228a3 |
* Device Monitor thread function.
|
|
Packit |
f228a3 |
*
|
|
Packit |
f228a3 |
* This function sets up a connection to usbmuxd
|
|
Packit |
f228a3 |
*/
|
|
Packit |
f228a3 |
static void *device_monitor(void *data)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
collection_init(&devices);
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
#ifndef WIN32
|
|
Packit |
f228a3 |
pthread_cleanup_push(device_monitor_cleanup, NULL);
|
|
Packit |
f228a3 |
#endif
|
|
Packit |
f228a3 |
while (event_cb) {
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
listenfd = usbmuxd_listen();
|
|
Packit |
f228a3 |
if (listenfd < 0) {
|
|
Packit |
f228a3 |
continue;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
while (event_cb) {
|
|
Packit |
f228a3 |
int res = get_next_event(listenfd, event_cb, data);
|
|
Packit |
f228a3 |
if (res < 0) {
|
|
Packit |
f228a3 |
break;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
#ifndef WIN32
|
|
Packit |
f228a3 |
pthread_cleanup_pop(1);
|
|
Packit |
f228a3 |
#else
|
|
Packit |
f228a3 |
device_monitor_cleanup(NULL);
|
|
Packit |
f228a3 |
#endif
|
|
Packit |
f228a3 |
return NULL;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
USBMUXD_API int usbmuxd_subscribe(usbmuxd_event_cb_t callback, void *user_data)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
int res;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
if (!callback) {
|
|
Packit |
f228a3 |
return -EINVAL;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
event_cb = callback;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
#ifdef WIN32
|
|
Packit |
f228a3 |
res = 0;
|
|
Packit |
f228a3 |
devmon = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)device_monitor, user_data, 0, NULL);
|
|
Packit |
f228a3 |
if (devmon == NULL) {
|
|
Packit |
f228a3 |
res = GetLastError();
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
#else
|
|
Packit |
f228a3 |
res = pthread_create(&devmon, NULL, device_monitor, user_data);
|
|
Packit |
f228a3 |
#endif
|
|
Packit |
f228a3 |
if (res != 0) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: ERROR: Could not start device watcher thread!\n", __func__);
|
|
Packit |
f228a3 |
return res;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
return 0;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
USBMUXD_API int usbmuxd_unsubscribe()
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
event_cb = NULL;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
socket_shutdown(listenfd, SHUT_RDWR);
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
#ifdef WIN32
|
|
Packit |
f228a3 |
if (devmon != NULL) {
|
|
Packit |
f228a3 |
WaitForSingleObject(devmon, INFINITE);
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
#else
|
|
Packit |
f228a3 |
if (pthread_kill(devmon, 0) == 0) {
|
|
Packit |
f228a3 |
pthread_cancel(devmon);
|
|
Packit |
f228a3 |
pthread_join(devmon, NULL);
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
#endif
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
return 0;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
static usbmuxd_device_info_t *device_info_from_device_record(struct usbmuxd_device_record *dev)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
if (!dev) {
|
|
Packit |
f228a3 |
return NULL;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
usbmuxd_device_info_t *devinfo = (usbmuxd_device_info_t*)malloc(sizeof(usbmuxd_device_info_t));
|
|
Packit |
f228a3 |
if (!devinfo) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Out of memory!\n", __func__);
|
|
Packit |
f228a3 |
return NULL;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
devinfo->handle = dev->device_id;
|
|
Packit |
f228a3 |
devinfo->product_id = dev->product_id;
|
|
Packit |
f228a3 |
memset(devinfo->udid, '\0', sizeof(devinfo->udid));
|
|
Packit |
f228a3 |
memcpy(devinfo->udid, dev->serial_number, sizeof(devinfo->udid));
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
if (strcasecmp(devinfo->udid, "ffffffffffffffffffffffffffffffffffffffff") == 0) {
|
|
Packit |
f228a3 |
sprintf(devinfo->udid + 32, "%08x", devinfo->handle);
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
return devinfo;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
USBMUXD_API int usbmuxd_get_device_list(usbmuxd_device_info_t **device_list)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
int sfd;
|
|
Packit |
f228a3 |
int tag;
|
|
Packit |
f228a3 |
int listen_success = 0;
|
|
Packit |
f228a3 |
uint32_t res;
|
|
Packit |
f228a3 |
struct collection tmpdevs;
|
|
Packit |
f228a3 |
usbmuxd_device_info_t *newlist = NULL;
|
|
Packit |
f228a3 |
struct usbmuxd_header hdr;
|
|
Packit |
f228a3 |
struct usbmuxd_device_record *dev;
|
|
Packit |
f228a3 |
int dev_cnt = 0;
|
|
Packit |
f228a3 |
void *payload = NULL;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
*device_list = NULL;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
retry:
|
|
Packit |
f228a3 |
sfd = connect_usbmuxd_socket();
|
|
Packit |
f228a3 |
if (sfd < 0) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: error opening socket!\n", __func__);
|
|
Packit |
f228a3 |
return sfd;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
tag = ++use_tag;
|
|
Packit |
f228a3 |
if ((proto_version == 1) && (try_list_devices)) {
|
|
Packit |
f228a3 |
if (send_list_devices_packet(sfd, tag) > 0) {
|
|
Packit |
f228a3 |
plist_t list = NULL;
|
|
Packit |
f228a3 |
if ((usbmuxd_get_result(sfd, tag, &res, &list) == 1) && (res == 0)) {
|
|
Packit |
f228a3 |
plist_t devlist = plist_dict_get_item(list, "DeviceList");
|
|
Packit |
f228a3 |
if (devlist && plist_get_node_type(devlist) == PLIST_ARRAY) {
|
|
Packit |
f228a3 |
collection_init(&tmpdevs);
|
|
Packit |
f228a3 |
uint32_t numdevs = plist_array_get_size(devlist);
|
|
Packit |
f228a3 |
uint32_t i;
|
|
Packit |
f228a3 |
for (i = 0; i < numdevs; i++) {
|
|
Packit |
f228a3 |
plist_t pdev = plist_array_get_item(devlist, i);
|
|
Packit |
f228a3 |
plist_t props = plist_dict_get_item(pdev, "Properties");
|
|
Packit |
f228a3 |
dev = device_record_from_plist(props);
|
|
Packit |
f228a3 |
usbmuxd_device_info_t *devinfo = device_info_from_device_record(dev);
|
|
Packit |
f228a3 |
free(dev);
|
|
Packit |
f228a3 |
if (!devinfo) {
|
|
Packit |
f228a3 |
socket_close(sfd);
|
|
Packit |
f228a3 |
DEBUG(1, "%s: can't create device info object\n", __func__);
|
|
Packit |
f228a3 |
plist_free(list);
|
|
Packit |
f228a3 |
return -1;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
collection_add(&tmpdevs, devinfo);
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
plist_free(list);
|
|
Packit |
f228a3 |
goto got_device_list;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
} else {
|
|
Packit |
f228a3 |
if (res == RESULT_BADVERSION) {
|
|
Packit |
f228a3 |
proto_version = 0;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
socket_close(sfd);
|
|
Packit |
f228a3 |
try_list_devices = 0;
|
|
Packit |
f228a3 |
plist_free(list);
|
|
Packit |
f228a3 |
goto retry;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
plist_free(list);
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
tag = ++use_tag;
|
|
Packit |
f228a3 |
if (send_listen_packet(sfd, tag) > 0) {
|
|
Packit |
f228a3 |
res = -1;
|
|
Packit |
f228a3 |
// get response
|
|
Packit |
f228a3 |
if ((usbmuxd_get_result(sfd, tag, &res, NULL) == 1) && (res == 0)) {
|
|
Packit |
f228a3 |
listen_success = 1;
|
|
Packit |
f228a3 |
} else {
|
|
Packit |
f228a3 |
socket_close(sfd);
|
|
Packit |
f228a3 |
if ((res == RESULT_BADVERSION) && (proto_version == 1)) {
|
|
Packit |
f228a3 |
proto_version = 0;
|
|
Packit |
f228a3 |
goto retry;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Did not get response to scan request (with result=0)...\n", __func__);
|
|
Packit |
f228a3 |
return res;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
if (!listen_success) {
|
|
Packit |
f228a3 |
socket_close(sfd);
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Could not send listen request!\n", __func__);
|
|
Packit |
f228a3 |
return -1;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
collection_init(&tmpdevs);
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
// receive device list
|
|
Packit |
f228a3 |
while (1) {
|
|
Packit |
f228a3 |
if (receive_packet(sfd, &hdr, &payload, 100) > 0) {
|
|
Packit |
f228a3 |
if (hdr.message == MESSAGE_DEVICE_ADD) {
|
|
Packit |
f228a3 |
dev = payload;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
usbmuxd_device_info_t *devinfo = device_info_from_device_record(dev);
|
|
Packit |
f228a3 |
if (!devinfo) {
|
|
Packit |
f228a3 |
socket_close(sfd);
|
|
Packit |
f228a3 |
DEBUG(1, "%s: can't create device info object\n", __func__);
|
|
Packit |
f228a3 |
free(payload);
|
|
Packit |
f228a3 |
return -1;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
collection_add(&tmpdevs, devinfo);
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
} else if (hdr.message == MESSAGE_DEVICE_REMOVE) {
|
|
Packit |
f228a3 |
uint32_t handle;
|
|
Packit |
f228a3 |
usbmuxd_device_info_t *devinfo = NULL;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
memcpy(&handle, payload, sizeof(uint32_t));
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
FOREACH(usbmuxd_device_info_t *di, &tmpdevs) {
|
|
Packit |
f228a3 |
if (di && di->handle == handle) {
|
|
Packit |
f228a3 |
devinfo = di;
|
|
Packit |
f228a3 |
break;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
} ENDFOREACH
|
|
Packit |
f228a3 |
if (devinfo) {
|
|
Packit |
f228a3 |
collection_remove(&tmpdevs, devinfo);
|
|
Packit |
f228a3 |
free(devinfo);
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
} else {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Unexpected message %d\n", __func__, hdr.message);
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
if (payload)
|
|
Packit |
f228a3 |
free(payload);
|
|
Packit |
f228a3 |
} else {
|
|
Packit |
f228a3 |
// we _should_ have all of them now.
|
|
Packit |
f228a3 |
// or perhaps an error occured.
|
|
Packit |
f228a3 |
break;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
got_device_list:
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
// explicitly close connection
|
|
Packit |
f228a3 |
socket_close(sfd);
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
// create copy of device info entries from collection
|
|
Packit |
f228a3 |
newlist = (usbmuxd_device_info_t*)malloc(sizeof(usbmuxd_device_info_t) * (collection_count(&tmpdevs) + 1));
|
|
Packit |
f228a3 |
dev_cnt = 0;
|
|
Packit |
f228a3 |
FOREACH(usbmuxd_device_info_t *di, &tmpdevs) {
|
|
Packit |
f228a3 |
if (di) {
|
|
Packit |
f228a3 |
memcpy(&newlist[dev_cnt], di, sizeof(usbmuxd_device_info_t));
|
|
Packit |
f228a3 |
free(di);
|
|
Packit |
f228a3 |
dev_cnt++;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
} ENDFOREACH
|
|
Packit |
f228a3 |
collection_free(&tmpdevs);
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
memset(&newlist[dev_cnt], 0, sizeof(usbmuxd_device_info_t));
|
|
Packit |
f228a3 |
*device_list = newlist;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
return dev_cnt;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
USBMUXD_API int usbmuxd_device_list_free(usbmuxd_device_info_t **device_list)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
if (device_list) {
|
|
Packit |
f228a3 |
free(*device_list);
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
return 0;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
USBMUXD_API int usbmuxd_get_device_by_udid(const char *udid, usbmuxd_device_info_t *device)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
usbmuxd_device_info_t *dev_list = NULL;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
if (!device) {
|
|
Packit |
f228a3 |
return -EINVAL;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
if (usbmuxd_get_device_list(&dev_list) < 0) {
|
|
Packit |
f228a3 |
return -ENODEV;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
int i;
|
|
Packit |
f228a3 |
int result = 0;
|
|
Packit |
f228a3 |
for (i = 0; dev_list[i].handle > 0; i++) {
|
|
Packit |
f228a3 |
if (!udid) {
|
|
Packit |
f228a3 |
device->handle = dev_list[i].handle;
|
|
Packit |
f228a3 |
device->product_id = dev_list[i].product_id;
|
|
Packit |
f228a3 |
strcpy(device->udid, dev_list[i].udid);
|
|
Packit |
f228a3 |
result = 1;
|
|
Packit |
f228a3 |
break;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
if (!strcmp(udid, dev_list[i].udid)) {
|
|
Packit |
f228a3 |
device->handle = dev_list[i].handle;
|
|
Packit |
f228a3 |
device->product_id = dev_list[i].product_id;
|
|
Packit |
f228a3 |
strcpy(device->udid, dev_list[i].udid);
|
|
Packit |
f228a3 |
result = 1;
|
|
Packit |
f228a3 |
break;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
free(dev_list);
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
return result;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
USBMUXD_API int usbmuxd_connect(const int handle, const unsigned short port)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
int sfd;
|
|
Packit |
f228a3 |
int tag;
|
|
Packit |
f228a3 |
int connected = 0;
|
|
Packit |
f228a3 |
uint32_t res = -1;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
retry:
|
|
Packit |
f228a3 |
sfd = connect_usbmuxd_socket();
|
|
Packit |
f228a3 |
if (sfd < 0) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Error: Connection to usbmuxd failed: %s\n",
|
|
Packit |
f228a3 |
__func__, strerror(errno));
|
|
Packit |
f228a3 |
return sfd;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
tag = ++use_tag;
|
|
Packit |
f228a3 |
if (send_connect_packet(sfd, tag, (uint32_t)handle, (uint16_t)port) <= 0) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Error sending connect message!\n", __func__);
|
|
Packit |
f228a3 |
} else {
|
|
Packit |
f228a3 |
// read ACK
|
|
Packit |
f228a3 |
DEBUG(2, "%s: Reading connect result...\n", __func__);
|
|
Packit |
f228a3 |
if (usbmuxd_get_result(sfd, tag, &res, NULL) == 1) {
|
|
Packit |
f228a3 |
if (res == 0) {
|
|
Packit |
f228a3 |
DEBUG(2, "%s: Connect success!\n", __func__);
|
|
Packit |
f228a3 |
connected = 1;
|
|
Packit |
f228a3 |
} else {
|
|
Packit |
f228a3 |
if ((res == RESULT_BADVERSION) && (proto_version == 1)) {
|
|
Packit |
f228a3 |
proto_version = 0;
|
|
Packit |
f228a3 |
socket_close(sfd);
|
|
Packit |
f228a3 |
goto retry;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Connect failed, Error code=%d\n", __func__, res);
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
if (connected) {
|
|
Packit |
f228a3 |
return sfd;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
socket_close(sfd);
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
return -1;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
USBMUXD_API int usbmuxd_disconnect(int sfd)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
return socket_close(sfd);
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
USBMUXD_API int usbmuxd_send(int sfd, const char *data, uint32_t len, uint32_t *sent_bytes)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
int num_sent;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
if (sfd < 0) {
|
|
Packit |
f228a3 |
return -EINVAL;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
num_sent = socket_send(sfd, (void*)data, len);
|
|
Packit |
f228a3 |
if (num_sent < 0) {
|
|
Packit |
f228a3 |
*sent_bytes = 0;
|
|
Packit |
f228a3 |
num_sent = errno;
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Error %d when sending: %s\n", __func__, num_sent, strerror(num_sent));
|
|
Packit |
f228a3 |
return -num_sent;
|
|
Packit |
f228a3 |
} else if ((uint32_t)num_sent < len) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Warning: Did not send enough (only %d of %d)\n", __func__, num_sent, len);
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
*sent_bytes = num_sent;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
return 0;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
USBMUXD_API int usbmuxd_recv_timeout(int sfd, char *data, uint32_t len, uint32_t *recv_bytes, unsigned int timeout)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
int num_recv = socket_receive_timeout(sfd, (void*)data, len, 0, timeout);
|
|
Packit |
f228a3 |
if (num_recv < 0) {
|
|
Packit |
f228a3 |
*recv_bytes = 0;
|
|
Packit |
f228a3 |
return num_recv;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
*recv_bytes = num_recv;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
return 0;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
USBMUXD_API int usbmuxd_recv(int sfd, char *data, uint32_t len, uint32_t *recv_bytes)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
return usbmuxd_recv_timeout(sfd, data, len, recv_bytes, 5000);
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
USBMUXD_API int usbmuxd_read_buid(char **buid)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
int sfd;
|
|
Packit |
f228a3 |
int tag;
|
|
Packit |
f228a3 |
int ret = -1;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
if (!buid) {
|
|
Packit |
f228a3 |
return -EINVAL;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
*buid = NULL;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
sfd = connect_usbmuxd_socket();
|
|
Packit |
f228a3 |
if (sfd < 0) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Error: Connection to usbmuxd failed: %s\n", __func__, strerror(errno));
|
|
Packit |
f228a3 |
return sfd;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
proto_version = 1;
|
|
Packit |
f228a3 |
tag = ++use_tag;
|
|
Packit |
f228a3 |
if (send_read_buid_packet(sfd, tag) <= 0) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Error sending ReadBUID message!\n", __func__);
|
|
Packit |
f228a3 |
} else {
|
|
Packit |
f228a3 |
uint32_t rc = 0;
|
|
Packit |
f228a3 |
plist_t pl = NULL;
|
|
Packit |
f228a3 |
ret = usbmuxd_get_result(sfd, tag, &rc, &pl);
|
|
Packit |
f228a3 |
if ((ret == 1) && (rc == 0)) {
|
|
Packit |
f228a3 |
plist_t node = plist_dict_get_item(pl, "BUID");
|
|
Packit |
f228a3 |
if (node && plist_get_node_type(node) == PLIST_STRING) {
|
|
Packit |
f228a3 |
plist_get_string_val(node, buid);
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
ret = 0;
|
|
Packit |
f228a3 |
} else if (ret == 1) {
|
|
Packit |
f228a3 |
ret = -(int)rc;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
plist_free(pl);
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
socket_close(sfd);
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
return ret;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
USBMUXD_API int usbmuxd_read_pair_record(const char* record_id, char **record_data, uint32_t *record_size)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
int sfd;
|
|
Packit |
f228a3 |
int tag;
|
|
Packit |
f228a3 |
int ret = -1;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
if (!record_id || !record_data || !record_size) {
|
|
Packit |
f228a3 |
return -EINVAL;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
*record_data = NULL;
|
|
Packit |
f228a3 |
*record_size = 0;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
sfd = connect_usbmuxd_socket();
|
|
Packit |
f228a3 |
if (sfd < 0) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Error: Connection to usbmuxd failed: %s\n",
|
|
Packit |
f228a3 |
__func__, strerror(errno));
|
|
Packit |
f228a3 |
return sfd;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
proto_version = 1;
|
|
Packit |
f228a3 |
tag = ++use_tag;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
if (send_pair_record_packet(sfd, tag, "ReadPairRecord", record_id, NULL) <= 0) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Error sending ReadPairRecord message!\n", __func__);
|
|
Packit |
f228a3 |
} else {
|
|
Packit |
f228a3 |
uint32_t rc = 0;
|
|
Packit |
f228a3 |
plist_t pl = NULL;
|
|
Packit |
f228a3 |
ret = usbmuxd_get_result(sfd, tag, &rc, &pl);
|
|
Packit |
f228a3 |
if ((ret == 1) && (rc == 0)) {
|
|
Packit |
f228a3 |
plist_t node = plist_dict_get_item(pl, "PairRecordData");
|
|
Packit |
f228a3 |
if (node && plist_get_node_type(node) == PLIST_DATA) {
|
|
Packit |
f228a3 |
uint64_t int64val = 0;
|
|
Packit |
f228a3 |
plist_get_data_val(node, record_data, &int64val);
|
|
Packit |
f228a3 |
if (*record_data && int64val > 0) {
|
|
Packit |
f228a3 |
*record_size = (uint32_t)int64val;
|
|
Packit |
f228a3 |
ret = 0;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
} else if (ret == 1) {
|
|
Packit |
f228a3 |
ret = -(int)rc;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
plist_free(pl);
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
socket_close(sfd);
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
return ret;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
USBMUXD_API int usbmuxd_save_pair_record(const char* record_id, const char *record_data, uint32_t record_size)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
int sfd;
|
|
Packit |
f228a3 |
int tag;
|
|
Packit |
f228a3 |
int ret = -1;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
if (!record_id || !record_data || !record_size) {
|
|
Packit |
f228a3 |
return -EINVAL;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
sfd = connect_usbmuxd_socket();
|
|
Packit |
f228a3 |
if (sfd < 0) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Error: Connection to usbmuxd failed: %s\n",
|
|
Packit |
f228a3 |
__func__, strerror(errno));
|
|
Packit |
f228a3 |
return sfd;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
proto_version = 1;
|
|
Packit |
f228a3 |
tag = ++use_tag;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
plist_t data = plist_new_data(record_data, record_size);
|
|
Packit |
f228a3 |
if (send_pair_record_packet(sfd, tag, "SavePairRecord", record_id, data) <= 0) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Error sending SavePairRecord message!\n", __func__);
|
|
Packit |
f228a3 |
} else {
|
|
Packit |
f228a3 |
uint32_t rc = 0;
|
|
Packit |
f228a3 |
ret = usbmuxd_get_result(sfd, tag, &rc, NULL);
|
|
Packit |
f228a3 |
if ((ret == 1) && (rc == 0)) {
|
|
Packit |
f228a3 |
ret = 0;
|
|
Packit |
f228a3 |
} else if (ret == 1) {
|
|
Packit |
f228a3 |
ret = -(int)rc;
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Error: saving pair record failed: %d\n", __func__, ret);
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
plist_free(data);
|
|
Packit |
f228a3 |
socket_close(sfd);
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
return ret;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
USBMUXD_API int usbmuxd_delete_pair_record(const char* record_id)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
int sfd;
|
|
Packit |
f228a3 |
int tag;
|
|
Packit |
f228a3 |
int ret = -1;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
if (!record_id) {
|
|
Packit |
f228a3 |
return -EINVAL;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
sfd = connect_usbmuxd_socket();
|
|
Packit |
f228a3 |
if (sfd < 0) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Error: Connection to usbmuxd failed: %s\n",
|
|
Packit |
f228a3 |
__func__, strerror(errno));
|
|
Packit |
f228a3 |
return sfd;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
proto_version = 1;
|
|
Packit |
f228a3 |
tag = ++use_tag;
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
if (send_pair_record_packet(sfd, tag, "DeletePairRecord", record_id, NULL) <= 0) {
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Error sending DeletePairRecord message!\n", __func__);
|
|
Packit |
f228a3 |
} else {
|
|
Packit |
f228a3 |
uint32_t rc = 0;
|
|
Packit |
f228a3 |
ret = usbmuxd_get_result(sfd, tag, &rc, NULL);
|
|
Packit |
f228a3 |
if ((ret == 1) && (rc == 0)) {
|
|
Packit |
f228a3 |
ret = 0;
|
|
Packit |
f228a3 |
} else if (ret == 1) {
|
|
Packit |
f228a3 |
ret = -(int)rc;
|
|
Packit |
f228a3 |
DEBUG(1, "%s: Error: deleting pair record failed: %d\n", __func__, ret);
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
socket_close(sfd);
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
return ret;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
USBMUXD_API void libusbmuxd_set_use_inotify(int set)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
#ifdef HAVE_INOTIFY
|
|
Packit |
f228a3 |
use_inotify = set;
|
|
Packit |
f228a3 |
#endif
|
|
Packit |
f228a3 |
return;
|
|
Packit |
f228a3 |
}
|
|
Packit |
f228a3 |
|
|
Packit |
f228a3 |
USBMUXD_API void libusbmuxd_set_debug_level(int level)
|
|
Packit |
f228a3 |
{
|
|
Packit |
f228a3 |
libusbmuxd_debug = level;
|
|
Packit |
f228a3 |
socket_set_verbose(level);
|
|
Packit |
f228a3 |
}
|