summaryrefslogtreecommitdiffstats
path: root/daemon
diff options
context:
space:
mode:
Diffstat (limited to 'daemon')
-rw-r--r--daemon/CMakeLists.txt23
-rw-r--r--daemon/client.c616
-rw-r--r--daemon/client.h47
-rw-r--r--daemon/device.c781
-rw-r--r--daemon/device.h52
-rw-r--r--daemon/log.c95
-rw-r--r--daemon/log.h44
-rw-r--r--daemon/main.c618
-rw-r--r--daemon/usb-linux.c598
-rw-r--r--daemon/usb.h66
10 files changed, 0 insertions, 2940 deletions
diff --git a/daemon/CMakeLists.txt b/daemon/CMakeLists.txt
deleted file mode 100644
index c323f7b..0000000
--- a/daemon/CMakeLists.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-find_package(USB REQUIRED)
-include_directories(${USB_INCLUDE_DIRS})
-include_directories(${OPT_INCLUDES})
-set(LIBS ${LIBS} ${USB_LIBRARIES} ${OPT_LIBS})
-if(HAVE_PLIST)
- add_definitions("-DHAVE_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)
-
-add_definitions(-DUSBMUXD_DAEMON -DUSBMUXD_VERSION="${USBMUXD_VERSION}")
-add_executable(usbmuxd main.c usb-linux.c log.c ${CMAKE_SOURCE_DIR}/common/utils.c device.c client.c)
-target_link_libraries(usbmuxd ${LIBS})
-
-install(TARGETS usbmuxd RUNTIME DESTINATION sbin)
-
-message("
-* REMINDER
-* Remember to add a user named 'usbmux' with USB access permissions
-* for the udev hotplugging feature to work out of the box.
-")
diff --git a/daemon/client.c b/daemon/client.c
deleted file mode 100644
index ac1045a..0000000
--- a/daemon/client.c
+++ /dev/null
@@ -1,616 +0,0 @@
-/*
- usbmuxd - iPhone/iPod Touch USB multiplex server daemon
-
-Copyright (C) 2009 Hector Martin "marcan" <hector@marcansoft.com>
-Copyright (C) 2009 Nikias Bassen <nikias@gmx.li>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 or version 3.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#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 {
- CLIENT_COMMAND, // waiting for command
- CLIENT_LISTEN, // listening for devices
- CLIENT_CONNECTING1, // issued connection request
- CLIENT_CONNECTING2, // connection established, but waiting for response message to get sent
- CLIENT_CONNECTED, // connected
- CLIENT_DEAD
-};
-
-struct mux_client {
- int fd;
- unsigned char *ob_buf;
- uint32_t ob_size;
- uint32_t ob_capacity;
- unsigned char *ib_buf;
- uint32_t ib_size;
- uint32_t ib_capacity;
- short events, devents;
- uint32_t connect_tag;
- int connect_device;
- enum client_state state;
- uint32_t proto_version;
-};
-
-static struct collection client_list;
-
-int client_read(struct mux_client *client, void *buffer, uint32_t len)
-{
- usbmuxd_log(LL_SPEW, "client_read fd %d buf %p len %d", client->fd, buffer, len);
- if(client->state != CLIENT_CONNECTED) {
- usbmuxd_log(LL_ERROR, "Attempted to read from client %d not in CONNECTED state", client->fd);
- return -1;
- }
- return recv(client->fd, buffer, len, 0);
-}
-
-int client_write(struct mux_client *client, void *buffer, uint32_t len)
-{
- usbmuxd_log(LL_SPEW, "client_write fd %d buf %p len %d", client->fd, buffer, len);
- if(client->state != CLIENT_CONNECTED) {
- usbmuxd_log(LL_ERROR, "Attempted to write to client %d not in CONNECTED state", client->fd);
- return -1;
- }
- return send(client->fd, buffer, len, 0);
-}
-
-int client_set_events(struct mux_client *client, short events)
-{
- if((client->state != CLIENT_CONNECTED) && (client->state != CLIENT_CONNECTING2)) {
- usbmuxd_log(LL_ERROR, "client_set_events to client %d not in CONNECTED state", client->fd);
- return -1;
- }
- client->devents = events;
- if(client->state == CLIENT_CONNECTED)
- client->events = events;
- return 0;
-}
-
-int client_accept(int listenfd)
-{
- struct sockaddr_un addr;
- int cfd;
- socklen_t len = sizeof(struct sockaddr_un);
- cfd = accept(listenfd, (struct sockaddr *)&addr, &len);
- if (cfd < 0) {
- usbmuxd_log(LL_ERROR, "accept() failed (%s)", strerror(errno));
- return cfd;
- }
-
- struct mux_client *client;
- client = malloc(sizeof(struct mux_client));
- memset(client, 0, sizeof(struct mux_client));
-
- client->fd = cfd;
- client->ob_buf = malloc(REPLY_BUF_SIZE);
- client->ob_size = 0;
- client->ob_capacity = REPLY_BUF_SIZE;
- client->ib_buf = malloc(CMD_BUF_SIZE);
- client->ib_size = 0;
- client->ib_capacity = CMD_BUF_SIZE;
- client->state = CLIENT_COMMAND;
- client->events = POLLIN;
-
- collection_add(&client_list, client);
-
- usbmuxd_log(LL_INFO, "New client on fd %d", client->fd);
- return client->fd;
-}
-
-void client_close(struct mux_client *client)
-{
- usbmuxd_log(LL_INFO, "Disconnecting client fd %d", client->fd);
- if(client->state == CLIENT_CONNECTING1 || client->state == CLIENT_CONNECTING2) {
- usbmuxd_log(LL_INFO, "Client died mid-connect, aborting device %d connection", client->connect_device);
- client->state = CLIENT_DEAD;
- device_abort_connect(client->connect_device, client);
- }
- close(client->fd);
- if(client->ob_buf)
- free(client->ob_buf);
- if(client->ib_buf)
- free(client->ib_buf);
- collection_remove(&client_list, client);
- free(client);
-}
-
-void client_get_fds(struct fdlist *list)
-{
- FOREACH(struct mux_client *client, &client_list) {
- fdlist_add(list, FD_CLIENT, client->fd, client->events);
- } ENDFOREACH
-}
-
-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 = client->proto_version;
- hdr.length = sizeof(hdr) + payload_length;
- hdr.message = msg;
- hdr.tag = tag;
- usbmuxd_log(LL_DEBUG, "send_pkt fd %d tag %d msg %d payload_length %d", client->fd, tag, msg, payload_length);
- if((client->ob_capacity - client->ob_size) < hdr.length) {
- usbmuxd_log(LL_ERROR, "Client %d output buffer full (%d bytes) while sending message %d (%d bytes)", client->fd, client->ob_capacity, hdr.message, hdr.length);
- client_close(client);
- return -1;
- }
- memcpy(client->ob_buf + client->ob_size, &hdr, sizeof(hdr));
- if(payload && payload_length)
- memcpy(client->ob_buf + client->ob_size + sizeof(hdr), payload, payload_length);
- client->ob_size += hdr.length;
- client->events |= POLLOUT;
- return hdr.length;
-}
-
-static int send_result(struct mux_client *client, uint32_t tag, uint32_t result)
-{
- 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)
-{
- usbmuxd_log(LL_SPEW, "client_notify_connect fd %d result %d", client->fd, result);
- if(client->state == CLIENT_DEAD)
- return -1;
- if(client->state != CLIENT_CONNECTING1) {
- usbmuxd_log(LL_ERROR, "client_notify_connect when client %d is not in CONNECTING1 state", client->fd);
- return -1;
- }
- if(send_result(client, client->connect_tag, result) < 0)
- return -1;
- if(result == RESULT_OK) {
- client->state = CLIENT_CONNECTING2;
- client->events = POLLOUT; // wait for the result packet to go through
- // no longer need this
- free(client->ib_buf);
- client->ib_buf = NULL;
- } else {
- client->state = CLIENT_COMMAND;
- }
- return 0;
-}
-
-static int notify_device_add(struct mux_client *client, struct device_info *dev)
-{
- 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)
-{
- 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)
-{
- struct device_info *devs;
- struct device_info *dev;
- int count, i;
-
- client->state = CLIENT_LISTEN;
- count = device_get_count();
- if(!count)
- return 0;
- devs = malloc(sizeof(struct device_info) * count);
- count = device_get_list(devs);
-
- // going to need a larger buffer for many devices
- int needed_buffer = count * (sizeof(struct usbmuxd_device_record) + sizeof(struct usbmuxd_header)) + REPLY_BUF_SIZE;
- if(client->ob_capacity < needed_buffer) {
- usbmuxd_log(LL_DEBUG, "Enlarging client %d reply buffer %d -> %d to make space for device notifications", client->fd, client->ob_capacity, needed_buffer);
- client->ob_buf = realloc(client->ob_buf, needed_buffer);
- client->ob_capacity = needed_buffer;
- }
- dev = devs;
- for(i=0; i<count; i++) {
- if(notify_device_add(client, dev++) < 0) {
- free(devs);
- return -1;
- }
- }
- free(devs);
- return count;
-}
-
-static int client_command(struct mux_client *client, struct usbmuxd_header *hdr)
-{
- int res;
- usbmuxd_log(LL_DEBUG, "Client command in fd %d len %d ver %d msg %d tag %d", client->fd, hdr->length, hdr->version, hdr->message, hdr->tag);
-
- if(client->state != CLIENT_COMMAND) {
- usbmuxd_log(LL_ERROR, "Client %d command received in the wrong state", client->fd);
- if(send_result(client, hdr->tag, RESULT_BADCOMMAND) < 0)
- return -1;
- client_close(client);
- return -1;
- }
-
- 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;
- usbmuxd_log(LL_DEBUG, "Client %d now LISTENING", client->fd);
- return start_listen(client);
- case MESSAGE_CONNECT:
- ch = (void*)hdr;
- usbmuxd_log(LL_DEBUG, "Client %d connection request to device %d port %d", client->fd, ch->device_id, ntohs(ch->port));
- res = device_start_connect(ch->device_id, ntohs(ch->port), client);
- if(res < 0) {
- if(send_result(client, hdr->tag, -res) < 0)
- return -1;
- } else {
- client->connect_tag = hdr->tag;
- client->connect_device = ch->device_id;
- client->state = CLIENT_CONNECTING1;
- }
- return 0;
- default:
- usbmuxd_log(LL_ERROR, "Client %d invalid command %d", client->fd, hdr->message);
- if(send_result(client, hdr->tag, RESULT_BADCOMMAND) < 0)
- return -1;
- return 0;
- }
- return -1;
-}
-
-static void process_send(struct mux_client *client)
-{
- int res;
- if(!client->ob_size) {
- usbmuxd_log(LL_WARNING, "Client %d OUT process but nothing to send?", client->fd);
- client->events &= ~POLLOUT;
- return;
- }
- res = send(client->fd, client->ob_buf, client->ob_size, 0);
- if(res <= 0) {
- usbmuxd_log(LL_ERROR, "Send to client fd %d failed: %d %s", client->fd, res, strerror(errno));
- client_close(client);
- return;
- }
- if(res == client->ob_size) {
- client->ob_size = 0;
- client->events &= ~POLLOUT;
- if(client->state == CLIENT_CONNECTING2) {
- usbmuxd_log(LL_DEBUG, "Client %d switching to CONNECTED state", client->fd);
- client->state = CLIENT_CONNECTED;
- client->events = client->devents;
- // no longer need this
- free(client->ob_buf);
- client->ob_buf = NULL;
- }
- } else {
- client->ob_size -= res;
- memmove(client->ob_buf, client->ob_buf + res, client->ob_size);
- }
-}
-static void process_recv(struct mux_client *client)
-{
- int res;
- int did_read = 0;
- if(client->ib_size < sizeof(struct usbmuxd_header)) {
- res = recv(client->fd, client->ib_buf + client->ib_size, sizeof(struct usbmuxd_header) - client->ib_size, 0);
- if(res <= 0) {
- if(res < 0)
- usbmuxd_log(LL_ERROR, "Receive from client fd %d failed: %s", client->fd, strerror(errno));
- else
- usbmuxd_log(LL_INFO, "Client %d connection closed", client->fd);
- client_close(client);
- return;
- }
- client->ib_size += res;
- if(client->ib_size < sizeof(struct usbmuxd_header))
- return;
- 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);
- return;
- }
- if(hdr->length > client->ib_capacity) {
- usbmuxd_log(LL_INFO, "Client %d message is too long (%d bytes)", client->fd, hdr->length);
- client_close(client);
- return;
- }
- if(hdr->length < sizeof(struct usbmuxd_header)) {
- usbmuxd_log(LL_ERROR, "Client %d message is too short (%d bytes)", client->fd, hdr->length);
- client_close(client);
- return;
- }
- if(client->ib_size < hdr->length) {
- if(did_read)
- return; //maybe we would block, so defer to next loop
- res = recv(client->fd, client->ib_buf + client->ib_size, hdr->length - client->ib_size, 0);
- if(res < 0) {
- usbmuxd_log(LL_ERROR, "Receive from client fd %d failed: %s", client->fd, strerror(errno));
- client_close(client);
- return;
- } else if(res == 0) {
- usbmuxd_log(LL_INFO, "Client %d connection closed", client->fd);
- client_close(client);
- return;
- }
- client->ib_size += res;
- if(client->ib_size < hdr->length)
- return;
- }
- client_command(client, hdr);
- client->ib_size = 0;
-}
-
-void client_process(int fd, short events)
-{
- struct mux_client *client = NULL;
- FOREACH(struct mux_client *lc, &client_list) {
- if(lc->fd == fd) {
- client = lc;
- break;
- }
- } ENDFOREACH
-
- if(!client) {
- usbmuxd_log(LL_INFO, "client_process: fd %d not found in client list", fd);
- return;
- }
-
- if(client->state == CLIENT_CONNECTED) {
- usbmuxd_log(LL_SPEW, "client_process in CONNECTED state");
- device_client_process(client->connect_device, client, events);
- } else {
- if(events & POLLIN) {
- process_recv(client);
- } else if(events & POLLOUT) { //not both in case client died as part of process_recv
- process_send(client);
- }
- }
-
-}
-
-void client_device_add(struct device_info *dev)
-{
- usbmuxd_log(LL_DEBUG, "client_device_add: id %d, location 0x%x, serial %s", dev->id, dev->location, dev->serial);
- FOREACH(struct mux_client *client, &client_list) {
- if(client->state == CLIENT_LISTEN)
- notify_device_add(client, dev);
- } ENDFOREACH
-}
-void client_device_remove(int device_id)
-{
- uint32_t id = device_id;
- usbmuxd_log(LL_DEBUG, "client_device_remove: id %d", device_id);
- FOREACH(struct mux_client *client, &client_list) {
- if(client->state == CLIENT_LISTEN)
- notify_device_remove(client, id);
- } ENDFOREACH
-}
-
-
-void client_init(void)
-{
- usbmuxd_log(LL_DEBUG, "client_init");
- collection_init(&client_list);
-}
-
-void client_shutdown(void)
-{
- usbmuxd_log(LL_DEBUG, "client_shutdown");
- FOREACH(struct mux_client *client, &client_list) {
- client_close(client);
- } ENDFOREACH
- collection_free(&client_list);
-}
diff --git a/daemon/client.h b/daemon/client.h
deleted file mode 100644
index 60d8348..0000000
--- a/daemon/client.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- usbmuxd - iPhone/iPod Touch USB multiplex server daemon
-
-Copyright (C) 2009 Hector Martin "marcan" <hector@marcansoft.com>
-Copyright (C) 2009 Nikias Bassen <nikias@gmx.li>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 or version 3.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-*/
-
-#ifndef __CLIENT_H__
-#define __CLIENT_H__
-
-#include <stdint.h>
-#include "usbmuxd-proto.h"
-
-struct device_info;
-struct mux_client;
-
-int client_read(struct mux_client *client, void *buffer, uint32_t len);
-int client_write(struct mux_client *client, void *buffer, uint32_t len);
-int client_set_events(struct mux_client *client, short events);
-void client_close(struct mux_client *client);
-int client_notify_connect(struct mux_client *client, enum usbmuxd_result result);
-
-void client_device_add(struct device_info *dev);
-void client_device_remove(int device_id);
-
-int client_accept(int fd);
-void client_get_fds(struct fdlist *list);
-void client_process(int fd, short events);
-
-void client_init(void);
-void client_shutdown(void);
-
-#endif
diff --git a/daemon/device.c b/daemon/device.c
deleted file mode 100644
index 8c786a7..0000000
--- a/daemon/device.c
+++ /dev/null
@@ -1,781 +0,0 @@
-/*
- usbmuxd - iPhone/iPod Touch USB multiplex server daemon
-
-Copyright (C) 2009 Hector Martin "marcan" <hector@marcansoft.com>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 or version 3.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-*/
-
-#define _BSD_SOURCE
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <sys/time.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include "device.h"
-#include "client.h"
-#include "usb.h"
-#include "log.h"
-
-int next_device_id;
-
-#define DEV_MRU 65536
-
-#define CONN_INBUF_SIZE 262144
-#define CONN_OUTBUF_SIZE 65536
-
-#define ACK_TIMEOUT 30
-
-enum mux_protocol {
- MUX_PROTO_VERSION = 0,
- MUX_PROTO_TCP = IPPROTO_TCP,
-};
-
-enum mux_dev_state {
- MUXDEV_INIT, // sent version packet
- MUXDEV_ACTIVE, // received version packet, active
- MUXDEV_DEAD // dead
-};
-
-enum mux_conn_state {
- CONN_CONNECTING, // SYN
- CONN_CONNECTED, // SYN/SYNACK/ACK -> active
- CONN_REFUSED, // RST received during SYN
- CONN_DYING, // RST received
- CONN_DEAD // being freed; used to prevent infinite recursion between client<->device freeing
-};
-
-struct mux_header
-{
- uint32_t protocol;
- uint32_t length;
-};
-
-struct version_header
-{
- uint32_t major;
- uint32_t minor;
- uint32_t padding;
-};
-
-struct mux_device;
-
-#define CONN_ACK_PENDING 1
-
-struct mux_connection
-{
- struct mux_device *dev;
- struct mux_client *client;
- enum mux_conn_state state;
- uint16_t sport, dport;
- uint32_t tx_seq, tx_ack, tx_acked, tx_win;
- uint32_t rx_seq, rx_recvd, rx_ack, rx_win;
- uint32_t max_payload;
- uint32_t sendable;
- int flags;
- unsigned char *ib_buf;
- uint32_t ib_size;
- uint32_t ib_capacity;
- unsigned char *ob_buf;
- uint32_t ob_capacity;
- short events;
- uint64_t last_ack_time;
-};
-
-struct mux_device
-{
- struct usb_device *usbdev;
- int id;
- enum mux_dev_state state;
- struct collection connections;
- uint16_t next_sport;
- unsigned char *pktbuf;
- uint32_t pktlen;
-};
-
-static struct collection device_list;
-
-uint64_t mstime64(void)
-{
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return tv.tv_sec * 1000 + tv.tv_usec / 1000;
-}
-
-static int get_next_device_id(void)
-{
- while(1) {
- int ok = 1;
- FOREACH(struct mux_device *dev, &device_list) {
- if(dev->id == next_device_id) {
- next_device_id++;
- ok = 0;
- break;
- }
- } ENDFOREACH
- if(ok)
- return next_device_id++;
- }
-}
-
-static int send_packet(struct mux_device *dev, enum mux_protocol proto, void *header, const void *data, int length)
-{
- unsigned char *buffer;
- int hdrlen;
- int res;
-
- switch(proto) {
- case MUX_PROTO_VERSION:
- hdrlen = sizeof(struct version_header);
- break;
- case MUX_PROTO_TCP:
- hdrlen = sizeof(struct tcphdr);
- break;
- default:
- usbmuxd_log(LL_ERROR, "Invalid protocol %d for outgoing packet (dev %d hdr %p data %p len %d)", proto, dev->id, header, data, length);
- return -1;
- }
- usbmuxd_log(LL_SPEW, "send_packet(%d, 0x%x, %p, %p, %d)", dev->id, proto, header, data, length);
-
- int total = sizeof(struct mux_header) + hdrlen + length;
-
- if(total > USB_MTU) {
- usbmuxd_log(LL_ERROR, "Tried to send packet larger than USB MTU (hdr %d data %d total %d) to device %d", hdrlen, length, total, dev->id);
- return -1;
- }
-
- buffer = malloc(total);
- struct mux_header *mhdr = (struct mux_header *)buffer;
- mhdr->protocol = htonl(proto);
- mhdr->length = htonl(total);
- memcpy(buffer + sizeof(struct mux_header), header, hdrlen);
- if(data && length)
- memcpy(buffer + sizeof(struct mux_header) + hdrlen, data, length);
-
- if((res = usb_send(dev->usbdev, buffer, total)) < 0) {
- usbmuxd_log(LL_ERROR, "usb_send failed while sending packet (len %d) to device %d: %d", total, dev->id, res);
- free(buffer);
- return res;
- }
- return total;
-}
-
-static uint16_t find_sport(struct mux_device *dev)
-{
- if(collection_count(&dev->connections) >= 65535)
- return 0; //insanity
-
- while(1) {
- int ok = 1;
- FOREACH(struct mux_connection *conn, &dev->connections) {
- if(dev->next_sport == conn->sport) {
- dev->next_sport++;
- ok = 0;
- break;
- }
- } ENDFOREACH
- if(ok)
- return dev->next_sport++;
- }
-}
-
-static int send_anon_rst(struct mux_device *dev, uint16_t sport, uint16_t dport, uint32_t ack)
-{
- struct tcphdr th;
- memset(&th, 0, sizeof(th));
- th.th_sport = htons(sport);
- th.th_dport = htons(dport);
- th.th_ack = htonl(ack);
- th.th_flags = TH_RST;
- th.th_off = sizeof(th) / 4;
-
- usbmuxd_log(LL_DEBUG, "[OUT] dev=%d sport=%d dport=%d flags=0x%x", dev->id, sport, dport, th.th_flags);
-
- int res = send_packet(dev, MUX_PROTO_TCP, &th, NULL, 0);
- return res;
-}
-
-static int send_tcp(struct mux_connection *conn, uint8_t flags, const unsigned char *data, int length)
-{
- struct tcphdr th;
- memset(&th, 0, sizeof(th));
- th.th_sport = htons(conn->sport);
- th.th_dport = htons(conn->dport);
- th.th_seq = htonl(conn->tx_seq);
- th.th_ack = htonl(conn->tx_ack);
- th.th_flags = flags;
- th.th_off = sizeof(th) / 4;
- th.th_win = htons(conn->tx_win >> 8);
-
- usbmuxd_log(LL_DEBUG, "[OUT] dev=%d sport=%d dport=%d seq=%d ack=%d flags=0x%x window=%d[%d] len=%d",
- conn->dev->id, conn->sport, conn->dport, conn->tx_seq, conn->tx_ack, flags, conn->tx_win, conn->tx_win >> 8, length);
-
- int res = send_packet(conn->dev, MUX_PROTO_TCP, &th, data, length);
- if(res >= 0) {
- conn->tx_acked = conn->tx_ack;
- conn->last_ack_time = mstime64();
- conn->flags &= ~CONN_ACK_PENDING;
- }
- return res;
-}
-
-static void connection_teardown(struct mux_connection *conn)
-{
- int res;
- if(conn->state == CONN_DEAD)
- return;
- usbmuxd_log(LL_DEBUG, "connection_teardown dev %d sport %d dport %d", conn->dev->id, conn->sport, conn->dport);
- if(conn->dev->state != MUXDEV_DEAD && conn->state != CONN_DYING && conn->state != CONN_REFUSED) {
- res = send_tcp(conn, TH_RST, NULL, 0);
- if(res < 0)
- usbmuxd_log(LL_ERROR, "Error sending TCP RST to device %d (%d->%d)", conn->dev->id, conn->sport, conn->dport);
- }
- if(conn->client) {
- if(conn->state == CONN_REFUSED || conn->state == CONN_CONNECTING) {
- client_notify_connect(conn->client, RESULT_CONNREFUSED);
- } else {
- conn->state = CONN_DEAD;
- client_close(conn->client);
- }
- }
- if(conn->ib_buf)
- free(conn->ib_buf);
- if(conn->ob_buf)
- free(conn->ob_buf);
- collection_remove(&conn->dev->connections, conn);
- free(conn);
-}
-
-int device_start_connect(int device_id, uint16_t dport, struct mux_client *client)
-{
- struct mux_device *dev = NULL;
- FOREACH(struct mux_device *cdev, &device_list) {
- if(cdev->id == device_id) {
- dev = cdev;
- break;
- }
- } ENDFOREACH
- if(!dev) {
- usbmuxd_log(LL_WARNING, "Attempted to connect to nonexistent device %d", device_id);
- return -RESULT_BADDEV;
- }
-
- uint16_t sport = find_sport(dev);
- if(!sport) {
- usbmuxd_log(LL_WARNING, "Unable to allocate port for device %d", device_id);
- return -RESULT_BADDEV;
- }
-
- struct mux_connection *conn;
- conn = malloc(sizeof(struct mux_connection));
- memset(conn, 0, sizeof(struct mux_connection));
-
- conn->dev = dev;
- conn->client = client;
- conn->state = CONN_CONNECTING;
- conn->sport = sport;
- conn->dport = dport;
- conn->tx_seq = 0;
- conn->tx_ack = 0;
- conn->tx_acked = 0;
- conn->tx_win = 131072;
- conn->rx_recvd = 0;
- conn->flags = 0;
- conn->max_payload = USB_MTU - sizeof(struct mux_header) - sizeof(struct tcphdr);
-
- conn->ob_buf = malloc(CONN_OUTBUF_SIZE);
- conn->ob_capacity = CONN_OUTBUF_SIZE;
- conn->ib_buf = malloc(CONN_INBUF_SIZE);
- conn->ib_capacity = CONN_INBUF_SIZE;
- conn->ib_size = 0;
-
- int res;
-
- res = send_tcp(conn, TH_SYN, NULL, 0);
- if(res < 0) {
- usbmuxd_log(LL_ERROR, "Error sending TCP SYN to device %d (%d->%d)", dev->id, sport, dport);
- free(conn);
- return -RESULT_CONNREFUSED; //bleh
- }
- collection_add(&dev->connections, conn);
- return 0;
-}
-
-static void update_connection(struct mux_connection *conn)
-{
- uint32_t sent = conn->tx_seq - conn->rx_ack;
-
- if(conn->rx_win > sent)
- conn->sendable = conn->rx_win - sent;
- else
- conn->sendable = 0;
-
- if(conn->sendable > conn->ob_capacity)
- conn->sendable = conn->ob_capacity;
- if(conn->sendable > conn->max_payload)
- conn->sendable = conn->max_payload;
-
- if(conn->sendable > 0)
- conn->events |= POLLIN;
- else
- conn->events &= ~POLLIN;
-
- if(conn->ib_size)
- conn->events |= POLLOUT;
- else
- conn->events &= ~POLLOUT;
-
- if(conn->tx_acked != conn->tx_ack)
- conn->flags |= CONN_ACK_PENDING;
- else
- conn->flags &= ~CONN_ACK_PENDING;
-
- usbmuxd_log(LL_SPEW, "update_connection: sendable %d, events %d, flags %d", conn->sendable, conn->events, conn->flags);
- client_set_events(conn->client, conn->events);
-}
-
-void device_client_process(int device_id, struct mux_client *client, short events)
-{
- struct mux_connection *conn = NULL;
- FOREACH(struct mux_device *dev, &device_list) {
- if(dev->id == device_id) {
- FOREACH(struct mux_connection *lconn, &dev->connections) {
- if(lconn->client == client) {
- conn = lconn;
- break;
- }
- } ENDFOREACH
- break;
- }
- } ENDFOREACH
-
- if(!conn) {
- usbmuxd_log(LL_WARNING, "Could not find connection for device %d client %p", device_id, client);
- return;
- }
- usbmuxd_log(LL_SPEW, "device_client_process (%d)", events);
-
- int res;
- int size;
- if(events & POLLOUT) {
- size = client_write(conn->client, conn->ib_buf, conn->ib_size);
- if(size <= 0) {
- usbmuxd_log(LL_DEBUG, "error writing to client (%d)", size);
- connection_teardown(conn);
- return;
- }
- conn->tx_ack += size;
- if(size == conn->ib_size) {
- conn->ib_size = 0;
- } else {
- conn->ib_size -= size;
- memmove(conn->ib_buf, conn->ib_buf + size, conn->ib_size);
- }
- }
- if(events & POLLIN) {
- size = client_read(conn->client, conn->ob_buf, conn->sendable);
- if(size <= 0) {
- usbmuxd_log(LL_DEBUG, "error reading from client (%d)", size);
- connection_teardown(conn);
- return;
- }
- res = send_tcp(conn, TH_ACK, conn->ob_buf, size);
- if(res < 0) {
- connection_teardown(conn);
- return;
- }
- conn->tx_seq += size;
- }
-
- update_connection(conn);
-}
-
-static void connection_device_input(struct mux_connection *conn, unsigned char *payload, uint32_t payload_length)
-{
- if((conn->ib_size + payload_length) > conn->ib_capacity) {
- usbmuxd_log(LL_ERROR, "Input buffer overflow on device %d connection %d->%d (space=%d, payload=%d)", conn->dev->id, conn->sport, conn->dport, conn->ib_capacity-conn->ib_size, payload_length);
- connection_teardown(conn);
- return;
- }
- memcpy(conn->ib_buf + conn->ib_size, payload, payload_length);
- conn->ib_size += payload_length;
- conn->rx_recvd += payload_length;
- update_connection(conn);
-}
-
-void device_abort_connect(int device_id, struct mux_client *client)
-{
- FOREACH(struct mux_device *dev, &device_list) {
- if(dev->id == device_id) {
- FOREACH(struct mux_connection *conn, &dev->connections) {
- if(conn->client == client) {
- connection_teardown(conn);
- return;
- }
- } ENDFOREACH
- usbmuxd_log(LL_WARNING, "Attempted to abort for nonexistent connection for device %d", device_id);
- return;
- }
- } ENDFOREACH
- usbmuxd_log(LL_WARNING, "Attempted to abort connection for nonexistent device %d", device_id);
-}
-
-static void device_version_input(struct mux_device *dev, struct version_header *vh)
-{
- if(dev->state != MUXDEV_INIT) {
- usbmuxd_log(LL_WARNING, "Version packet from already initialized device %d", dev->id);
- return;
- }
- vh->major = ntohl(vh->major);
- vh->minor = ntohl(vh->minor);
- if(vh->major != 1 || vh->minor != 0) {
- usbmuxd_log(LL_ERROR, "Device %d has unknown version %d.%d\n", dev->id, vh->major, vh->minor);
- collection_remove(&device_list, dev);
- free(dev);
- return;
- }
- usbmuxd_log(LL_NOTICE, "Connected to v%d.%d device %d on location 0x%x with serial number %s", vh->major, vh->minor, dev->id, usb_get_location(dev->usbdev), usb_get_serial(dev->usbdev));
- dev->state = MUXDEV_ACTIVE;
- collection_init(&dev->connections);
- struct device_info info;
- info.id = dev->id;
- info.location = usb_get_location(dev->usbdev);
- info.serial = usb_get_serial(dev->usbdev);
- info.pid = usb_get_pid(dev->usbdev);
- client_device_add(&info);
-}
-
-static void device_tcp_input(struct mux_device *dev, struct tcphdr *th, unsigned char *payload, uint32_t payload_length)
-{
- uint16_t sport = ntohs(th->th_dport);
- uint16_t dport = ntohs(th->th_sport);
- struct mux_connection *conn = NULL;
-
- usbmuxd_log(LL_DEBUG, "[IN] dev=%d sport=%d dport=%d seq=%d ack=%d flags=0x%x window=%d[%d] len=%d",
- dev->id, dport, sport, ntohl(th->th_seq), ntohl(th->th_ack), th->th_flags, ntohs(th->th_win) << 8, ntohs(th->th_win), payload_length);
-
- if(dev->state != MUXDEV_ACTIVE) {
- usbmuxd_log(LL_ERROR, "Received TCP packet from device %d but the device isn't active yet, discarding\n", dev->id);
- return;
- }
-
- FOREACH(struct mux_connection *lconn, &dev->connections) {
- if(lconn->sport == sport && lconn->dport == dport) {
- conn = lconn;
- break;
- }
- } ENDFOREACH
-
- if(!conn) {
- usbmuxd_log(LL_INFO, "No connection for device %d incoming packet %d->%d", dev->id, dport, sport);
- if(!(th->th_flags & TH_RST)) {
- if(send_anon_rst(dev, sport, dport, ntohl(th->th_seq)) < 0)
- usbmuxd_log(LL_ERROR, "Error sending TCP RST to device %d (%d->%d)", conn->dev->id, sport, dport);
- }
- return;
- }
-
- conn->rx_seq = ntohl(th->th_seq);
- conn->rx_ack = ntohl(th->th_ack);
- conn->rx_win = ntohs(th->th_win) << 8;
-
- if(th->th_flags & TH_RST) {
- char *buf = malloc(payload_length+1);
- memcpy(buf, payload, payload_length);
- if(payload_length && (buf[payload_length-1] == '\n'))
- buf[payload_length-1] = 0;
- buf[payload_length] = 0;
- usbmuxd_log(LL_DEBUG, "RST reason: %s", buf);
- free(buf);
- }
-
- if(conn->state == CONN_CONNECTING) {
- if(th->th_flags != (TH_SYN|TH_ACK)) {
- if(th->th_flags & TH_RST)
- conn->state = CONN_REFUSED;
- usbmuxd_log(LL_INFO, "Connection refused by device %d (%d->%d)", dev->id, sport, dport);
- connection_teardown(conn); //this also sends the notification to the client
- } else {
- conn->tx_seq++;
- conn->tx_ack++;
- conn->rx_recvd = conn->rx_seq;
- if(send_tcp(conn, TH_ACK, NULL, 0) < 0) {
- usbmuxd_log(LL_ERROR, "Error sending TCP ACK to device %d (%d->%d)", dev->id, sport, dport);
- connection_teardown(conn);
- return;
- }
- conn->state = CONN_CONNECTED;
- if(client_notify_connect(conn->client, RESULT_OK) < 0) {
- conn->client = NULL;
- connection_teardown(conn);
- }
- update_connection(conn);
- }
- } else if(conn->state == CONN_CONNECTED) {
- if(th->th_flags != TH_ACK) {
- usbmuxd_log(LL_INFO, "Connection reset by device %d (%d->%d)", dev->id, sport, dport);
- if(th->th_flags & TH_RST)
- conn->state = CONN_DYING;
- connection_teardown(conn);
- } else {
- connection_device_input(conn, payload, payload_length);
- }
- }
-}
-
-void device_data_input(struct usb_device *usbdev, unsigned char *buffer, uint32_t length)
-{
- struct mux_device *dev = NULL;
- FOREACH(struct mux_device *tdev, &device_list) {
- if(tdev->usbdev == usbdev) {
- dev = tdev;
- break;
- }
- } ENDFOREACH
- if(!dev) {
- usbmuxd_log(LL_WARNING, "Cannot find device entry for RX input from USB device %p on location 0x%x", usbdev, usb_get_location(usbdev));
- return;
- }
-
- if(!length)
- return;
-
- // sanity check (should never happen with current USB implementation)
- if((length > USB_MRU) || (length > DEV_MRU)) {
- usbmuxd_log(LL_ERROR, "Too much data received from USB (%d), file a bug", length);
- return;
- }
-
- usbmuxd_log(LL_SPEW, "Mux data input for device %p: %p len %d", dev, buffer, length);
-
- // handle broken up transfers
- if(dev->pktlen) {
- if((length + dev->pktlen) > DEV_MRU) {
- usbmuxd_log(LL_ERROR, "Incoming split packet is too large (%d so far), dropping!", length + dev->pktlen);
- dev->pktlen = 0;
- return;
- }
- memcpy(dev->pktbuf + dev->pktlen, buffer, length);
- struct mux_header *mhdr = (struct mux_header *)dev->pktbuf;
- if((length < USB_MRU) || (ntohl(mhdr->length) == (length + dev->pktlen))) {
- buffer = dev->pktbuf;
- length += dev->pktlen;
- dev->pktlen = 0;
- usbmuxd_log(LL_SPEW, "Gathered mux data from buffer (total size: %d)", length);
- } else {
- dev->pktlen += length;
- usbmuxd_log(LL_SPEW, "Appended mux data to buffer (total size: %d)", dev->pktlen);
- return;
- }
- } else {
- struct mux_header *mhdr = (struct mux_header *)buffer;
- if((length == USB_MRU) && (length < ntohl(mhdr->length))) {
- memcpy(dev->pktbuf, buffer, length);
- dev->pktlen = length;
- usbmuxd_log(LL_SPEW, "Copied mux data to buffer (size: %d)", dev->pktlen);
- return;
- }
- }
-
- struct mux_header *mhdr = (struct mux_header *)buffer;
-
- if(ntohl(mhdr->length) != length) {
- usbmuxd_log(LL_ERROR, "Incoming packet size mismatch (dev %d, expected %d, got %d)", dev->id, ntohl(mhdr->length), length);
- return;
- }
-
- struct tcphdr *th;
- unsigned char *payload;
- uint32_t payload_length;
-
- switch(ntohl(mhdr->protocol)) {
- case MUX_PROTO_VERSION:
- if(length < (sizeof(struct mux_header) + sizeof(struct version_header))) {
- usbmuxd_log(LL_ERROR, "Incoming version packet is too small (%d)", length);
- return;
- }
- device_version_input(dev, (struct version_header *)(mhdr+1));
- break;
- case MUX_PROTO_TCP:
- if(length < (sizeof(struct mux_header) + sizeof(struct tcphdr))) {
- usbmuxd_log(LL_ERROR, "Incoming TCP packet is too small (%d)", length);
- return;
- }
- th = (struct tcphdr *)(mhdr+1);
- payload = (unsigned char *)(th+1);
- payload_length = length - sizeof(struct tcphdr) - sizeof(struct mux_header);
- device_tcp_input(dev, (struct tcphdr *)(mhdr+1), payload, payload_length);
- break;
- default:
- usbmuxd_log(LL_ERROR, "Incoming packet for device %d has unknown protocol 0x%x)", dev->id, ntohl(mhdr->protocol));
- break;
- }
-
-}
-
-int device_add(struct usb_device *usbdev)
-{
- int res;
- int id = get_next_device_id();
- struct mux_device *dev;
- usbmuxd_log(LL_NOTICE, "Connecting to new device on location 0x%x as ID %d", usb_get_location(usbdev), id);
- dev = malloc(sizeof(struct mux_device));
- dev->id = id;
- dev->usbdev = usbdev;
- dev->state = MUXDEV_INIT;
- dev->next_sport = 1;
- dev->pktbuf = malloc(DEV_MRU);
- dev->pktlen = 0;
- struct version_header vh;
- vh.major = htonl(1);
- vh.minor = htonl(0);
- vh.padding = 0;
- if((res = send_packet(dev, MUX_PROTO_VERSION, &vh, NULL, 0)) < 0) {
- usbmuxd_log(LL_ERROR, "Error sending version request packet to device %d", id);
- free(dev);
- return res;
- }
- collection_add(&device_list, dev);
- return 0;
-}
-
-void device_remove(struct usb_device *usbdev)
-{
- FOREACH(struct mux_device *dev, &device_list) {
- if(dev->usbdev == usbdev) {
- usbmuxd_log(LL_NOTICE, "Removed device %d on location 0x%x", dev->id, usb_get_location(usbdev));
- if(dev->state == MUXDEV_ACTIVE) {
- dev->state = MUXDEV_DEAD;
- FOREACH(struct mux_connection *conn, &dev->connections) {
- connection_teardown(conn);
- } ENDFOREACH
- client_device_remove(dev->id);
- collection_free(&dev->connections);
- }
- collection_remove(&device_list, dev);
- free(dev->pktbuf);
- free(dev);
- return;
- }
- } ENDFOREACH
- usbmuxd_log(LL_WARNING, "Cannot find device entry while removing USB device %p on location 0x%x", usbdev, usb_get_location(usbdev));
-}
-
-int device_get_count(void)
-{
- int count = 0;
- FOREACH(struct mux_device *dev, &device_list) {
- if(dev->state == MUXDEV_ACTIVE)
- count++;
- } ENDFOREACH
- return count;
-}
-
-int device_get_list(struct device_info *p)
-{
- int count = 0;
- FOREACH(struct mux_device *dev, &device_list) {
- if(dev->state == MUXDEV_ACTIVE) {
- p->id = dev->id;
- p->serial = usb_get_serial(dev->usbdev);
- p->location = usb_get_location(dev->usbdev);
- p->pid = usb_get_pid(dev->usbdev);
- count++;
- p++;
- }
- } ENDFOREACH
- return count;
-}
-
-int device_get_timeout(void)
-{
- uint64_t oldest = (uint64_t)-1;
- FOREACH(struct mux_device *dev, &device_list) {
- if(dev->state == MUXDEV_ACTIVE) {
- FOREACH(struct mux_connection *conn, &dev->connections) {
- if((conn->state == CONN_CONNECTED) && (conn->flags & CONN_ACK_PENDING) && conn->last_ack_time < oldest)
- oldest = conn->last_ack_time;
- } ENDFOREACH
- }
- } ENDFOREACH
- uint64_t ct = mstime64();
- if(oldest == -1)
- return 100000; //meh
- if((ct - oldest) > ACK_TIMEOUT)
- return 0;
- return ACK_TIMEOUT - (ct - oldest);
-}
-
-void device_check_timeouts(void)
-{
- uint64_t ct = mstime64();
- FOREACH(struct mux_device *dev, &device_list) {
- if(dev->state == MUXDEV_ACTIVE) {
- FOREACH(struct mux_connection *conn, &dev->connections) {
- if((conn->state == CONN_CONNECTED) &&
- (conn->flags & CONN_ACK_PENDING) &&
- (ct - conn->last_ack_time) > ACK_TIMEOUT) {
- usbmuxd_log(LL_DEBUG, "Sending ACK due to expired timeout (%" PRIu64 " -> %" PRIu64 ")", conn->last_ack_time, ct);
- if(send_tcp(conn, TH_ACK, NULL, 0) < 0) {
- usbmuxd_log(LL_ERROR, "Error sending TCP ACK to device %d (%d->%d)", dev->id, conn->sport, conn->dport);
- connection_teardown(conn);
- }
- }
- } ENDFOREACH
- }
- } ENDFOREACH
-}
-
-void device_init(void)
-{
- usbmuxd_log(LL_DEBUG, "device_init");
- collection_init(&device_list);
- next_device_id = 1;
-}
-
-void device_kill_connections(void)
-{
- usbmuxd_log(LL_DEBUG, "device_kill_connections");
- FOREACH(struct mux_device *dev, &device_list) {
- if(dev->state != MUXDEV_INIT) {
- FOREACH(struct mux_connection *conn, &dev->connections) {
- connection_teardown(conn);
- } ENDFOREACH
- }
- } ENDFOREACH
- // give USB a while to send the final connection RSTs and the like
- usb_process_timeout(100);
-}
-
-void device_shutdown(void)
-{
- usbmuxd_log(LL_DEBUG, "device_shutdown");
- FOREACH(struct mux_device *dev, &device_list) {
- FOREACH(struct mux_connection *conn, &dev->connections) {
- connection_teardown(conn);
- } ENDFOREACH
- collection_free(&dev->connections);
- collection_remove(&device_list, dev);
- free(dev);
- } ENDFOREACH
- collection_free(&device_list);
-}
diff --git a/daemon/device.h b/daemon/device.h
deleted file mode 100644
index ea77069..0000000
--- a/daemon/device.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- usbmuxd - iPhone/iPod Touch USB multiplex server daemon
-
-Copyright (C) 2009 Hector Martin "marcan" <hector@marcansoft.com>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 or version 3.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-*/
-
-#ifndef __DEVICE_H__
-#define __DEVICE_H__
-
-#include "usb.h"
-#include "client.h"
-
-struct device_info {
- int id;
- const char *serial;
- uint32_t location;
- uint16_t pid;
-};
-
-void device_data_input(struct usb_device *dev, unsigned char *buf, uint32_t length);
-
-int device_add(struct usb_device *dev);
-void device_remove(struct usb_device *dev);
-
-int device_start_connect(int device_id, uint16_t port, struct mux_client *client);
-void device_client_process(int device_id, struct mux_client *client, short events);
-void device_abort_connect(int device_id, struct mux_client *client);
-
-int device_get_count(void);
-int device_get_list(struct device_info *p);
-
-int device_get_timeout(void);
-void device_check_timeouts(void);
-
-void device_init(void);
-void device_kill_connections(void);
-void device_shutdown(void);
-#endif
diff --git a/daemon/log.c b/daemon/log.c
deleted file mode 100644
index 1973257..0000000
--- a/daemon/log.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- usbmuxd - iPhone/iPod Touch USB multiplex server daemon
-
-Copyright (C) 2009 Hector Martin "marcan" <hector@marcansoft.com>
-Copyright (C) 2009 Nikias Bassen <nikias@gmx.li>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 or version 3.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <time.h>
-#include <sys/time.h>
-#include <syslog.h>
-
-#include "log.h"
-
-int log_level = LL_WARNING;
-
-int log_syslog = 0;
-
-void log_enable_syslog()
-{
- if (!log_syslog) {
- openlog("usbmuxd", LOG_PID, 0);
- log_syslog = 1;
- }
-}
-
-void log_disable_syslog()
-{
- if (log_syslog) {
- closelog();
- }
-}
-
-static int level_to_syslog_level(int level)
-{
- int result = level + LOG_CRIT;
- if (result > LOG_DEBUG) {
- result = LOG_DEBUG;
- }
- return result;
-}
-
-void usbmuxd_log(enum loglevel level, const char *fmt, ...)
-{
- va_list ap;
- char *fs;
- struct timeval ts;
- struct tm *tp;
-
- if(level > log_level)
- return;
-
- gettimeofday(&ts, NULL);
- tp = localtime(&ts.tv_sec);
-
- fs = malloc(20 + strlen(fmt));
-
- if(log_syslog) {
- sprintf(fs, "[%d] %s\n", level, fmt);
- } else {
- strftime(fs, 10, "[%H:%M:%S", tp);
- sprintf(fs+9, ".%03d][%d] %s\n", (int)(ts.tv_usec / 1000), level, fmt);
- }
-
- va_start(ap, fmt);
- if (log_syslog) {
- vsyslog(level_to_syslog_level(level), fs, ap);
- } else {
- vfprintf(stderr, fs, ap);
- }
- va_end(ap);
-
- free(fs);
-}
diff --git a/daemon/log.h b/daemon/log.h
deleted file mode 100644
index eeefa41..0000000
--- a/daemon/log.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- usbmuxd - iPhone/iPod Touch USB multiplex server daemon
-
-Copyright (C) 2009 Hector Martin "marcan" <hector@marcansoft.com>
-Copyright (C) 2009 Nikias Bassen <nikias@gmx.li>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 or version 3.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-*/
-
-#ifndef __LOG_H__
-#define __LOG_H__
-
-enum loglevel {
- LL_FATAL = 0,
- LL_ERROR,
- LL_WARNING,
- LL_NOTICE,
- LL_INFO,
- LL_DEBUG,
- LL_SPEW,
- LL_FLOOD,
-};
-
-extern int log_level;
-
-void log_enable_syslog();
-void log_disable_syslog();
-
-void usbmuxd_log(enum loglevel level, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
-
-
-#endif
diff --git a/daemon/main.c b/daemon/main.c
deleted file mode 100644
index 140bee1..0000000
--- a/daemon/main.c
+++ /dev/null
@@ -1,618 +0,0 @@
-/*
- usbmuxd - iPhone/iPod Touch USB multiplex server daemon
-
-Copyright (C) 2009 Hector Martin "marcan" <hector@marcansoft.com>
-Copyright (C) 2009 Nikias Bassen <nikias@gmx.li>
-Copyright (C) 2009 Paul Sladen <libiphone@paul.sladen.org>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 or version 3.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-*/
-
-#define _BSD_SOURCE
-#define _GNU_SOURCE
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <unistd.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <pwd.h>
-#include <grp.h>
-
-#include "log.h"
-#include "usb.h"
-#include "device.h"
-#include "client.h"
-
-static const char *socket_path = "/var/run/usbmuxd";
-static const char *lockfile = "/var/run/usbmuxd.pid";
-
-int should_exit;
-int should_discover;
-
-static int verbose = 0;
-static int foreground = 0;
-static int drop_privileges = 0;
-static const char *drop_user = NULL;
-static int opt_udev = 0;
-static int opt_exit = 0;
-static int exit_signal = 0;
-static int daemon_pipe;
-
-static int report_to_parent = 0;
-
-int create_socket(void) {
- struct sockaddr_un bind_addr;
- int listenfd;
-
- if(unlink(socket_path) == -1 && errno != ENOENT) {
- usbmuxd_log(LL_FATAL, "unlink(%s) failed: %s", socket_path, strerror(errno));
- return -1;
- }
-
- listenfd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (listenfd == -1) {
- usbmuxd_log(LL_FATAL, "socket() failed: %s", strerror(errno));
- return -1;
- }
-
- bzero(&bind_addr, sizeof(bind_addr));
- bind_addr.sun_family = AF_UNIX;
- strcpy(bind_addr.sun_path, socket_path);
- if (bind(listenfd, (struct sockaddr*)&bind_addr, sizeof(bind_addr)) != 0) {
- usbmuxd_log(LL_FATAL, "bind() failed: %s", strerror(errno));
- return -1;
- }
-
- // Start listening
- if (listen(listenfd, 5) != 0) {
- usbmuxd_log(LL_FATAL, "listen() failed: %s", strerror(errno));
- return -1;
- }
-
- chmod(socket_path, 0666);
-
- return listenfd;
-}
-
-void handle_signal(int sig)
-{
- if (sig != SIGUSR1 && sig != SIGUSR2) {
- usbmuxd_log(LL_NOTICE,"Caught signal %d, exiting", sig);
- should_exit = 1;
- } else {
- if(opt_udev) {
- if (sig == SIGUSR1) {
- usbmuxd_log(LL_INFO, "Caught SIGUSR1, checking if we can terminate (no more devices attached)...");
- if (device_get_count() > 0) {
- // we can't quit, there are still devices attached.
- usbmuxd_log(LL_NOTICE, "Refusing to terminate, there are still devices attached. Kill me with signal 15 (TERM) to force quit.");
- } else {
- // it's safe to quit
- should_exit = 1;
- }
- } else if (sig == SIGUSR2) {
- usbmuxd_log(LL_INFO, "Caught SIGUSR2, scheduling device discovery");
- should_discover = 1;
- }
- } else {
- usbmuxd_log(LL_INFO, "Caught SIGUSR1/2 but we weren't started in --udev mode, ignoring");
- }
- }
-}
-
-void set_signal_handlers(void)
-{
- struct sigaction sa;
- sigset_t set;
-
- // Mask all signals we handle. They will be unmasked by ppoll().
- sigemptyset(&set);
- sigaddset(&set, SIGINT);
- sigaddset(&set, SIGQUIT);
- sigaddset(&set, SIGTERM);
- sigaddset(&set, SIGUSR1);
- sigaddset(&set, SIGUSR2);
- sigprocmask(SIG_SETMASK, &set, NULL);
-
- memset(&sa, 0, sizeof(struct sigaction));
- sa.sa_handler = handle_signal;
- sigaction(SIGINT, &sa, NULL);
- sigaction(SIGQUIT, &sa, NULL);
- sigaction(SIGTERM, &sa, NULL);
- sigaction(SIGUSR1, &sa, NULL);
- sigaction(SIGUSR2, &sa, NULL);
-}
-
-#if defined(__FreeBSD__) || defined(__APPLE__)
-static int ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout, const sigset_t *sigmask)
-{
- int ready;
- sigset_t origmask;
- int to = timeout->tv_sec*1000 + timeout->tv_nsec/1000000;
-
- sigprocmask(SIG_SETMASK, sigmask, &origmask);
- ready = poll(fds, nfds, to);
- sigprocmask(SIG_SETMASK, &origmask, NULL);
-
- return ready;
-}
-#endif
-
-int main_loop(int listenfd)
-{
- int to, cnt, i, dto;
- struct fdlist pollfds;
- struct timespec tspec;
-
- sigset_t empty_sigset;
- sigemptyset(&empty_sigset); // unmask all signals
-
- fdlist_create(&pollfds);
- while(!should_exit) {
- usbmuxd_log(LL_FLOOD, "main_loop iteration");
- to = usb_get_timeout();
- usbmuxd_log(LL_FLOOD, "USB timeout is %d ms", to);
- dto = device_get_timeout();
- usbmuxd_log(LL_FLOOD, "Device timeout is %d ms", to);
- if(dto < to)
- to = dto;
-
- fdlist_reset(&pollfds);
- fdlist_add(&pollfds, FD_LISTEN, listenfd, POLLIN);
- usb_get_fds(&pollfds);
- client_get_fds(&pollfds);
- usbmuxd_log(LL_FLOOD, "fd count is %d", pollfds.count);
-
- tspec.tv_sec = to / 1000;
- tspec.tv_nsec = (to % 1000) * 1000000;
- cnt = ppoll(pollfds.fds, pollfds.count, &tspec, &empty_sigset);
- usbmuxd_log(LL_FLOOD, "poll() returned %d", cnt);
- if(cnt == -1) {
- if(errno == EINTR) {
- if(should_exit) {
- usbmuxd_log(LL_INFO, "Event processing interrupted");
- break;
- }
- if(should_discover) {
- should_discover = 0;
- usbmuxd_log(LL_INFO, "Device discovery triggered by udev");
- usb_discover();
- }
- }
- } else if(cnt == 0) {
- if(usb_process() < 0) {
- usbmuxd_log(LL_FATAL, "usb_process() failed");
- fdlist_free(&pollfds);
- return -1;
- }
- device_check_timeouts();
- } else {
- int done_usb = 0;
- for(i=0; i<pollfds.count; i++) {
- if(pollfds.fds[i].revents) {
- if(!done_usb && pollfds.owners[i] == FD_USB) {
- if(usb_process() < 0) {
- usbmuxd_log(LL_FATAL, "usb_process() failed");
- fdlist_free(&pollfds);
- return -1;
- }
- done_usb = 1;
- }
- if(pollfds.owners[i] == FD_LISTEN) {
- if(client_accept(listenfd) < 0) {
- usbmuxd_log(LL_FATAL, "client_accept() failed");
- fdlist_free(&pollfds);
- return -1;
- }
- }
- if(pollfds.owners[i] == FD_CLIENT) {
- client_process(pollfds.fds[i].fd, pollfds.fds[i].revents);
- }
- }
- }
- }
- }
- fdlist_free(&pollfds);
- return 0;
-}
-
-/**
- * make this program run detached from the current console
- */
-static int daemonize(void)
-{
- pid_t pid;
- pid_t sid;
- int pfd[2];
- int res;
-
- // already a daemon
- if (getppid() == 1)
- return 0;
-
- if((res = pipe(pfd)) < 0) {
- usbmuxd_log(LL_FATAL, "pipe() failed.");
- return res;
- }
-
- pid = fork();
- if (pid < 0) {
- usbmuxd_log(LL_FATAL, "fork() failed.");
- return pid;
- }
-
- if (pid > 0) {
- // exit parent process
- int status;
- close(pfd[1]);
-
- if((res = read(pfd[0],&status,sizeof(int))) != sizeof(int)) {
- fprintf(stderr, "usbmuxd: ERROR: Failed to get init status from child, check syslog for messages.\n");
- exit(1);
- }
- if(status != 0)
- fprintf(stderr, "usbmuxd: ERROR: Child process exited with error %d, check syslog for messages.\n", status);
- exit(status);
- }
- // At this point we are executing as the child process
- // but we need to do one more fork
-
- daemon_pipe = pfd[1];
- close(pfd[0]);
- report_to_parent = 1;
-
- // Change the file mode mask
- umask(0);
-
- // Create a new SID for the child process
- sid = setsid();
- if (sid < 0) {
- usbmuxd_log(LL_FATAL, "setsid() failed.");
- return -1;
- }
-
- pid = fork();
- if (pid < 0) {
- usbmuxd_log(LL_FATAL, "fork() failed (second).");
- return pid;
- }
-
- if (pid > 0) {
- // exit parent process
- close(daemon_pipe);
- exit(0);
- }
-
- // Change the current working directory.
- if ((chdir("/")) < 0) {
- usbmuxd_log(LL_FATAL, "chdir() failed");
- return -2;
- }
- // Redirect standard files to /dev/null
- if (!freopen("/dev/null", "r", stdin)) {
- usbmuxd_log(LL_FATAL, "Redirection of stdin failed.");
- return -3;
- }
- if (!freopen("/dev/null", "w", stdout)) {
- usbmuxd_log(LL_FATAL, "Redirection of stdout failed.");
- return -3;
- }
-
- return 0;
-}
-
-static int notify_parent(int status)
-{
- int res;
-
- report_to_parent = 0;
- if ((res = write(daemon_pipe, &status, sizeof(int))) != sizeof(int)) {
- usbmuxd_log(LL_FATAL, "Could not notify parent!");
- if(res >= 0)
- return -2;
- else
- return res;
- }
- close(daemon_pipe);
- if (!freopen("/dev/null", "w", stderr)) {
- usbmuxd_log(LL_FATAL, "Redirection of stderr failed.");
- return -1;
- }
- return 0;
-}
-
-static void usage()
-{
- printf("usage: usbmuxd [options]\n");
- printf("\t-h|--help Print this message.\n");
- printf("\t-v|--verbose Be verbose (use twice or more to increase).\n");
- printf("\t-f|--foreground Do not daemonize (implies one -v).\n");
- printf("\t-U|--user USER Change to this user after startup (needs usb privileges).\n");
- printf("\t-u|--udev Run in udev operation mode.\n");
- printf("\t-x|--exit Tell a running instance to exit if there are no devices\n");
- printf("\t connected (must be in udev mode).\n");
- printf("\t-X|--force-exit Tell a running instance to exit, even if there are still\n");
- printf("\t devices connected (always works).\n");
- printf("\n");
-}
-
-static void parse_opts(int argc, char **argv)
-{
- static struct option longopts[] = {
- {"help", 0, NULL, 'h'},
- {"foreground", 0, NULL, 'f'},
- {"verbose", 0, NULL, 'v'},
- {"user", 2, NULL, 'U'},
- {"udev", 0, NULL, 'u'},
- {"exit", 0, NULL, 'x'},
- {"force-exit", 0, NULL, 'X'},
- {NULL, 0, NULL, 0}
- };
- int c;
-
- while (1) {
- c = getopt_long(argc, argv, "hfvuU:xX", longopts, (int *) 0);
- if (c == -1) {
- break;
- }
-
- switch (c) {
- case 'h':
- usage();
- exit(0);
- case 'f':
- foreground = 1;
- break;
- case 'v':
- ++verbose;
- break;
- case 'U':
- drop_privileges = 1;
- drop_user = optarg;
- break;
- case 'u':
- opt_udev = 1;
- break;
- case 'x':
- opt_exit = 1;
- exit_signal = SIGUSR1;
- break;
- case 'X':
- opt_exit = 1;
- exit_signal = SIGTERM;
- break;
- default:
- usage();
- exit(2);
- }
- }
-}
-
-int main(int argc, char *argv[])
-{
- int listenfd;
- int res = 0;
- int lfd;
- struct flock lock;
- char pids[10];
-
- parse_opts(argc, argv);
-
- argc -= optind;
- argv += optind;
-
- if (!foreground) {
- verbose += LL_WARNING;
- log_enable_syslog();
- } else {
- verbose += LL_NOTICE;
- }
-
- /* set log level to specified verbosity */
- log_level = verbose;
-
- usbmuxd_log(LL_NOTICE, "usbmuxd v%s starting up", USBMUXD_VERSION);
- should_exit = 0;
- should_discover = 0;
-
- set_signal_handlers();
- signal(SIGPIPE, SIG_IGN);
-
- res = lfd = open(lockfile, O_WRONLY|O_CREAT, 0644);
- if(res == -1) {
- usbmuxd_log(LL_FATAL, "Could not open lockfile");
- goto terminate;
- }
- lock.l_type = F_WRLCK;
- lock.l_whence = SEEK_SET;
- lock.l_start = 0;
- lock.l_len = 0;
- fcntl(lfd, F_GETLK, &lock);
- close(lfd);
- if (lock.l_type != F_UNLCK) {
- if (opt_exit) {
- if (lock.l_pid && !kill(lock.l_pid, 0)) {
- usbmuxd_log(LL_NOTICE, "Sending signal %d to instance with pid %d", exit_signal, lock.l_pid);
- res = 0;
- if (kill(lock.l_pid, exit_signal) < 0) {
- usbmuxd_log(LL_FATAL, "Could not deliver signal %d to pid %d", exit_signal, lock.l_pid);
- res = -1;
- }
- goto terminate;
- } else {
- usbmuxd_log(LL_ERROR, "Could not determine pid of the other running instance!");
- res = -1;
- goto terminate;
- }
- } else {
- if (!opt_udev) {
- usbmuxd_log(LL_ERROR, "Another instance is already running (pid %d). exiting.", lock.l_pid);
- res = -1;
- } else {
- usbmuxd_log(LL_NOTICE, "Another instance is already running (pid %d). Telling it to check for devices.", lock.l_pid);
- if (lock.l_pid && !kill(lock.l_pid, 0)) {
- usbmuxd_log(LL_NOTICE, "Sending signal SIGUSR2 to instance with pid %d", lock.l_pid);
- res = 0;
- if (kill(lock.l_pid, SIGUSR2) < 0) {
- usbmuxd_log(LL_FATAL, "Could not deliver SIGUSR2 to pid %d", lock.l_pid);
- res = -1;
- }
- } else {
- usbmuxd_log(LL_ERROR, "Could not determine pid of the other running instance!");
- res = -1;
- }
- }
- goto terminate;
- }
- }
- unlink(lockfile);
-
- if (opt_exit) {
- usbmuxd_log(LL_NOTICE, "No running instance found, none killed. exiting.");
- goto terminate;
- }
-
- if (!foreground) {
- if ((res = daemonize()) < 0) {
- fprintf(stderr, "usbmuxd: FATAL: Could not daemonize!\n");
- usbmuxd_log(LL_FATAL, "Could not daemonize!");
- goto terminate;
- }
- }
-
- // now open the lockfile and place the lock
- res = lfd = open(lockfile, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644);
- if(res < 0) {
- usbmuxd_log(LL_FATAL, "Could not open lockfile");
- goto terminate;
- }
- lock.l_type = F_WRLCK;
- lock.l_whence = SEEK_SET;
- lock.l_start = 0;
- lock.l_len = 0;
- if ((res = fcntl(lfd, F_SETLK, &lock)) < 0) {
- usbmuxd_log(LL_FATAL, "Lockfile locking failed!");
- goto terminate;
- }
- sprintf(pids, "%d", getpid());
- if ((res = write(lfd, pids, strlen(pids))) != strlen(pids)) {
- usbmuxd_log(LL_FATAL, "Could not write pidfile!");
- if(res >= 0)
- res = -2;
- goto terminate;
- }
-
- usbmuxd_log(LL_INFO, "Creating socket");
- res = listenfd = create_socket();
- if(listenfd < 0)
- goto terminate;
-
- // drop elevated privileges
- if (drop_privileges && (getuid() == 0 || geteuid() == 0)) {
- struct passwd *pw;
- if (!drop_user) {
- usbmuxd_log(LL_FATAL, "No user to drop privileges to?");
- res = -1;
- goto terminate;
- }
- pw = getpwnam(drop_user);
- if (!pw) {
- usbmuxd_log(LL_FATAL, "Dropping privileges failed, check if user '%s' exists!", drop_user);
- res = -1;
- goto terminate;
- }
- if (pw->pw_uid == 0) {
- usbmuxd_log(LL_INFO, "Not dropping privileges to root");
- } else {
- if ((res = initgroups(drop_user, pw->pw_gid)) < 0) {
- usbmuxd_log(LL_FATAL, "Failed to drop privileges (cannot set supplementary groups)");
- goto terminate;
- }
- if ((res = setgid(pw->pw_gid)) < 0) {
- usbmuxd_log(LL_FATAL, "Failed to drop privileges (cannot set group ID to %d)", pw->pw_gid);
- goto terminate;
- }
- if ((res = setuid(pw->pw_uid)) < 0) {
- usbmuxd_log(LL_FATAL, "Failed to drop privileges (cannot set user ID to %d)", pw->pw_uid);
- goto terminate;
- }
-
- // security check
- if (setuid(0) != -1) {
- usbmuxd_log(LL_FATAL, "Failed to drop privileges properly!");
- res = -1;
- goto terminate;
- }
- if (getuid() != pw->pw_uid || getgid() != pw->pw_gid) {
- usbmuxd_log(LL_FATAL, "Failed to drop privileges properly!");
- res = -1;
- goto terminate;
- }
- usbmuxd_log(LL_NOTICE, "Successfully dropped privileges to '%s'", drop_user);
- }
- }
-
- client_init();
- device_init();
- usbmuxd_log(LL_INFO, "Initializing USB");
- if((res = usb_init()) < 0)
- goto terminate;
-
- usbmuxd_log(LL_INFO, "%d device%s detected", res, (res==1)?"":"s");
-
- usbmuxd_log(LL_NOTICE, "Initialization complete");
-
- if (report_to_parent)
- if((res = notify_parent(0)) < 0)
- goto terminate;
-
- if(opt_udev)
- usb_autodiscover(0); // discovery triggered by udev
-
- res = main_loop(listenfd);
- if(res < 0)
- usbmuxd_log(LL_FATAL, "main_loop failed");
-
- usbmuxd_log(LL_NOTICE, "usbmuxd shutting down");
- device_kill_connections();
- usb_shutdown();
- device_shutdown();
- client_shutdown();
- usbmuxd_log(LL_NOTICE, "Shutdown complete");
-
-terminate:
- log_disable_syslog();
-
- if (res < 0)
- res = -res;
- else
- res = 0;
- if (report_to_parent)
- notify_parent(res);
-
- return res;
-}
diff --git a/daemon/usb-linux.c b/daemon/usb-linux.c
deleted file mode 100644
index 334d967..0000000
--- a/daemon/usb-linux.c
+++ /dev/null
@@ -1,598 +0,0 @@
-/*
- usbmuxd - iPhone/iPod Touch USB multiplex server daemon
-
-Copyright (C) 2009 Hector Martin "marcan" <hector@marcansoft.com>
-Copyright (C) 2009 Nikias Bassen <nikias@gmx.li>
-Copyright (C) 2009 Martin Szulecki <opensuse@sukimashita.com>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 or version 3.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-
-#include <libusb.h>
-
-#include "usb.h"
-#include "log.h"
-#include "device.h"
-
-// interval for device connection/disconnection polling, in milliseconds
-// we need this because there is currently no asynchronous device discovery mechanism in libusb
-#define DEVICE_POLL_TIME 1000
-
-struct usb_device {
- libusb_device_handle *dev;
- uint8_t bus, address;
- uint16_t vid, pid;
- char serial[256];
- int alive;
- uint8_t interface, ep_in, ep_out;
- struct libusb_transfer *rx_xfer;
- struct collection tx_xfers;
- int wMaxPacketSize;
-};
-
-static struct collection device_list;
-
-static struct timeval next_dev_poll_time;
-
-static int devlist_failures;
-static int device_polling;
-
-static void usb_disconnect(struct usb_device *dev)
-{
- if(!dev->dev) {
- return;
- }
-
- // kill the rx xfer and tx xfers and try to make sure the callbacks get called before we free the device
- if(dev->rx_xfer) {
- usbmuxd_log(LL_DEBUG, "usb_disconnect: cancelling RX xfer");
- libusb_cancel_transfer(dev->rx_xfer);
- }
- FOREACH(struct libusb_transfer *xfer, &dev->tx_xfers) {
- usbmuxd_log(LL_DEBUG, "usb_disconnect: cancelling TX xfer %p", xfer);
- libusb_cancel_transfer(xfer);
- } ENDFOREACH
-
- while(dev->rx_xfer || collection_count(&dev->tx_xfers)) {
- struct timeval tv;
- int res;
-
- tv.tv_sec = 0;
- tv.tv_usec = 1000;
- if((res = libusb_handle_events_timeout(NULL, &tv)) < 0) {
- usbmuxd_log(LL_ERROR, "libusb_handle_events_timeout for usb_disconnect failed: %d", res);
- break;
- }
- }
- collection_free(&dev->tx_xfers);
- libusb_release_interface(dev->dev, dev->interface);
- libusb_close(dev->dev);
- dev->dev = NULL;
- collection_remove(&device_list, dev);
- free(dev);
-}
-
-static void tx_callback(struct libusb_transfer *xfer)
-{
- struct usb_device *dev = xfer->user_data;
- usbmuxd_log(LL_SPEW, "TX callback dev %d-%d len %d -> %d status %d", dev->bus, dev->address, xfer->length, xfer->actual_length, xfer->status);
- if(xfer->status != LIBUSB_TRANSFER_COMPLETED) {
- switch(xfer->status) {
- case LIBUSB_TRANSFER_COMPLETED: //shut up compiler
- case LIBUSB_TRANSFER_ERROR:
- // funny, this happens when we disconnect the device while waiting for a transfer, sometimes
- usbmuxd_log(LL_INFO, "Device %d-%d TX aborted due to error or disconnect", dev->bus, dev->address);
- break;
- case LIBUSB_TRANSFER_TIMED_OUT:
- usbmuxd_log(LL_ERROR, "TX transfer timed out for device %d-%d", dev->bus, dev->address);
- break;
- case LIBUSB_TRANSFER_CANCELLED:
- usbmuxd_log(LL_DEBUG, "Device %d-%d TX transfer cancelled", dev->bus, dev->address);
- break;
- case LIBUSB_TRANSFER_STALL:
- usbmuxd_log(LL_ERROR, "TX transfer stalled for device %d-%d", dev->bus, dev->address);
- break;
- case LIBUSB_TRANSFER_NO_DEVICE:
- // other times, this happens, and also even when we abort the transfer after device removal
- usbmuxd_log(LL_INFO, "Device %d-%d TX aborted due to disconnect", dev->bus, dev->address);
- break;
- case LIBUSB_TRANSFER_OVERFLOW:
- usbmuxd_log(LL_ERROR, "TX transfer overflow for device %d-%d", dev->bus, dev->address);
- break;
- // and nothing happens (this never gets called) if the device is freed after a disconnect! (bad)
- }
- // we can't usb_disconnect here due to a deadlock, so instead mark it as dead and reap it after processing events
- // we'll do device_remove there too
- dev->alive = 0;
- }
- if(xfer->buffer)
- free(xfer->buffer);
- collection_remove(&dev->tx_xfers, xfer);
- libusb_free_transfer(xfer);
-}
-
-int usb_send(struct usb_device *dev, const unsigned char *buf, int length)
-{
- int res;
- struct libusb_transfer *xfer = libusb_alloc_transfer(0);
- libusb_fill_bulk_transfer(xfer, dev->dev, dev->ep_out, (void*)buf, length, tx_callback, dev, 0);
- if((res = libusb_submit_transfer(xfer)) < 0) {
- usbmuxd_log(LL_ERROR, "Failed to submit TX transfer %p len %d to device %d-%d: %d", buf, length, dev->bus, dev->address, res);
- libusb_free_transfer(xfer);
- return res;
- }
- collection_add(&dev->tx_xfers, xfer);
- if (length % dev->wMaxPacketSize == 0) {
- usbmuxd_log(LL_DEBUG, "Send ZLP");
- // Send Zero Length Packet
- xfer = libusb_alloc_transfer(0);
- void *buffer = malloc(1);
- libusb_fill_bulk_transfer(xfer, dev->dev, dev->ep_out, buffer, 0, tx_callback, dev, 0);
- if((res = libusb_submit_transfer(xfer)) < 0) {
- usbmuxd_log(LL_ERROR, "Failed to submit TX ZLP transfer to device %d-%d: %d", dev->bus, dev->address, res);
- libusb_free_transfer(xfer);
- return res;
- }
- collection_add(&dev->tx_xfers, xfer);
- }
- return 0;
-}
-
-static void rx_callback(struct libusb_transfer *xfer)
-{
- struct usb_device *dev = xfer->user_data;
- usbmuxd_log(LL_SPEW, "RX callback dev %d-%d len %d status %d", dev->bus, dev->address, xfer->actual_length, xfer->status);
- if(xfer->status == LIBUSB_TRANSFER_COMPLETED) {
- device_data_input(dev, xfer->buffer, xfer->actual_length);
- libusb_submit_transfer(xfer);
- } else {
- switch(xfer->status) {
- case LIBUSB_TRANSFER_COMPLETED: //shut up compiler
- case LIBUSB_TRANSFER_ERROR:
- // funny, this happens when we disconnect the device while waiting for a transfer, sometimes
- usbmuxd_log(LL_INFO, "Device %d-%d RX aborted due to error or disconnect", dev->bus, dev->address);
- break;
- case LIBUSB_TRANSFER_TIMED_OUT:
- usbmuxd_log(LL_ERROR, "RX transfer timed out for device %d-%d", dev->bus, dev->address);
- break;
- case LIBUSB_TRANSFER_CANCELLED:
- usbmuxd_log(LL_DEBUG, "Device %d-%d RX transfer cancelled", dev->bus, dev->address);
- break;
- case LIBUSB_TRANSFER_STALL:
- usbmuxd_log(LL_ERROR, "RX transfer stalled for device %d-%d", dev->bus, dev->address);
- break;
- case LIBUSB_TRANSFER_NO_DEVICE:
- // other times, this happens, and also even when we abort the transfer after device removal
- usbmuxd_log(LL_INFO, "Device %d-%d RX aborted due to disconnect", dev->bus, dev->address);
- break;
- case LIBUSB_TRANSFER_OVERFLOW:
- usbmuxd_log(LL_ERROR, "RX transfer overflow for device %d-%d", dev->bus, dev->address);
- break;
- // and nothing happens (this never gets called) if the device is freed after a disconnect! (bad)
- }
- free(xfer->buffer);
- dev->rx_xfer = NULL;
- libusb_free_transfer(xfer);
- // we can't usb_disconnect here due to a deadlock, so instead mark it as dead and reap it after processing events
- // we'll do device_remove there too
- dev->alive = 0;
- }
-}
-
-static int start_rx(struct usb_device *dev)
-{
- int res;
- void *buf;
- dev->rx_xfer = libusb_alloc_transfer(0);
- buf = malloc(USB_MRU);
- libusb_fill_bulk_transfer(dev->rx_xfer, dev->dev, dev->ep_in, buf, USB_MRU, rx_callback, dev, 0);
- if((res = libusb_submit_transfer(dev->rx_xfer)) != 0) {
- usbmuxd_log(LL_ERROR, "Failed to submit RX transfer to device %d-%d: %d", dev->bus, dev->address, res);
- libusb_free_transfer(dev->rx_xfer);
- dev->rx_xfer = NULL;
- return res;
- }
- return 0;
-}
-
-int usb_discover(void)
-{
- int cnt, i, j, res;
- int valid_count = 0;
- libusb_device **devs;
-
- cnt = libusb_get_device_list(NULL, &devs);
- if(cnt < 0) {
- usbmuxd_log(LL_WARNING, "Could not get device list: %d", cnt);
- devlist_failures++;
- // sometimes libusb fails getting the device list if you've just removed something
- if(devlist_failures > 5) {
- usbmuxd_log(LL_FATAL, "Too many errors getting device list\n");
- return cnt;
- } else {
- gettimeofday(&next_dev_poll_time, NULL);
- next_dev_poll_time.tv_usec += DEVICE_POLL_TIME * 1000;
- next_dev_poll_time.tv_sec += next_dev_poll_time.tv_usec / 1000000;
- next_dev_poll_time.tv_usec = next_dev_poll_time.tv_usec % 1000000;
- return 0;
- }
- }
- devlist_failures = 0;
-
- usbmuxd_log(LL_SPEW, "usb_discover: scanning %d devices", cnt);
-
- FOREACH(struct usb_device *usbdev, &device_list) {
- usbdev->alive = 0;
- } ENDFOREACH
-
- for(i=0; i<cnt; i++) {
- // the following are non-blocking operations on the device list
- libusb_device *dev = devs[i];
- uint8_t bus = libusb_get_bus_number(dev);
- uint8_t address = libusb_get_device_address(dev);
- struct libusb_device_descriptor devdesc;
- int found = 0;
- FOREACH(struct usb_device *usbdev, &device_list) {
- if(usbdev->bus == bus && usbdev->address == address) {
- valid_count++;
- usbdev->alive = 1;
- found = 1;
- break;
- }
- } ENDFOREACH
- if(found)
- continue; //device already found
- if((res = libusb_get_device_descriptor(dev, &devdesc)) != 0) {
- usbmuxd_log(LL_WARNING, "Could not get device descriptor for device %d-%d: %d", bus, address, res);
- continue;
- }
- if(devdesc.idVendor != VID_APPLE)
- continue;
- if((devdesc.idProduct < PID_RANGE_LOW) ||
- (devdesc.idProduct > PID_RANGE_MAX))
- continue;
- libusb_device_handle *handle;
- usbmuxd_log(LL_INFO, "Found new device with v/p %04x:%04x at %d-%d", devdesc.idVendor, devdesc.idProduct, bus, address);
- // potentially blocking operations follow; they will only run when new devices are detected, which is acceptable
- if((res = libusb_open(dev, &handle)) != 0) {
- usbmuxd_log(LL_WARNING, "Could not open device %d-%d: %d", bus, address, res);
- continue;
- }
- int current_config = 0;
- if((res = libusb_get_configuration(handle, &current_config)) != 0) {
- usbmuxd_log(LL_WARNING, "Could not get configuration for device %d-%d: %d", bus, address, res);
- libusb_close(handle);
- continue;
- }
- if (current_config != devdesc.bNumConfigurations) {
- struct libusb_config_descriptor *config;
- if((res = libusb_get_active_config_descriptor(dev, &config)) != 0) {
- usbmuxd_log(LL_NOTICE, "Could not get old configuration descriptor for device %d-%d: %d", bus, address, res);
- } else {
- for(j=0; j<config->bNumInterfaces; j++) {
- const struct libusb_interface_descriptor *intf = &config->interface[j].altsetting[0];
- if((res = libusb_kernel_driver_active(handle, intf->bInterfaceNumber)) < 0) {
- usbmuxd_log(LL_NOTICE, "Could not check kernel ownership of interface %d for device %d-%d: %d", intf->bInterfaceNumber, bus, address, res);
- continue;
- }
- if(res == 1) {
- usbmuxd_log(LL_INFO, "Detaching kernel driver for device %d-%d, interface %d", bus, address, intf->bInterfaceNumber);
- if((res = libusb_detach_kernel_driver(handle, intf->bInterfaceNumber)) < 0) {
- usbmuxd_log(LL_WARNING, "Could not detach kernel driver (%d), configuration change will probably fail!", res);
- continue;
- }
- }
- }
- libusb_free_config_descriptor(config);
- }
- if((res = libusb_set_configuration(handle, devdesc.bNumConfigurations)) != 0) {
- usbmuxd_log(LL_WARNING, "Could not set configuration %d for device %d-%d: %d", devdesc.bNumConfigurations, bus, address, res);
- libusb_close(handle);
- continue;
- }
- }
-
- struct libusb_config_descriptor *config;
- if((res = libusb_get_active_config_descriptor(dev, &config)) != 0) {
- usbmuxd_log(LL_WARNING, "Could not get configuration descriptor for device %d-%d: %d", bus, address, res);
- libusb_close(handle);
- continue;
- }
-
- struct usb_device *usbdev;
- usbdev = malloc(sizeof(struct usb_device));
- memset(usbdev, 0, sizeof(*usbdev));
-
- for(j=0; j<config->bNumInterfaces; j++) {
- const struct libusb_interface_descriptor *intf = &config->interface[j].altsetting[0];
- if(intf->bInterfaceClass != INTERFACE_CLASS ||
- intf->bInterfaceSubClass != INTERFACE_SUBCLASS ||
- intf->bInterfaceProtocol != INTERFACE_PROTOCOL)
- continue;
- if(intf->bNumEndpoints != 2) {
- usbmuxd_log(LL_WARNING, "Endpoint count mismatch for interface %d of device %d-%d", intf->bInterfaceNumber, bus, address);
- continue;
- }
- if((intf->endpoint[0].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_OUT &&
- (intf->endpoint[1].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_IN) {
- usbdev->interface = intf->bInterfaceNumber;
- usbdev->ep_out = intf->endpoint[0].bEndpointAddress;
- usbdev->ep_in = intf->endpoint[1].bEndpointAddress;
- usbmuxd_log(LL_INFO, "Found interface %d with endpoints %02x/%02x for device %d-%d", usbdev->interface, usbdev->ep_out, usbdev->ep_in, bus, address);
- break;
- } else if((intf->endpoint[1].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_OUT &&
- (intf->endpoint[0].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_IN) {
- usbdev->interface = intf->bInterfaceNumber;
- usbdev->ep_out = intf->endpoint[1].bEndpointAddress;
- usbdev->ep_in = intf->endpoint[0].bEndpointAddress;
- usbmuxd_log(LL_INFO, "Found interface %d with swapped endpoints %02x/%02x for device %d-%d", usbdev->interface, usbdev->ep_out, usbdev->ep_in, bus, address);
- break;
- } else {
- usbmuxd_log(LL_WARNING, "Endpoint type mismatch for interface %d of device %d-%d", intf->bInterfaceNumber, bus, address);
- }
- }
-
- if(j == config->bNumInterfaces) {
- usbmuxd_log(LL_WARNING, "Could not find a suitable USB interface for device %d-%d", bus, address);
- libusb_free_config_descriptor(config);
- libusb_close(handle);
- free(usbdev);
- continue;
- }
-
- libusb_free_config_descriptor(config);
-
- if((res = libusb_claim_interface(handle, usbdev->interface)) != 0) {
- usbmuxd_log(LL_WARNING, "Could not claim interface %d for device %d-%d: %d", usbdev->interface, bus, address, res);
- libusb_close(handle);
- free(usbdev);
- continue;
- }
-
- if((res = libusb_get_string_descriptor_ascii(handle, devdesc.iSerialNumber, (uint8_t *)usbdev->serial, 256)) <= 0) {
- usbmuxd_log(LL_WARNING, "Could not get serial number for device %d-%d: %d", bus, address, res);
- libusb_release_interface(handle, usbdev->interface);
- libusb_close(handle);
- free(usbdev);
- continue;
- }
- usbdev->serial[res] = 0;
- usbdev->bus = bus;
- usbdev->address = address;
- usbdev->vid = devdesc.idVendor;
- usbdev->pid = devdesc.idProduct;
- usbdev->dev = handle;
- usbdev->alive = 1;
- usbdev->wMaxPacketSize = libusb_get_max_packet_size(dev, usbdev->ep_out);
- if (usbdev->wMaxPacketSize <= 0) {
- usbmuxd_log(LL_ERROR, "Could not determine wMaxPacketSize for device %d-%d, setting to 64", usbdev->bus, usbdev->address);
- usbdev->wMaxPacketSize = 64;
- } else {
- usbmuxd_log(LL_INFO, "Using wMaxPacketSize=%d for device %d-%d", usbdev->wMaxPacketSize, usbdev->bus, usbdev->address);
- }
-
- collection_init(&usbdev->tx_xfers);
-
- collection_add(&device_list, usbdev);
-
- if(device_add(usbdev) < 0) {
- usb_disconnect(usbdev);
- continue;
- }
- if(start_rx(usbdev) < 0) {
- device_remove(usbdev);
- usb_disconnect(usbdev);
- continue;
- }
- valid_count++;
- }
- FOREACH(struct usb_device *usbdev, &device_list) {
- if(!usbdev->alive) {
- device_remove(usbdev);
- usb_disconnect(usbdev);
- }
- } ENDFOREACH
-
- libusb_free_device_list(devs, 1);
-
- gettimeofday(&next_dev_poll_time, NULL);
- next_dev_poll_time.tv_usec += DEVICE_POLL_TIME * 1000;
- next_dev_poll_time.tv_sec += next_dev_poll_time.tv_usec / 1000000;
- next_dev_poll_time.tv_usec = next_dev_poll_time.tv_usec % 1000000;
-
- return valid_count;
-}
-
-const char *usb_get_serial(struct usb_device *dev)
-{
- if(!dev->dev) {
- return NULL;
- }
- return dev->serial;
-}
-
-uint32_t usb_get_location(struct usb_device *dev)
-{
- if(!dev->dev) {
- return 0;
- }
- return (dev->bus << 16) | dev->address;
-}
-
-uint16_t usb_get_pid(struct usb_device *dev)
-{
- if(!dev->dev) {
- return 0;
- }
- return dev->pid;
-}
-
-void usb_get_fds(struct fdlist *list)
-{
- const struct libusb_pollfd **usbfds;
- const struct libusb_pollfd **p;
- usbfds = libusb_get_pollfds(NULL);
- if(!usbfds) {
- usbmuxd_log(LL_ERROR, "libusb_get_pollfds failed");
- return;
- }
- p = usbfds;
- while(*p) {
- fdlist_add(list, FD_USB, (*p)->fd, (*p)->events);
- p++;
- }
- free(usbfds);
-}
-
-void usb_autodiscover(int enable)
-{
- usbmuxd_log(LL_DEBUG, "usb polling enable: %d", enable);
- device_polling = enable;
-}
-
-static int dev_poll_remain_ms(void)
-{
- int msecs;
- struct timeval tv;
- if(!device_polling)
- return 100000; // devices will never be polled if this is > 0
- gettimeofday(&tv, NULL);
- msecs = (next_dev_poll_time.tv_sec - tv.tv_sec) * 1000;
- msecs += (next_dev_poll_time.tv_usec - tv.tv_usec) / 1000;
- if(msecs < 0)
- return 0;
- return msecs;
-}
-
-int usb_get_timeout(void)
-{
- struct timeval tv;
- int msec;
- int res;
- int pollrem;
- pollrem = dev_poll_remain_ms();
- res = libusb_get_next_timeout(NULL, &tv);
- if(res == 0)
- return pollrem;
- if(res < 0) {
- usbmuxd_log(LL_ERROR, "libusb_get_next_timeout failed: %d", res);
- return pollrem;
- }
- msec = tv.tv_sec * 1000;
- msec += tv.tv_usec / 1000;
- if(msec > pollrem)
- return pollrem;
- return msec;
-}
-
-int usb_process(void)
-{
- int res;
- struct timeval tv;
- tv.tv_sec = tv.tv_usec = 0;
- res = libusb_handle_events_timeout(NULL, &tv);
- if(res < 0) {
- usbmuxd_log(LL_ERROR, "libusb_handle_events_timeout failed: %d", res);
- return res;
- }
- // reap devices marked dead due to an RX error
- FOREACH(struct usb_device *usbdev, &device_list) {
- if(!usbdev->alive) {
- device_remove(usbdev);
- usb_disconnect(usbdev);
- }
- } ENDFOREACH
-
- if(dev_poll_remain_ms() <= 0) {
- res = usb_discover();
- if(res < 0) {
- usbmuxd_log(LL_ERROR, "usb_discover failed: %d", res);
- return res;
- }
- }
- return 0;
-}
-
-int usb_process_timeout(int msec)
-{
- int res;
- struct timeval tleft, tcur, tfin;
- gettimeofday(&tcur, NULL);
- tfin.tv_sec = tcur.tv_sec + (msec / 1000);
- tfin.tv_usec = tcur.tv_usec + (msec % 1000) * 1000;
- tfin.tv_sec += tfin.tv_usec / 1000000;
- tfin.tv_usec %= 1000000;
- while((tfin.tv_sec > tcur.tv_sec) || ((tfin.tv_sec == tcur.tv_sec) && (tfin.tv_usec > tcur.tv_usec))) {
- tleft.tv_sec = tfin.tv_sec - tcur.tv_sec;
- tleft.tv_usec = tfin.tv_usec - tcur.tv_usec;
- if(tleft.tv_usec < 0) {
- tleft.tv_usec += 1000000;
- tleft.tv_sec -= 1;
- }
- res = libusb_handle_events_timeout(NULL, &tleft);
- if(res < 0) {
- usbmuxd_log(LL_ERROR, "libusb_handle_events_timeout failed: %d", res);
- return res;
- }
- // reap devices marked dead due to an RX error
- FOREACH(struct usb_device *usbdev, &device_list) {
- if(!usbdev->alive) {
- device_remove(usbdev);
- usb_disconnect(usbdev);
- }
- } ENDFOREACH
- gettimeofday(&tcur, NULL);
- }
- return 0;
-}
-
-int usb_init(void)
-{
- int res;
- usbmuxd_log(LL_DEBUG, "usb_init for linux / libusb 1.0");
-
- devlist_failures = 0;
- device_polling = 1;
- res = libusb_init(NULL);
- //libusb_set_debug(NULL, 3);
- if(res != 0) {
- usbmuxd_log(LL_FATAL, "libusb_init failed: %d", res);
- return -1;
- }
-
- collection_init(&device_list);
-
- return usb_discover();
-}
-
-void usb_shutdown(void)
-{
- usbmuxd_log(LL_DEBUG, "usb_shutdown");
- FOREACH(struct usb_device *usbdev, &device_list) {
- device_remove(usbdev);
- usb_disconnect(usbdev);
- } ENDFOREACH
- collection_free(&device_list);
- libusb_exit(NULL);
-}
diff --git a/daemon/usb.h b/daemon/usb.h
deleted file mode 100644
index 6fe7ee6..0000000
--- a/daemon/usb.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- usbmuxd - iPhone/iPod Touch USB multiplex server daemon
-
-Copyright (C) 2009 Hector Martin "marcan" <hector@marcansoft.com>
-Copyright (C) 2009 Nikias Bassen <nikias@gmx.li>
-Copyright (C) 2009 Martin Szulecki <opensuse@sukimashita.com>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 or version 3.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-*/
-
-#ifndef __USB_H__
-#define __USB_H__
-
-#include <stdint.h>
-#include "utils.h"
-
-#define INTERFACE_CLASS 255
-#define INTERFACE_SUBCLASS 254
-#define INTERFACE_PROTOCOL 2
-
-// libusb fragments packets larger than this (usbfs limitation)
-// on input, this creates race conditions and other issues
-#define USB_MRU 16384
-
-// max transmission packet size
-// libusb fragments these too, but doesn't send ZLPs so we're safe
-// but we need to send a ZLP ourselves at the end (see usb-linux.c)
-// we're using 3 * 16384 to optimize for the fragmentation
-// this results in three URBs per full transfer, 32 USB packets each
-// if there are ZLP issues this should make them show up easily too
-#define USB_MTU (3 * 16384)
-
-#define USB_PACKET_SIZE 512
-
-#define VID_APPLE 0x5ac
-#define PID_RANGE_LOW 0x1290
-#define PID_RANGE_MAX 0x12af
-
-struct usb_device;
-
-int usb_init(void);
-void usb_shutdown(void);
-const char *usb_get_serial(struct usb_device *dev);
-uint32_t usb_get_location(struct usb_device *dev);
-uint16_t usb_get_pid(struct usb_device *dev);
-void usb_get_fds(struct fdlist *list);
-int usb_get_timeout(void);
-int usb_send(struct usb_device *dev, const unsigned char *buf, int length);
-int usb_discover(void);
-void usb_autodiscover(int enable);
-int usb_process(void);
-int usb_process_timeout(int msec);
-
-#endif