summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Hector Martin2009-04-28 19:01:12 +0200
committerGravatar Hector Martin2009-04-28 19:01:12 +0200
commit53fb582e7729d5b7ed40ff04d912fcf5add7ce1c (patch)
tree8dd1f4d5426421a3a84a9d5df43f2fba48d12143
parentc2d46d901822c54a0677318522db62f30b8d5f04 (diff)
downloadusbmuxd-53fb582e7729d5b7ed40ff04d912fcf5add7ce1c.tar.gz
usbmuxd-53fb582e7729d5b7ed40ff04d912fcf5add7ce1c.tar.bz2
USB TX/RX, device framework, version packets
-rw-r--r--client.c1
-rw-r--r--client.h7
-rw-r--r--device.c225
-rw-r--r--device.h6
-rw-r--r--log.h4
-rw-r--r--main.c15
-rw-r--r--usb-linux.c152
-rw-r--r--usb.h3
8 files changed, 384 insertions, 29 deletions
diff --git a/client.c b/client.c
index c56f8f4..f0868fb 100644
--- a/client.c
+++ b/client.c
@@ -24,4 +24,5 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 24
25#include "log.h" 25#include "log.h"
26#include "usb.h" 26#include "usb.h"
27#include "client.h"
27 28
diff --git a/client.h b/client.h
index d6f61af..2bb3920 100644
--- a/client.h
+++ b/client.h
@@ -18,7 +18,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 18
19*/ 19*/
20 20
21#ifndef __MUX_H__ 21#ifndef __CLIENT_H__
22#define __MUX_H__ 22#define __CLIENT_H__
23 23
24#endif 24#endif
25
26void client_accept(int fd);
27void client_get_fds(struct fdlist *list);
diff --git a/device.c b/device.c
index 659f4ae..79ec00c 100644
--- a/device.c
+++ b/device.c
@@ -18,39 +18,242 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 18
19*/ 19*/
20 20
21#define _BSD_SOURCE
22
21#ifdef HAVE_CONFIG_H 23#ifdef HAVE_CONFIG_H
22#include <config.h> 24#include <config.h>
23#endif 25#endif
24 26
27#include <netinet/in.h>
28#include <netinet/tcp.h>
25#include <stdlib.h> 29#include <stdlib.h>
30#include <string.h>
26#include "device.h" 31#include "device.h"
27#include "usb.h" 32#include "usb.h"
28#include "log.h" 33#include "log.h"
29 34
30int device_id; 35int next_device_id;
31/* 36
32int get_next_device_id(void) 37enum mux_protocol {
38 MUX_PROTO_VERSION = 0,
39 MUX_PROTO_TCP = IPPROTO_TCP,
40};
41
42enum mux_dev_state {
43 MUXDEV_INIT,
44 MUXDEV_ACTIVE,
45 MUXDEV_DEAD
46};
47
48struct mux_header
49{
50 uint32_t protocol;
51 uint32_t length;
52};
53
54struct version_header
55{
56 uint32_t major;
57 uint32_t minor;
58 uint32_t padding;
59};
60
61struct mux_device
62{
63 struct usb_device *usbdev;
64 int id;
65 enum mux_dev_state state;
66};
67
68static int num_devs;
69static struct mux_device *device_list;
70
71static int alloc_device(void)
72{
73 int i;
74 for(i=0; i<num_devs; i++) {
75 if(!device_list[i].usbdev)
76 return i;
77 }
78 num_devs++;
79 device_list = realloc(device_list, sizeof(*device_list) * num_devs);
80 memset(&device_list[num_devs-1], 0, sizeof(*device_list));
81 return num_devs - 1;
82}
83
84static int get_next_device_id(void)
33{ 85{
34 int i; 86 int i;
35 while(1) { 87 while(1) {
36 for(i=0; i<num_devs; i++) { 88 for(i=0; i<num_devs; i++) {
37 if(device_list[i].dev && device_list[i].id == device_id) { 89 if(device_list[i].usbdev && device_list[i].id == next_device_id) {
38 device_id++; 90 next_device_id++;
39 break; 91 break;
40 } 92 }
41 } 93 }
42 if(i < num_devs) 94 if(i >= num_devs)
95 return next_device_id++;
96 }
97}
98
99int send_packet(struct mux_device *dev, enum mux_protocol proto, void *header, void *data, int length)
100{
101 unsigned char *buffer;
102 int hdrlen;
103 int res;
104
105 switch(proto) {
106 case MUX_PROTO_VERSION:
107 hdrlen = sizeof(struct version_header);
43 break; 108 break;
109 case MUX_PROTO_TCP:
110 hdrlen = sizeof(struct tcphdr);
111 break;
112 default:
113 usbmuxd_log(LL_ERROR, "Invalid protocol %d for outgoing packet (dev %d hdr %p data %p len %d)", proto, dev->id, header, data, length);
114 return -1;
115 }
116 usbmuxd_log(LL_SPEW, "send_packet(%d, 0x%x, %p, %p, %d)", dev->id, proto, header, data, length);
117
118 int total = sizeof(struct mux_header) + hdrlen + length;
119
120 if(total > USB_MTU) {
121 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);
122 return -1;
44 } 123 }
45 return device_id++; 124
125 buffer = malloc(total);
126 struct mux_header *mhdr = (struct mux_header *)buffer;
127 mhdr->protocol = htonl(proto);
128 mhdr->length = htonl(total);;
129 memcpy(buffer + sizeof(struct mux_header), header, hdrlen);
130 if(data && length)
131 memcpy(buffer + sizeof(struct mux_header) + hdrlen, data, length);
132
133 if((res = usb_send(dev->usbdev, buffer, total)) < 0) {
134 usbmuxd_log(LL_ERROR, "usb_send failed while sending packet (len %d) to device %d: %d", total, dev->id, res);
135 free(buffer);
136 return res;
137 }
138 return mhdr->length;
46} 139}
47*/ 140
48void device_add(struct usb_device *dev) 141static void device_version_input(struct mux_device *dev, struct version_header *vh)
142{
143 if(dev->state != MUXDEV_INIT) {
144 usbmuxd_log(LL_WARNING, "Version packet from already initialized device %d", dev->id);
145 return;
146 }
147 vh->major = ntohl(vh->major);
148 vh->minor = ntohl(vh->minor);
149 if(vh->major != 1 || vh->minor != 0) {
150 usbmuxd_log(LL_ERROR, "Device %d has unknown version %d.%d\n", dev->id, vh->major, vh->minor);
151 return;
152 }
153 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));
154}
155
156static void device_tcp_input(struct mux_device *dev, struct tcphdr *th, unsigned char *payload, int payload_length)
157{
158
159}
160
161
162void device_data_input(struct usb_device *usbdev, unsigned char *buffer, int length)
163{
164 int i;
165 struct mux_device *dev;
166 for(i=0; i<num_devs; i++) {
167 if(device_list[i].usbdev == usbdev) {
168 dev = &device_list[i];
169 break;
170 }
171 }
172 if(i >= num_devs) {
173 usbmuxd_log(LL_WARNING, "Cannot find device entry for RX input from USB device %p on location 0x%x", usbdev, usb_get_location(usbdev));
174 return;
175 }
176
177 usbmuxd_log(LL_SPEW, "Mux data input for device %p: %p len %d", dev, buffer, length);
178
179 struct mux_header *mhdr = (struct mux_header *)buffer;
180
181 if(ntohl(mhdr->length) != length) {
182 usbmuxd_log(LL_ERROR, "Incoming packet size mismatch (dev %d, expected %d, got %d)", dev->id, ntohl(mhdr->length), length);
183 return;
184 }
185
186 struct tcphdr *th;
187 unsigned char *payload;
188 int payload_length;
189
190 switch(ntohl(mhdr->protocol)) {
191 case MUX_PROTO_VERSION:
192 device_version_input(dev, (struct version_header *)(mhdr+1));
193 break;
194 case MUX_PROTO_TCP:
195 th = (struct tcphdr *)(mhdr+1);
196 payload = (unsigned char *)(th+1);
197 payload_length = length - sizeof(struct tcphdr) - sizeof(struct mux_header);
198 device_tcp_input(dev, (struct tcphdr *)(mhdr+1), payload, payload_length);
199 break;
200 default:
201 usbmuxd_log(LL_ERROR, "Incoming packet for device %d has unknown protocol 0x%x)", dev->id, ntohl(mhdr->protocol));
202 break;
203 }
204
205}
206
207int device_add(struct usb_device *dev)
49{ 208{
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)); 209 int res;
210 int id = get_next_device_id();
211 int idx = alloc_device();
212 usbmuxd_log(LL_NOTICE, "Connecting to new device on location 0x%x as ID %d", usb_get_location(dev), id);
213 device_list[idx].id = id;
214 device_list[idx].usbdev = dev;
215 device_list[idx].state = MUXDEV_INIT;
216 struct version_header vh;
217 vh.major = htonl(1);
218 vh.minor = htonl(0);
219 vh.padding = 0;
220 if((res = send_packet(&device_list[idx], MUX_PROTO_VERSION, &vh, NULL, 0)) < 0) {
221 usbmuxd_log(LL_ERROR, "Error sending version request packet to device %d\n", id);
222 device_list[idx].usbdev = NULL;
223 device_list[idx].state = MUXDEV_DEAD;
224 return res;
225 }
226 return 0;
51} 227}
52 228
53void device_remove(struct usb_device *dev) 229void device_remove(struct usb_device *dev)
54{ 230{
55 usbmuxd_log(LL_NOTICE, "Removed device on location 0x%x with serial number %s", usb_get_location(dev), usb_get_serial(dev)); 231 int i;
232 for(i=0; i<num_devs; i++) {
233 if(device_list[i].usbdev == dev) {
234 usbmuxd_log(LL_NOTICE, "Removed device %d on location 0x%x", device_list[i].id, usb_get_location(dev));
235 device_list[i].usbdev = NULL;
236 return;
237 }
238 }
239 usbmuxd_log(LL_WARNING, "Cannot find device entry while removing USB device %p on location 0x%x", dev, usb_get_location(dev));
240}
241
242void device_init(void)
243{
244 usbmuxd_log(LL_DEBUG, "device_init");
245 num_devs = 1;
246 device_list = malloc(sizeof(*device_list) * num_devs);
247 memset(device_list, 0, sizeof(*device_list) * num_devs);
248 next_device_id = 1;
249}
250
251void device_shutdown(void)
252{
253 int i;
254 usbmuxd_log(LL_DEBUG, "device_shutdown");
255 for(i=0; i<num_devs; i++)
256 device_remove(device_list[i].usbdev);
257 free(device_list);
258 device_list = NULL;
56} 259}
diff --git a/device.h b/device.h
index 11beaea..878688c 100644
--- a/device.h
+++ b/device.h
@@ -23,7 +23,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 23
24#include "usb.h" 24#include "usb.h"
25 25
26void device_add(struct usb_device *dev); 26void device_data_input(struct usb_device *dev, unsigned char *buf, int length);
27
28int device_add(struct usb_device *dev);
27void device_remove(struct usb_device *dev); 29void device_remove(struct usb_device *dev);
28 30
31void device_init(void);
32void device_shutdown(void);
29#endif 33#endif
diff --git a/log.h b/log.h
index 56ecbf4..f6eb5c1 100644
--- a/log.h
+++ b/log.h
@@ -29,10 +29,12 @@ enum loglevel {
29 LL_INFO, 29 LL_INFO,
30 LL_DEBUG, 30 LL_DEBUG,
31 LL_SPEW, 31 LL_SPEW,
32 LL_FLOOD,
32}; 33};
33 34
34extern int log_level; 35extern int log_level;
35 36
36void usbmuxd_log(enum loglevel level, const char *fmt, ...); 37void usbmuxd_log(enum loglevel level, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
38
37 39
38#endif 40#endif
diff --git a/main.c b/main.c
index bc846cc..7bc8dbe 100644
--- a/main.c
+++ b/main.c
@@ -34,8 +34,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
34 34
35#include "log.h" 35#include "log.h"
36#include "usb.h" 36#include "usb.h"
37#include "device.h"
37 38
38const char *socket_path = "/tmp/usbmuxd"; //TODO: CHANGEME 39static const char *socket_path = "/tmp/usbmuxd"; //TODO: CHANGEME
39 40
40int create_socket(void) { 41int create_socket(void) {
41 struct sockaddr_un bind_addr; 42 struct sockaddr_un bind_addr;
@@ -75,17 +76,17 @@ int main_loop(int listenfd)
75 struct fdlist pollfds; 76 struct fdlist pollfds;
76 77
77 while(1) { 78 while(1) {
78 usbmuxd_log(LL_SPEW, "main_loop iteration"); 79 usbmuxd_log(LL_FLOOD, "main_loop iteration");
79 to = usb_get_timeout(); 80 to = usb_get_timeout();
80 usbmuxd_log(LL_SPEW, "USB timeout is %d ms", to); 81 usbmuxd_log(LL_FLOOD, "USB timeout is %d ms", to);
81 82
82 fdlist_create(&pollfds); 83 fdlist_create(&pollfds);
83 fdlist_add(&pollfds, FD_LISTEN, listenfd, POLLIN); 84 fdlist_add(&pollfds, FD_LISTEN, listenfd, POLLIN);
84 usb_get_fds(&pollfds); 85 usb_get_fds(&pollfds);
85 usbmuxd_log(LL_SPEW, "fd count is %d", pollfds.count); 86 usbmuxd_log(LL_FLOOD, "fd count is %d", pollfds.count);
86 87
87 cnt = poll(pollfds.fds, pollfds.count, to); 88 cnt = poll(pollfds.fds, pollfds.count, to);
88 usbmuxd_log(LL_SPEW, "poll() returned %d", cnt); 89 usbmuxd_log(LL_FLOOD, "poll() returned %d", cnt);
89 90
90 if(cnt == 0) { 91 if(cnt == 0) {
91 if(usb_process() < 0) { 92 if(usb_process() < 0) {
@@ -122,6 +123,7 @@ int main(int argc, char *argv[])
122 if(listenfd < 0) 123 if(listenfd < 0)
123 return 1; 124 return 1;
124 125
126 device_init();
125 usbmuxd_log(LL_INFO, "Initializing USB"); 127 usbmuxd_log(LL_INFO, "Initializing USB");
126 if((res = usb_init()) < 0) 128 if((res = usb_init()) < 0)
127 return 2; 129 return 2;
@@ -135,8 +137,9 @@ int main(int argc, char *argv[])
135 137
136 usbmuxd_log(LL_NOTICE, "usbmux shutting down"); 138 usbmuxd_log(LL_NOTICE, "usbmux shutting down");
137 usb_shutdown(); 139 usb_shutdown();
140 device_shutdown();
138 usbmuxd_log(LL_NOTICE, "Shutdown complete"); 141 usbmuxd_log(LL_NOTICE, "Shutdown complete");
139 142
140 if(res < 0) 143 if(res < 0)
141 return -res; 144 return -res;
142 return 0; 145 return 0;
diff --git a/usb-linux.c b/usb-linux.c
index 0820ed9..27a7bb1 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -42,13 +42,13 @@ struct usb_device {
42 uint8_t bus, address; 42 uint8_t bus, address;
43 char serial[256]; 43 char serial[256];
44 int alive; 44 int alive;
45 struct libusb_transfer *rx_xfer;
45}; 46};
46 47
47int num_devs; 48static int num_devs;
48int device_id; 49static struct usb_device *device_list;
49struct usb_device *device_list;
50 50
51struct timeval next_dev_poll_time; 51static struct timeval next_dev_poll_time;
52 52
53static int alloc_device(void) 53static int alloc_device(void)
54{ 54{
@@ -68,11 +68,130 @@ static void usb_disconnect(struct usb_device *dev)
68 if(!dev->dev) { 68 if(!dev->dev) {
69 return; 69 return;
70 } 70 }
71 if(dev->rx_xfer) {
72 // kill the rx xfer and try to make sure the rx callback gets called before we free the device
73 struct timeval tv;
74 int res;
75 // TODO: BUG: outstanding TX xfers are not listed but we need to free them
76 libusb_cancel_transfer(dev->rx_xfer);
77 tv.tv_sec = tv.tv_usec = 0;
78 if((res = libusb_handle_events_timeout(NULL, &tv)) < 0) {
79 usbmuxd_log(LL_ERROR, "libusb_handle_events_timeout for device removal failed: %d", res);
80 }
81 }
71 libusb_release_interface(dev->dev, USB_INTERFACE); 82 libusb_release_interface(dev->dev, USB_INTERFACE);
72 libusb_close(dev->dev); 83 libusb_close(dev->dev);
73 dev->dev = NULL; 84 dev->dev = NULL;
74} 85}
75 86
87static void tx_callback(struct libusb_transfer *xfer)
88{
89 struct usb_device *dev = xfer->user_data;
90 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);
91 if(xfer->status != LIBUSB_TRANSFER_COMPLETED) {
92 switch(xfer->status) {
93 case LIBUSB_TRANSFER_COMPLETED: //shut up compiler
94 case LIBUSB_TRANSFER_ERROR:
95 // funny, this happens when we disconnect the device while waiting for a transfer, sometimes
96 usbmuxd_log(LL_INFO, "Device %d-%d TX aborted due to error or disconnect", dev->bus, dev->address);
97 break;
98 case LIBUSB_TRANSFER_TIMED_OUT:
99 usbmuxd_log(LL_ERROR, "TX transfer timed out for device %d-%d", dev->bus, dev->address);
100 break;
101 case LIBUSB_TRANSFER_CANCELLED:
102 usbmuxd_log(LL_ERROR, "TX transfer cancelled for device %d-%d", dev->bus, dev->address);
103 break;
104 case LIBUSB_TRANSFER_STALL:
105 usbmuxd_log(LL_ERROR, "TX transfer stalled for device %d-%d", dev->bus, dev->address);
106 break;
107 case LIBUSB_TRANSFER_NO_DEVICE:
108 // other times, this happens, and also even when we abort the transfer after device removal
109 usbmuxd_log(LL_INFO, "Device %d-%d TX aborted due to disconnect", dev->bus, dev->address);
110 break;
111 case LIBUSB_TRANSFER_OVERFLOW:
112 usbmuxd_log(LL_ERROR, "TX transfer overflow for device %d-%d", dev->bus, dev->address);
113 break;
114 // and nothing happens (this never gets called) if the device is freed after a disconnect! (bad)
115 }
116 // we can't usb_disconnect here due to a deadlock, so instead mark it as dead and reap it after processing events
117 // we'll do device_remove there too
118 dev->alive = 0;
119 }
120 free(xfer->buffer);
121 libusb_free_transfer(xfer);
122}
123
124int usb_send(struct usb_device *dev, const unsigned char *buf, int length)
125{
126 int res;
127 struct libusb_transfer *xfer = libusb_alloc_transfer(0);
128 libusb_fill_bulk_transfer(xfer, dev->dev, BULK_OUT, (void*)buf, length, tx_callback, dev, 0);
129 xfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK;
130 if((res = libusb_submit_transfer(xfer)) < 0) {
131 usbmuxd_log(LL_ERROR, "Failed to submit TX transfer %p len %d to device %d-%d: %d", buf, length, dev->bus, dev->address, res);
132 libusb_free_transfer(xfer);
133 return res;
134 }
135 return 0;
136}
137
138static void rx_callback(struct libusb_transfer *xfer)
139{
140 struct usb_device *dev = xfer->user_data;
141 usbmuxd_log(LL_SPEW, "RX callback dev %d-%d len %d status %d", dev->bus, dev->address, xfer->actual_length, xfer->status);
142 if(xfer->status == LIBUSB_TRANSFER_COMPLETED) {
143 device_data_input(dev, xfer->buffer, xfer->actual_length);
144 libusb_submit_transfer(xfer);
145 } else {
146 switch(xfer->status) {
147 case LIBUSB_TRANSFER_COMPLETED: //shut up compiler
148 case LIBUSB_TRANSFER_ERROR:
149 // funny, this happens when we disconnect the device while waiting for a transfer, sometimes
150 usbmuxd_log(LL_INFO, "Device %d-%d RX aborted due to error or disconnect", dev->bus, dev->address);
151 break;
152 case LIBUSB_TRANSFER_TIMED_OUT:
153 usbmuxd_log(LL_ERROR, "RX transfer timed out for device %d-%d", dev->bus, dev->address);
154 break;
155 case LIBUSB_TRANSFER_CANCELLED:
156 usbmuxd_log(LL_ERROR, "RX transfer cancelled for device %d-%d", dev->bus, dev->address);
157 break;
158 case LIBUSB_TRANSFER_STALL:
159 usbmuxd_log(LL_ERROR, "RX transfer stalled for device %d-%d", dev->bus, dev->address);
160 break;
161 case LIBUSB_TRANSFER_NO_DEVICE:
162 // other times, this happens, and also even when we abort the transfer after device removal
163 usbmuxd_log(LL_INFO, "Device %d-%d RX aborted due to disconnect", dev->bus, dev->address);
164 break;
165 case LIBUSB_TRANSFER_OVERFLOW:
166 usbmuxd_log(LL_ERROR, "RX transfer overflow for device %d-%d", dev->bus, dev->address);
167 break;
168 // and nothing happens (this never gets called) if the device is freed after a disconnect! (bad)
169 }
170 free(xfer->buffer);
171 dev->rx_xfer = NULL;
172 libusb_free_transfer(xfer);
173 // we can't usb_disconnect here due to a deadlock, so instead mark it as dead and reap it after processing events
174 // we'll do device_remove there too
175 dev->alive = 0;
176 }
177}
178
179static int start_rx(struct usb_device *dev)
180{
181 int res;
182 void *buf;
183 dev->rx_xfer = libusb_alloc_transfer(0);
184 buf = malloc(USB_MTU);
185 libusb_fill_bulk_transfer(dev->rx_xfer, dev->dev, BULK_IN, buf, USB_MTU, rx_callback, dev, 0);
186 if((res = libusb_submit_transfer(dev->rx_xfer)) != 0) {
187 usbmuxd_log(LL_ERROR, "Failed to submit RX transfer to device %d-%d: %d", dev->bus, dev->address, res);
188 libusb_free_transfer(dev->rx_xfer);
189 dev->rx_xfer = NULL;
190 return res;
191 }
192 return 0;
193}
194
76static int usb_discover(void) 195static int usb_discover(void)
77{ 196{
78 int cnt, i, j, res; 197 int cnt, i, j, res;
@@ -135,7 +254,8 @@ static int usb_discover(void)
135 int idx = alloc_device(); 254 int idx = alloc_device();
136 255
137 if((res = libusb_get_string_descriptor_ascii(handle, devdesc.iSerialNumber, (uint8_t *)device_list[idx].serial, 256)) <= 0) { 256 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); 257 usbmuxd_log(LL_WARNING, "Could not get serial number for device %d-%d: %d", bus, address, res);
258 libusb_release_interface(handle, USB_INTERFACE);
139 libusb_close(handle); 259 libusb_close(handle);
140 continue; 260 continue;
141 } 261 }
@@ -145,7 +265,15 @@ static int usb_discover(void)
145 device_list[idx].dev = handle; 265 device_list[idx].dev = handle;
146 device_list[idx].alive = 1; 266 device_list[idx].alive = 1;
147 267
148 device_add(&device_list[idx]); 268 if(device_add(&device_list[idx]) < 0) {
269 usb_disconnect(&device_list[j]);
270 continue;
271 }
272 if(start_rx(&device_list[idx]) < 0) {
273 device_remove(&device_list[j]);
274 usb_disconnect(&device_list[j]);
275 continue;
276 }
149 valid_count++; 277 valid_count++;
150 } 278 }
151 for(j=0; j<num_devs; j++) { 279 for(j=0; j<num_devs; j++) {
@@ -232,7 +360,7 @@ int usb_get_timeout(void)
232 360
233int usb_process(void) 361int usb_process(void)
234{ 362{
235 int res; 363 int i, res;
236 struct timeval tv; 364 struct timeval tv;
237 tv.tv_sec = tv.tv_usec = 0; 365 tv.tv_sec = tv.tv_usec = 0;
238 res = libusb_handle_events_timeout(NULL, &tv); 366 res = libusb_handle_events_timeout(NULL, &tv);
@@ -240,6 +368,14 @@ int usb_process(void)
240 usbmuxd_log(LL_ERROR, "libusb_handle_events_timeout failed: %d", res); 368 usbmuxd_log(LL_ERROR, "libusb_handle_events_timeout failed: %d", res);
241 return res; 369 return res;
242 } 370 }
371 // reap devices marked dead due to an RX error
372 for(i=0; i<num_devs; i++) {
373 if(device_list[i].dev && !device_list[i].alive) {
374 device_remove(&device_list[i]);
375 usb_disconnect(&device_list[i]);
376 }
377 }
378
243 if(dev_poll_remain_ms() <= 0) { 379 if(dev_poll_remain_ms() <= 0) {
244 res = usb_discover(); 380 res = usb_discover();
245 if(res < 0) { 381 if(res < 0) {
@@ -256,12 +392,12 @@ int usb_init(void)
256 usbmuxd_log(LL_DEBUG, "usb_init for linux / libusb 1.0"); 392 usbmuxd_log(LL_DEBUG, "usb_init for linux / libusb 1.0");
257 393
258 res = libusb_init(NULL); 394 res = libusb_init(NULL);
395 //libusb_set_debug(NULL, 3);
259 if(res != 0) { 396 if(res != 0) {
260 usbmuxd_log(LL_FATAL, "libusb_init failed: %d", res); 397 usbmuxd_log(LL_FATAL, "libusb_init failed: %d", res);
261 return -1; 398 return -1;
262 } 399 }
263 400
264 device_id = 1;
265 num_devs = 1; 401 num_devs = 1;
266 device_list = malloc(sizeof(*device_list) * num_devs); 402 device_list = malloc(sizeof(*device_list) * num_devs);
267 memset(device_list, 0, sizeof(*device_list) * num_devs); 403 memset(device_list, 0, sizeof(*device_list) * num_devs);
diff --git a/usb.h b/usb.h
index 25243d8..2a29d2f 100644
--- a/usb.h
+++ b/usb.h
@@ -26,6 +26,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26#define BULK_IN 0x85 26#define BULK_IN 0x85
27#define BULK_OUT 0x04 27#define BULK_OUT 0x04
28 28
29#define USB_MTU 65536
30
29#define VID_APPLE 0x5ac 31#define VID_APPLE 0x5ac
30#define PID_IPHONE2G 0x1290 32#define PID_IPHONE2G 0x1290
31#define PID_ITOUCH1G 0x1291 33#define PID_ITOUCH1G 0x1291
@@ -42,6 +44,7 @@ const char *usb_get_serial(struct usb_device *dev);
42int usb_get_location(struct usb_device *dev); 44int usb_get_location(struct usb_device *dev);
43void usb_get_fds(struct fdlist *list); 45void usb_get_fds(struct fdlist *list);
44int usb_get_timeout(void); 46int usb_get_timeout(void);
47int usb_send(struct usb_device *dev, const unsigned char *buf, int length);
45int usb_process(void); 48int usb_process(void);
46 49
47#endif 50#endif