diff options
| author | 2009-04-28 02:02:55 +0200 | |
|---|---|---|
| committer | 2009-04-28 02:02:55 +0200 | |
| commit | cc9e6a2318352a8fd3a35c25fcb294331ff54288 (patch) | |
| tree | 75b891a06a7eddf9674327ae387784b0c64967b0 | |
| parent | d982007a7350df35c5aeba820a520779694514a7 (diff) | |
| download | usbmuxd-cc9e6a2318352a8fd3a35c25fcb294331ff54288.tar.gz usbmuxd-cc9e6a2318352a8fd3a35c25fcb294331ff54288.tar.bz2 | |
USB mostly complete, main loop added, polls for devices
| -rw-r--r-- | CMakeLists.txt | 2 | ||||
| -rw-r--r-- | device.c | 56 | ||||
| -rw-r--r-- | device.h | 29 | ||||
| -rw-r--r-- | log.c | 18 | ||||
| -rw-r--r-- | log.h | 14 | ||||
| -rw-r--r-- | main.c | 66 | ||||
| -rw-r--r-- | usb-linux.c | 251 | ||||
| -rw-r--r-- | usb.h | 18 | ||||
| -rw-r--r-- | utils.c | 6 | ||||
| -rw-r--r-- | utils.h | 16 |
10 files changed, 440 insertions, 36 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 81a6965..acbc779 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
| @@ -11,6 +11,6 @@ set(LIBS ${LIBS} ${USB_LIBRARIES}) | |||
| 11 | #set(CMAKE_VERBOSE_MAKEFILE ON) | 11 | #set(CMAKE_VERBOSE_MAKEFILE ON) |
| 12 | 12 | ||
| 13 | add_definitions(-Wall -O2) | 13 | add_definitions(-Wall -O2) |
| 14 | add_executable(usbmuxd main.c usb-linux.c log.c utils.c) | 14 | add_executable(usbmuxd main.c usb-linux.c log.c utils.c device.c) |
| 15 | target_link_libraries(usbmuxd ${LIBS}) | 15 | target_link_libraries(usbmuxd ${LIBS}) |
| 16 | 16 | ||
diff --git a/device.c b/device.c new file mode 100644 index 0000000..659f4ae --- /dev/null +++ b/device.c | |||
| @@ -0,0 +1,56 @@ | |||
| 1 | /* | ||
| 2 | usbmuxd - iPhone/iPod Touch USB multiplex server daemon | ||
| 3 | |||
| 4 | Copyright (C) 2009 Hector Martin "marcan" <hector@marcansoft.com> | ||
| 5 | |||
| 6 | This program is free software; you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation, either version 2 or version 3. | ||
| 9 | |||
| 10 | This program is distributed in the hope that it will be useful, | ||
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | GNU General Public License for more details. | ||
| 14 | |||
| 15 | You should have received a copy of the GNU General Public License | ||
| 16 | along with this program; if not, write to the Free Software | ||
| 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 18 | |||
| 19 | */ | ||
| 20 | |||
| 21 | #ifdef HAVE_CONFIG_H | ||
| 22 | #include <config.h> | ||
| 23 | #endif | ||
| 24 | |||
| 25 | #include <stdlib.h> | ||
| 26 | #include "device.h" | ||
| 27 | #include "usb.h" | ||
| 28 | #include "log.h" | ||
| 29 | |||
| 30 | int device_id; | ||
| 31 | /* | ||
| 32 | int get_next_device_id(void) | ||
| 33 | { | ||
| 34 | int i; | ||
| 35 | while(1) { | ||
| 36 | for(i=0; i<num_devs; i++) { | ||
| 37 | if(device_list[i].dev && device_list[i].id == device_id) { | ||
| 38 | device_id++; | ||
| 39 | break; | ||
| 40 | } | ||
| 41 | } | ||
| 42 | if(i < num_devs) | ||
| 43 | break; | ||
| 44 | } | ||
| 45 | return device_id++; | ||
| 46 | } | ||
| 47 | */ | ||
| 48 | void device_add(struct usb_device *dev) | ||
| 49 | { | ||
| 50 | usbmuxd_log(LL_NOTICE, "Connected to new device on location 0x%x with serial number %s", usb_get_location(dev), usb_get_serial(dev)); | ||
| 51 | } | ||
| 52 | |||
| 53 | void device_remove(struct usb_device *dev) | ||
| 54 | { | ||
| 55 | usbmuxd_log(LL_NOTICE, "Removed device on location 0x%x with serial number %s", usb_get_location(dev), usb_get_serial(dev)); | ||
| 56 | } | ||
diff --git a/device.h b/device.h new file mode 100644 index 0000000..11beaea --- /dev/null +++ b/device.h | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | /* | ||
| 2 | usbmuxd - iPhone/iPod Touch USB multiplex server daemon | ||
| 3 | |||
| 4 | Copyright (C) 2009 Hector Martin "marcan" <hector@marcansoft.com> | ||
| 5 | |||
| 6 | This program is free software; you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation, either version 2 or version 3. | ||
| 9 | |||
| 10 | This program is distributed in the hope that it will be useful, | ||
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | GNU General Public License for more details. | ||
| 14 | |||
| 15 | You should have received a copy of the GNU General Public License | ||
| 16 | along with this program; if not, write to the Free Software | ||
| 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 18 | |||
| 19 | */ | ||
| 20 | |||
| 21 | #ifndef __DEVICE_H__ | ||
| 22 | #define __DEVICE_H__ | ||
| 23 | |||
| 24 | #include "usb.h" | ||
| 25 | |||
| 26 | void device_add(struct usb_device *dev); | ||
| 27 | void device_remove(struct usb_device *dev); | ||
| 28 | |||
| 29 | #endif | ||
| @@ -26,25 +26,33 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |||
| 26 | #include <stdlib.h> | 26 | #include <stdlib.h> |
| 27 | #include <string.h> | 27 | #include <string.h> |
| 28 | #include <stdarg.h> | 28 | #include <stdarg.h> |
| 29 | #include <time.h> | ||
| 30 | #include <sys/time.h> | ||
| 29 | 31 | ||
| 30 | #include "log.h" | 32 | #include "log.h" |
| 31 | 33 | ||
| 32 | int log_level = LOG_SPEW; | 34 | int log_level = LL_SPEW; |
| 33 | 35 | ||
| 34 | void usbmuxd_log(enum loglevel level, const char *fmt, ...) | 36 | void usbmuxd_log(enum loglevel level, const char *fmt, ...) |
| 35 | { | 37 | { |
| 36 | va_list ap; | 38 | va_list ap; |
| 37 | char *fs; | 39 | char *fs; |
| 40 | struct timeval ts; | ||
| 41 | struct tm *tp; | ||
| 38 | 42 | ||
| 39 | if(level < log_level) | 43 | gettimeofday(&ts, NULL); |
| 44 | tp = localtime(&ts.tv_sec); | ||
| 45 | |||
| 46 | if(level > log_level) | ||
| 40 | return; | 47 | return; |
| 41 | 48 | ||
| 42 | fs = malloc(10 + strlen(fmt)); | 49 | fs = malloc(20 + strlen(fmt)); |
| 43 | sprintf(fs, "[%d] %s\n", level, fmt); | 50 | strftime(fs, 10, "[%H:%M:%S", tp); |
| 51 | sprintf(fs+9, ".%03d][%d] %s\n", (int)(ts.tv_usec / 1000), level, fmt); | ||
| 44 | 52 | ||
| 45 | va_start(ap, fmt); | 53 | va_start(ap, fmt); |
| 46 | vfprintf(stderr, fs, ap); | 54 | vfprintf(stderr, fs, ap); |
| 47 | va_end(ap); | 55 | va_end(ap); |
| 48 | 56 | ||
| 49 | free(fs); | 57 | free(fs); |
| 50 | } \ No newline at end of file | 58 | } |
| @@ -22,13 +22,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |||
| 22 | #define __LOG_H__ | 22 | #define __LOG_H__ |
| 23 | 23 | ||
| 24 | enum loglevel { | 24 | enum loglevel { |
| 25 | LOG_SPEW = 0, | 25 | LL_FATAL = 0, |
| 26 | LOG_DEBUG, | 26 | LL_ERROR, |
| 27 | LOG_INFO, | 27 | LL_WARNING, |
| 28 | LOG_NOTICE, | 28 | LL_NOTICE, |
| 29 | LOG_WARNING, | 29 | LL_INFO, |
| 30 | LOG_ERROR, | 30 | LL_DEBUG, |
| 31 | LOG_FATAL, | 31 | LL_SPEW, |
| 32 | }; | 32 | }; |
| 33 | 33 | ||
| 34 | extern int log_level; | 34 | extern int log_level; |
| @@ -42,13 +42,13 @@ int create_socket(void) { | |||
| 42 | int listenfd; | 42 | int listenfd; |
| 43 | 43 | ||
| 44 | if(unlink(socket_path) == -1 && errno != ENOENT) { | 44 | if(unlink(socket_path) == -1 && errno != ENOENT) { |
| 45 | usbmuxd_log(LOG_FATAL, "unlink(%s) failed: %s", socket_path, strerror(errno)); | 45 | usbmuxd_log(LL_FATAL, "unlink(%s) failed: %s", socket_path, strerror(errno)); |
| 46 | return -1; | 46 | return -1; |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | listenfd = socket(AF_UNIX, SOCK_STREAM, 0); | 49 | listenfd = socket(AF_UNIX, SOCK_STREAM, 0); |
| 50 | if (listenfd == -1) { | 50 | if (listenfd == -1) { |
| 51 | usbmuxd_log(LOG_FATAL, "socket() failed: %s", strerror(errno)); | 51 | usbmuxd_log(LL_FATAL, "socket() failed: %s", strerror(errno)); |
| 52 | return -1; | 52 | return -1; |
| 53 | } | 53 | } |
| 54 | 54 | ||
| @@ -56,37 +56,85 @@ int create_socket(void) { | |||
| 56 | bind_addr.sun_family = AF_UNIX; | 56 | bind_addr.sun_family = AF_UNIX; |
| 57 | strcpy(bind_addr.sun_path, socket_path); | 57 | strcpy(bind_addr.sun_path, socket_path); |
| 58 | if (bind(listenfd, (struct sockaddr*)&bind_addr, sizeof(bind_addr)) != 0) { | 58 | if (bind(listenfd, (struct sockaddr*)&bind_addr, sizeof(bind_addr)) != 0) { |
| 59 | usbmuxd_log(LOG_FATAL, "bind() failed: %s", strerror(errno)); | 59 | usbmuxd_log(LL_FATAL, "bind() failed: %s", strerror(errno)); |
| 60 | return -1; | 60 | return -1; |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | // Start listening | 63 | // Start listening |
| 64 | if (listen(listenfd, 5) != 0) { | 64 | if (listen(listenfd, 5) != 0) { |
| 65 | usbmuxd_log(LOG_FATAL, "listen() failed: %s", strerror(errno)); | 65 | usbmuxd_log(LL_FATAL, "listen() failed: %s", strerror(errno)); |
| 66 | return -1; | 66 | return -1; |
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | return listenfd; | 69 | return listenfd; |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | int main_loop(int listenfd) | ||
| 73 | { | ||
| 74 | int to, cnt, i; | ||
| 75 | struct fdlist pollfds; | ||
| 76 | |||
| 77 | while(1) { | ||
| 78 | usbmuxd_log(LL_SPEW, "main_loop iteration"); | ||
| 79 | to = usb_get_timeout(); | ||
| 80 | usbmuxd_log(LL_SPEW, "USB timeout is %d ms", to); | ||
| 81 | |||
| 82 | fdlist_create(&pollfds); | ||
| 83 | usb_get_fds(&pollfds); | ||
| 84 | usbmuxd_log(LL_SPEW, "fd count is %d", pollfds.count); | ||
| 85 | |||
| 86 | cnt = poll(pollfds.fds, pollfds.count, to); | ||
| 87 | usbmuxd_log(LL_SPEW, "poll() returned %d", cnt); | ||
| 88 | |||
| 89 | if(cnt == 0) { | ||
| 90 | if(usb_process() < 0) { | ||
| 91 | usbmuxd_log(LL_FATAL, "usb_process() failed"); | ||
| 92 | return -1; | ||
| 93 | } | ||
| 94 | } else { | ||
| 95 | for(i=0; i<pollfds.count; i++) { | ||
| 96 | if(pollfds.fds[i].revents) { | ||
| 97 | if(pollfds.owners[i] == FD_USB) { | ||
| 98 | if(usb_process() < 0) { | ||
| 99 | usbmuxd_log(LL_FATAL, "usb_process() failed"); | ||
| 100 | return -1; | ||
| 101 | } | ||
| 102 | } | ||
| 103 | } | ||
| 104 | } | ||
| 105 | } | ||
| 106 | fdlist_free(&pollfds); | ||
| 107 | } | ||
| 108 | } | ||
| 109 | |||
| 72 | int main(int argc, char *argv[]) | 110 | int main(int argc, char *argv[]) |
| 73 | { | 111 | { |
| 74 | int listenfd; | 112 | int listenfd; |
| 75 | int res; | 113 | int res; |
| 76 | 114 | ||
| 77 | usbmuxd_log(LOG_NOTICE, "usbmux v0.1 starting up"); | 115 | usbmuxd_log(LL_NOTICE, "usbmux v0.1 starting up"); |
| 78 | 116 | ||
| 79 | usbmuxd_log(LOG_INFO, "Creating socket"); | 117 | usbmuxd_log(LL_INFO, "Creating socket"); |
| 80 | listenfd = create_socket(); | 118 | listenfd = create_socket(); |
| 81 | if(listenfd < 0) | 119 | if(listenfd < 0) |
| 82 | return 1; | 120 | return 1; |
| 83 | 121 | ||
| 84 | usbmuxd_log(LOG_INFO, "Initializing USB"); | 122 | usbmuxd_log(LL_INFO, "Initializing USB"); |
| 85 | if((res = usb_init()) < 0) | 123 | if((res = usb_init()) < 0) |
| 86 | return 2; | 124 | return 2; |
| 87 | usbmuxd_log(LOG_INFO, "%d device%s detected", res, (res==1)?"":"s"); | 125 | usbmuxd_log(LL_INFO, "%d device%s detected", res, (res==1)?"":"s"); |
| 88 | 126 | ||
| 89 | usbmuxd_log(LOG_NOTICE, "initialization complete"); | 127 | usbmuxd_log(LL_NOTICE, "Initialization complete"); |
| 128 | |||
| 129 | res = main_loop(listenfd); | ||
| 130 | if(res < 0) | ||
| 131 | usbmuxd_log(LL_FATAL, "main_loop failed"); | ||
| 132 | |||
| 133 | usbmuxd_log(LL_NOTICE, "usbmux shutting down"); | ||
| 134 | usb_shutdown(); | ||
| 135 | usbmuxd_log(LL_NOTICE, "Shutdown complete"); | ||
| 90 | 136 | ||
| 137 | if(res < 0) | ||
| 138 | return -res; | ||
| 91 | return 0; | 139 | return 0; |
| 92 | } | 140 | } |
diff --git a/usb-linux.c b/usb-linux.c index 221ce33..0820ed9 100644 --- a/usb-linux.c +++ b/usb-linux.c | |||
| @@ -24,11 +24,258 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |||
| 24 | 24 | ||
| 25 | #include <stdio.h> | 25 | #include <stdio.h> |
| 26 | #include <stdlib.h> | 26 | #include <stdlib.h> |
| 27 | #include <stdlib.h> | 27 | #include <stdint.h> |
| 28 | #include <string.h> | ||
| 28 | 29 | ||
| 29 | #include <libusb.h> | 30 | #include <libusb.h> |
| 30 | 31 | ||
| 31 | int usb_init(void) | 32 | #include "usb.h" |
| 33 | #include "log.h" | ||
| 34 | #include "device.h" | ||
| 35 | |||
| 36 | // interval for device connection/disconnection polling, in milliseconds | ||
| 37 | // we need this because there is currently no asynchronous device discovery mechanism in libusb | ||
| 38 | #define DEVICE_POLL_TIME 1000 | ||
| 39 | |||
| 40 | struct usb_device { | ||
| 41 | libusb_device_handle *dev; | ||
| 42 | uint8_t bus, address; | ||
| 43 | char serial[256]; | ||
| 44 | int alive; | ||
| 45 | }; | ||
| 46 | |||
| 47 | int num_devs; | ||
| 48 | int device_id; | ||
| 49 | struct usb_device *device_list; | ||
| 50 | |||
| 51 | struct timeval next_dev_poll_time; | ||
| 52 | |||
| 53 | static int alloc_device(void) | ||
| 32 | { | 54 | { |
| 55 | int i; | ||
| 56 | for(i=0; i<num_devs; i++) { | ||
| 57 | if(!device_list[i].dev) | ||
| 58 | return i; | ||
| 59 | } | ||
| 60 | num_devs++; | ||
| 61 | device_list = realloc(device_list, sizeof(*device_list) * num_devs); | ||
| 62 | memset(&device_list[num_devs-1], 0, sizeof(*device_list)); | ||
| 63 | return num_devs - 1; | ||
| 64 | } | ||
| 65 | |||
| 66 | static void usb_disconnect(struct usb_device *dev) | ||
| 67 | { | ||
| 68 | if(!dev->dev) { | ||
| 69 | return; | ||
| 70 | } | ||
| 71 | libusb_release_interface(dev->dev, USB_INTERFACE); | ||
| 72 | libusb_close(dev->dev); | ||
| 73 | dev->dev = NULL; | ||
| 74 | } | ||
| 75 | |||
| 76 | static int usb_discover(void) | ||
| 77 | { | ||
| 78 | int cnt, i, j, res; | ||
| 79 | int valid_count = 0; | ||
| 80 | libusb_device **devs; | ||
| 81 | |||
| 82 | cnt = libusb_get_device_list(NULL, &devs); | ||
| 83 | if(cnt < 0) { | ||
| 84 | usbmuxd_log(LL_FATAL, "Could not get device list: %d", cnt); | ||
| 85 | return cnt; | ||
| 86 | } | ||
| 87 | |||
| 88 | usbmuxd_log(LL_SPEW, "usb_discover: scanning %d devices", cnt); | ||
| 89 | |||
| 90 | for(j=0; j<num_devs; j++) { | ||
| 91 | device_list[j].alive = 0; | ||
| 92 | } | ||
| 93 | for(i=0; i<cnt; i++) { | ||
| 94 | // the following are non-blocking operations on the device list | ||
| 95 | libusb_device *dev = devs[i]; | ||
| 96 | uint8_t bus = libusb_get_bus_number(dev); | ||
| 97 | uint8_t address = libusb_get_device_address(dev); | ||
| 98 | struct libusb_device_descriptor devdesc; | ||
| 99 | for(j=0; j<num_devs; j++) { | ||
| 100 | if(device_list[j].dev && device_list[j].bus == bus && device_list[j].address == address) { | ||
| 101 | valid_count++; | ||
| 102 | device_list[j].alive = 1; | ||
| 103 | break; | ||
| 104 | } | ||
| 105 | } | ||
| 106 | if(j < num_devs) | ||
| 107 | continue; //device already found | ||
| 108 | if((res = libusb_get_device_descriptor(dev, &devdesc)) != 0) { | ||
| 109 | usbmuxd_log(LL_WARNING, "Could not get device descriptor for device %d-%d: %d", bus, address, res); | ||
| 110 | continue; | ||
| 111 | } | ||
| 112 | if(devdesc.idVendor != VID_APPLE) | ||
| 113 | continue; | ||
| 114 | if( (devdesc.idProduct != PID_IPHONE2G) && | ||
| 115 | (devdesc.idProduct != PID_ITOUCH1G) && | ||
| 116 | (devdesc.idProduct != PID_IPHONE3G)) | ||
| 117 | continue; | ||
| 118 | libusb_device_handle *handle; | ||
| 119 | usbmuxd_log(LL_INFO, "Found new device with v/p %04x:%04x at %d-%d", devdesc.idVendor, devdesc.idProduct, bus, address); | ||
| 120 | // potentially blocking operations follow; they will only run when new devices are detected, which is acceptable | ||
| 121 | if((res = libusb_open(dev, &handle)) != 0) { | ||
| 122 | usbmuxd_log(LL_WARNING, "Could not open device %d-%d: %d", bus, address, res); | ||
| 123 | continue; | ||
| 124 | } | ||
| 125 | if((res = libusb_set_configuration(handle, USB_CONFIGURATION)) != 0) { | ||
| 126 | usbmuxd_log(LL_WARNING, "Could not set configuration %d for device %d-%d: %d", USB_CONFIGURATION, bus, address, res); | ||
| 127 | libusb_close(handle); | ||
| 128 | continue; | ||
| 129 | } | ||
| 130 | if((res = libusb_claim_interface(handle, USB_INTERFACE)) != 0) { | ||
| 131 | usbmuxd_log(LL_WARNING, "Could not claim interface %d for device %d-%d: %d", USB_INTERFACE, bus, address, res); | ||
| 132 | libusb_close(handle); | ||
| 133 | continue; | ||
| 134 | } | ||
| 135 | int idx = alloc_device(); | ||
| 136 | |||
| 137 | if((res = libusb_get_string_descriptor_ascii(handle, devdesc.iSerialNumber, (uint8_t *)device_list[idx].serial, 256)) <= 0) { | ||
| 138 | usbmuxd_log(LL_WARNING, "Could not get serial number for device %d-%d: %d", USB_INTERFACE, bus, address, res); | ||
| 139 | libusb_close(handle); | ||
| 140 | continue; | ||
| 141 | } | ||
| 142 | device_list[idx].serial[res] = 0; | ||
| 143 | device_list[idx].bus = bus; | ||
| 144 | device_list[idx].address = address; | ||
| 145 | device_list[idx].dev = handle; | ||
| 146 | device_list[idx].alive = 1; | ||
| 147 | |||
| 148 | device_add(&device_list[idx]); | ||
| 149 | valid_count++; | ||
| 150 | } | ||
| 151 | for(j=0; j<num_devs; j++) { | ||
| 152 | if(device_list[j].dev && !device_list[j].alive) { | ||
| 153 | device_remove(&device_list[j]); | ||
| 154 | usb_disconnect(&device_list[j]); | ||
| 155 | } | ||
| 156 | } | ||
| 157 | libusb_free_device_list(devs, 1); | ||
| 158 | |||
| 159 | gettimeofday(&next_dev_poll_time, NULL); | ||
| 160 | next_dev_poll_time.tv_usec += DEVICE_POLL_TIME * 1000; | ||
| 161 | next_dev_poll_time.tv_sec += next_dev_poll_time.tv_usec / 1000000; | ||
| 162 | next_dev_poll_time.tv_usec = next_dev_poll_time.tv_usec % 1000000; | ||
| 163 | |||
| 164 | return valid_count; | ||
| 165 | } | ||
| 166 | |||
| 167 | const char *usb_get_serial(struct usb_device *dev) | ||
| 168 | { | ||
| 169 | if(!dev->dev) { | ||
| 170 | return NULL; | ||
| 171 | } | ||
| 172 | return dev->serial; | ||
| 173 | } | ||
| 174 | |||
| 175 | int usb_get_location(struct usb_device *dev) | ||
| 176 | { | ||
| 177 | if(!dev->dev) { | ||
| 178 | return 0; | ||
| 179 | } | ||
| 180 | return (dev->bus << 16) | dev->address; | ||
| 181 | } | ||
| 182 | |||
| 183 | void usb_get_fds(struct fdlist *list) | ||
| 184 | { | ||
| 185 | const struct libusb_pollfd **usbfds; | ||
| 186 | const struct libusb_pollfd **p; | ||
| 187 | usbfds = libusb_get_pollfds(NULL); | ||
| 188 | if(!usbfds) { | ||
| 189 | usbmuxd_log(LL_ERROR, "libusb_get_pollfds failed"); | ||
| 190 | return; | ||
| 191 | } | ||
| 192 | p = usbfds; | ||
| 193 | while(*p) { | ||
| 194 | fdlist_add(list, FD_USB, (*p)->fd, (*p)->events); | ||
| 195 | p++; | ||
| 196 | } | ||
| 197 | free(usbfds); | ||
| 198 | } | ||
| 199 | |||
| 200 | static int dev_poll_remain_ms(void) | ||
| 201 | { | ||
| 202 | int msecs; | ||
| 203 | struct timeval tv; | ||
| 204 | gettimeofday(&tv, NULL); | ||
| 205 | msecs = (next_dev_poll_time.tv_sec - tv.tv_sec) * 1000; | ||
| 206 | msecs += (next_dev_poll_time.tv_usec - tv.tv_usec) / 1000; | ||
| 207 | if(msecs < 0) | ||
| 208 | return 0; | ||
| 209 | return msecs; | ||
| 210 | } | ||
| 211 | |||
| 212 | int usb_get_timeout(void) | ||
| 213 | { | ||
| 214 | struct timeval tv; | ||
| 215 | int msec; | ||
| 216 | int res; | ||
| 217 | int pollrem; | ||
| 218 | pollrem = dev_poll_remain_ms(); | ||
| 219 | res = libusb_get_next_timeout(NULL, &tv); | ||
| 220 | if(res == 0) | ||
| 221 | return pollrem; | ||
| 222 | if(res < 0) { | ||
| 223 | usbmuxd_log(LL_ERROR, "libusb_get_next_timeout failed: %d", res); | ||
| 224 | return pollrem; | ||
| 225 | } | ||
| 226 | msec = tv.tv_sec * 1000; | ||
| 227 | msec += tv.tv_usec / 1000; | ||
| 228 | if(msec > pollrem) | ||
| 229 | return pollrem; | ||
| 230 | return msec; | ||
| 231 | } | ||
| 232 | |||
| 233 | int usb_process(void) | ||
| 234 | { | ||
| 235 | int res; | ||
| 236 | struct timeval tv; | ||
| 237 | tv.tv_sec = tv.tv_usec = 0; | ||
| 238 | res = libusb_handle_events_timeout(NULL, &tv); | ||
| 239 | if(res < 0) { | ||
| 240 | usbmuxd_log(LL_ERROR, "libusb_handle_events_timeout failed: %d", res); | ||
| 241 | return res; | ||
| 242 | } | ||
| 243 | if(dev_poll_remain_ms() <= 0) { | ||
| 244 | res = usb_discover(); | ||
| 245 | if(res < 0) { | ||
| 246 | usbmuxd_log(LL_ERROR, "usb_discover failed: %d", res); | ||
| 247 | return res; | ||
| 248 | } | ||
| 249 | } | ||
| 33 | return 0; | 250 | return 0; |
| 34 | } | 251 | } |
| 252 | |||
| 253 | int usb_init(void) | ||
| 254 | { | ||
| 255 | int res; | ||
| 256 | usbmuxd_log(LL_DEBUG, "usb_init for linux / libusb 1.0"); | ||
| 257 | |||
| 258 | res = libusb_init(NULL); | ||
| 259 | if(res != 0) { | ||
| 260 | usbmuxd_log(LL_FATAL, "libusb_init failed: %d", res); | ||
| 261 | return -1; | ||
| 262 | } | ||
| 263 | |||
| 264 | device_id = 1; | ||
| 265 | num_devs = 1; | ||
| 266 | device_list = malloc(sizeof(*device_list) * num_devs); | ||
| 267 | memset(device_list, 0, sizeof(*device_list) * num_devs); | ||
| 268 | |||
| 269 | return usb_discover(); | ||
| 270 | } | ||
| 271 | |||
| 272 | void usb_shutdown(void) | ||
| 273 | { | ||
| 274 | int i; | ||
| 275 | usbmuxd_log(LL_DEBUG, "usb_shutdown"); | ||
| 276 | for(i=0; i<num_devs; i++) | ||
| 277 | usb_disconnect(&device_list[i]); | ||
| 278 | free(device_list); | ||
| 279 | device_list = NULL; | ||
| 280 | libusb_exit(NULL); | ||
| 281 | } | ||
| @@ -21,9 +21,27 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |||
| 21 | #ifndef __USB_H__ | 21 | #ifndef __USB_H__ |
| 22 | #define __USB_H__ | 22 | #define __USB_H__ |
| 23 | 23 | ||
| 24 | #include "utils.h" | ||
| 25 | |||
| 24 | #define BULK_IN 0x85 | 26 | #define BULK_IN 0x85 |
| 25 | #define BULK_OUT 0x04 | 27 | #define BULK_OUT 0x04 |
| 26 | 28 | ||
| 29 | #define VID_APPLE 0x5ac | ||
| 30 | #define PID_IPHONE2G 0x1290 | ||
| 31 | #define PID_ITOUCH1G 0x1291 | ||
| 32 | #define PID_IPHONE3G 0x1292 | ||
| 33 | |||
| 34 | #define USB_CONFIGURATION 3 | ||
| 35 | #define USB_INTERFACE 1 | ||
| 36 | |||
| 37 | struct usb_device; | ||
| 38 | |||
| 27 | int usb_init(void); | 39 | int usb_init(void); |
| 40 | void usb_shutdown(void); | ||
| 41 | const char *usb_get_serial(struct usb_device *dev); | ||
| 42 | int usb_get_location(struct usb_device *dev); | ||
| 43 | void usb_get_fds(struct fdlist *list); | ||
| 44 | int usb_get_timeout(void); | ||
| 45 | int usb_process(void); | ||
| 28 | 46 | ||
| 29 | #endif | 47 | #endif |
| @@ -25,14 +25,14 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |||
| 25 | #include <stdlib.h> | 25 | #include <stdlib.h> |
| 26 | #include "utils.h" | 26 | #include "utils.h" |
| 27 | 27 | ||
| 28 | void fdlist_create(fdlist *list) | 28 | void fdlist_create(struct fdlist *list) |
| 29 | { | 29 | { |
| 30 | list->count = 0; | 30 | list->count = 0; |
| 31 | list->capacity = 4; | 31 | list->capacity = 4; |
| 32 | list->owners = malloc(sizeof(*list->owners) * list->capacity); | 32 | list->owners = malloc(sizeof(*list->owners) * list->capacity); |
| 33 | list->fds = malloc(sizeof(*list->fds) * list->capacity); | 33 | list->fds = malloc(sizeof(*list->fds) * list->capacity); |
| 34 | } | 34 | } |
| 35 | void fdlist_add(fdlist *list, enum fdowner owner, int fd, short events) | 35 | void fdlist_add(struct fdlist *list, enum fdowner owner, int fd, short events) |
| 36 | { | 36 | { |
| 37 | if(list->count == list->capacity) { | 37 | if(list->count == list->capacity) { |
| 38 | list->capacity *= 2; | 38 | list->capacity *= 2; |
| @@ -46,7 +46,7 @@ void fdlist_add(fdlist *list, enum fdowner owner, int fd, short events) | |||
| 46 | list->count++; | 46 | list->count++; |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | void fdlist_free(fdlist *list) | 49 | void fdlist_free(struct fdlist *list) |
| 50 | { | 50 | { |
| 51 | list->count = 0; | 51 | list->count = 0; |
| 52 | list->capacity = 0; | 52 | list->capacity = 0; |
| @@ -18,8 +18,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |||
| 18 | 18 | ||
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | #ifndef __LOG_H__ | 21 | #ifndef __UTILS_H__ |
| 22 | #define __LOG_H__ | 22 | #define __UTILS_H__ |
| 23 | 23 | ||
| 24 | #include <poll.h> | 24 | #include <poll.h> |
| 25 | 25 | ||
| @@ -29,19 +29,17 @@ enum fdowner { | |||
| 29 | FD_USB | 29 | FD_USB |
| 30 | }; | 30 | }; |
| 31 | 31 | ||
| 32 | typedef struct { | 32 | struct fdlist { |
| 33 | int count; | 33 | int count; |
| 34 | int capacity; | 34 | int capacity; |
| 35 | enum fdowner *owners; | 35 | enum fdowner *owners; |
| 36 | struct pollfd *fds; | 36 | struct pollfd *fds; |
| 37 | } fdlist; | 37 | }; |
| 38 | 38 | ||
| 39 | void fdlist_create(fdlist *list); | 39 | void fdlist_create(struct fdlist *list); |
| 40 | void fdlist_add(fdlist *list, enum fdowner owner, int fd, short events); | 40 | void fdlist_add(struct fdlist *list, enum fdowner owner, int fd, short events); |
| 41 | void fdlist_free(fdlist *list); | 41 | void fdlist_free(struct fdlist *list); |
| 42 | 42 | ||
| 43 | #define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) | 43 | #define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) |
| 44 | 44 | ||
| 45 | |||
| 46 | |||
| 47 | #endif | 45 | #endif |
