summaryrefslogtreecommitdiffstats
path: root/device.c
diff options
context:
space:
mode:
Diffstat (limited to 'device.c')
-rw-r--r--device.c225
1 files changed, 214 insertions, 11 deletions
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}