summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2009-08-20 01:19:09 +0200
committerGravatar Hector Martin2009-08-21 03:08:18 +0200
commitc46062aca98f2f077b3bab5c5f72ff2cb57b9dc2 (patch)
tree0934caaa277436a42c515c9ccc86acb004620c7a
parent886d4014509d64023ecf99b57d0fd39818e85bd4 (diff)
downloadusbmuxd-c46062aca98f2f077b3bab5c5f72ff2cb57b9dc2.tar.gz
usbmuxd-c46062aca98f2f077b3bab5c5f72ff2cb57b9dc2.tar.bz2
Updated usbmuxd protocol definition and public header.
[Hector] Merged by putting utils.c into a common dir, avoiding log.c dependency for libusbmuxd, adding CMake magic to tie things up.
-rw-r--r--common/utils.c (renamed from usbmuxd/utils.c)11
-rw-r--r--common/utils.h (renamed from usbmuxd/utils.h)0
-rw-r--r--libusbmuxd/CMakeLists.txt4
-rw-r--r--libusbmuxd/libusbmuxd.c333
-rw-r--r--libusbmuxd/usbmuxd-proto.h58
-rw-r--r--libusbmuxd/usbmuxd.h61
-rw-r--r--tools/iproxy.c4
-rw-r--r--usbmuxd/CMakeLists.txt8
-rw-r--r--usbmuxd/client.c36
-rw-r--r--usbmuxd/client.h50
10 files changed, 409 insertions, 156 deletions
diff --git a/usbmuxd/utils.c b/common/utils.c
index 1ffa04a..6803941 100644
--- a/usbmuxd/utils.c
+++ b/common/utils.c
@@ -24,8 +24,15 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 24
25#include <stdlib.h> 25#include <stdlib.h>
26#include <string.h> 26#include <string.h>
27#include <stdio.h>
27#include "utils.h" 28#include "utils.h"
28#include "log.h" 29
30#ifdef USBMUXD_DAEMON
31# include "log.h"
32# define util_error(...) usbmuxd_log(LL_ERROR, __VA_ARGS__)
33#else
34# define util_error(...) fprintf(stderr, __VA_ARGS__)
35#endif
29 36
30void fdlist_create(struct fdlist *list) 37void fdlist_create(struct fdlist *list)
31{ 38{
@@ -96,7 +103,7 @@ void collection_remove(struct collection *col, void *element)
96 return; 103 return;
97 } 104 }
98 } 105 }
99 usbmuxd_log(LL_ERROR, "collection_remove: element %p not present in collection %p (cap %d)", element, col, col->capacity); 106 util_error("collection_remove: element %p not present in collection %p (cap %d)", element, col, col->capacity);
100} 107}
101 108
102int collection_count(struct collection *col) 109int collection_count(struct collection *col)
diff --git a/usbmuxd/utils.h b/common/utils.h
index ad4ac9d..ad4ac9d 100644
--- a/usbmuxd/utils.h
+++ b/common/utils.h
diff --git a/libusbmuxd/CMakeLists.txt b/libusbmuxd/CMakeLists.txt
index 61de1a8..7f7b35f 100644
--- a/libusbmuxd/CMakeLists.txt
+++ b/libusbmuxd/CMakeLists.txt
@@ -1,4 +1,6 @@
1add_library (libusbmuxd libusbmuxd.c sock_stuff.c) 1include_directories (${CMAKE_SOURCE_DIR}/common)
2
3add_library (libusbmuxd libusbmuxd.c sock_stuff.c ../common/utils.c)
2 4
3# 'lib' is a UNIXism, the proper CMake target is usbmuxd 5# 'lib' is a UNIXism, the proper CMake target is usbmuxd
4# But we can't use that due to the conflict with the usbmuxd daemon, 6# But we can't use that due to the conflict with the usbmuxd daemon,
diff --git a/libusbmuxd/libusbmuxd.c b/libusbmuxd/libusbmuxd.c
index 090695f..6a54765 100644
--- a/libusbmuxd/libusbmuxd.c
+++ b/libusbmuxd/libusbmuxd.c
@@ -6,6 +6,7 @@
6#include <sys/socket.h> 6#include <sys/socket.h>
7#include <arpa/inet.h> 7#include <arpa/inet.h>
8#include <unistd.h> 8#include <unistd.h>
9#include <signal.h>
9 10
10// usbmuxd public interface 11// usbmuxd public interface
11#include "usbmuxd.h" 12#include "usbmuxd.h"
@@ -13,10 +14,48 @@
13#include "usbmuxd-proto.h" 14#include "usbmuxd-proto.h"
14// socket utility functions 15// socket utility functions
15#include "sock_stuff.h" 16#include "sock_stuff.h"
17// misc utility functions
18#include "utils.h"
16 19
20static struct collection devices;
21static usbmuxd_event_cb_t event_cb = NULL;
22pthread_t devmon;
23static int listenfd = -1;
24
25/**
26 * Finds a device info record by its handle.
27 * if the record is not found, NULL is returned.
28 */
29static usbmuxd_device_info_t *devices_find(int handle)
30{
31 FOREACH(usbmuxd_device_info_t *dev, &devices) {
32 if (dev && dev->handle == handle) {
33 return dev;
34 }
35 } ENDFOREACH
36 return NULL;
37}
38
39/**
40 * Creates a socket connection to usbmuxd.
41 * For Mac/Linux it is a unix domain socket,
42 * for Windows it is a tcp socket.
43 */
44static int connect_usbmuxd_socket()
45{
46#ifdef WINDOWS
47 return connect_socket("127.0.0.1", 27015);
48#else
49 return connect_unix_socket(USBMUXD_SOCKET_FILE);
50#endif
51}
52
53/**
54 * Retrieves the result code to a previously sent request.
55 */
17static int usbmuxd_get_result(int sfd, uint32_t tag, uint32_t * result) 56static int usbmuxd_get_result(int sfd, uint32_t tag, uint32_t * result)
18{ 57{
19 struct usbmuxd_result res; 58 struct usbmuxd_result_msg res;
20 int recv_len; 59 int recv_len;
21 60
22 if (!result) { 61 if (!result) {
@@ -29,8 +68,8 @@ static int usbmuxd_get_result(int sfd, uint32_t tag, uint32_t * result)
29 } else { 68 } else {
30 if ((recv_len == sizeof(res)) 69 if ((recv_len == sizeof(res))
31 && (res.header.length == (uint32_t) recv_len) 70 && (res.header.length == (uint32_t) recv_len)
32 && (res.header.reserved == 0) 71 && (res.header.version == USBMUXD_PROTOCOL_VERSION)
33 && (res.header.type == USBMUXD_RESULT) 72 && (res.header.message == MESSAGE_RESULT)
34 ) { 73 ) {
35 *result = res.result; 74 *result = res.result;
36 if (res.header.tag == tag) { 75 if (res.header.tag == tag) {
@@ -44,16 +83,229 @@ static int usbmuxd_get_result(int sfd, uint32_t tag, uint32_t * result)
44 return -1; 83 return -1;
45} 84}
46 85
47int usbmuxd_scan(usbmuxd_scan_result ** available_devices) 86/**
87 * Generates an event, i.e. calls the callback function.
88 * A reference to a populated usbmuxd_event_t with information about the event
89 * and the corresponding device will be passed to the callback function.
90 */
91static void generate_event(usbmuxd_event_cb_t callback, const usbmuxd_device_info_t *dev, enum usbmuxd_device_event event)
92{
93 usbmuxd_event_t ev;
94
95 if (!callback || !dev) {
96 return;
97 }
98
99 ev.event = event;
100 memcpy(&ev.device, dev, sizeof(usbmuxd_device_info_t));
101
102 printf("%s: event=%d, handle=%d\n", __func__, ev.event, ev.device.handle);
103
104 callback(&ev);
105}
106
107/**
108 * Tries to connect to usbmuxd and wait if it is not running.
109 *
110 * TODO inotify support should come here
111 */
112static int usbmuxd_listen()
48{ 113{
49 struct usbmuxd_scan_request s_req;
50 int sfd; 114 int sfd;
51 int scan_success = 0; 115 uint32_t res = -1;
116 struct usbmuxd_listen_request req;
117 struct usbmuxd_header hdr;
118
119 req.header.length = sizeof(struct usbmuxd_listen_request);
120 req.header.version = USBMUXD_PROTOCOL_VERSION;
121 req.header.message = MESSAGE_LISTEN;
122 req.header.tag = 2;
123
124 sfd = connect_usbmuxd_socket();
125 if (sfd < 0) {
126 fprintf(stderr, "DEBUG: waiting for usbmuxd to come up.\n");
127
128 while (event_cb) {
129 if ((sfd = connect_usbmuxd_socket()) > 0) {
130 fprintf(stderr, "DEBUG: usbmuxd started\n");
131 break;
132 }
133 sleep(1);
134 }
135 }
136
137 if (sfd < 0) {
138 fprintf(stderr, "ERROR: usbmuxd was supposed to be running here...\n");
139 return sfd;
140 }
141
142 if (send_buf(sfd, &req, req.header.length) != (int)req.header.length) {
143 fprintf(stderr, "ERROR: could not send listen packet\n");
144 close(sfd);
145 return -1;
146 }
147 if (usbmuxd_get_result(sfd, req.header.tag, &res) && (res != 0)) {
148 fprintf(stderr, "ERROR: did not get OK\n");
149 close(sfd);
150 return -1;
151 }
152
153 return sfd;
154}
155
156/**
157 * Waits for an event to occur, i.e. a packet coming from usbmuxd.
158 * Calls generate_event to pass the event via callback to the client program.
159 */
160int get_next_event(int sfd, usbmuxd_event_cb_t callback)
161{
162 int recv_len;
163 struct usbmuxd_listen_request req;
164 struct usbmuxd_header hdr;
165
166 /* block until we receive something */
167 recv_len = recv_buf_timeout(sfd, &hdr, sizeof(hdr), 0, 0);
168 if (recv_len < 0) {
169 int i;
170 fprintf(stderr, "DEBUG: connection closed.\n");
171 // when then usbmuxd connection fails,
172 // generate remove events for every device that
173 // is still present so applications know about it
174 // TODO: is this behaviour correct?
175 FOREACH(usbmuxd_device_info_t *dev, &devices) {
176 generate_event(callback, dev, UE_DEVICE_REMOVE);
177 } ENDFOREACH
178 collection_free(&devices);
179 return recv_len;
180 } else if (recv_len == sizeof(hdr)) {
181 if (hdr.message == MESSAGE_DEVICE_ADD) {
182 struct usbmuxd_device_record dev;
183 usbmuxd_device_info_t *devinfo = (usbmuxd_device_info_t*)malloc(sizeof(usbmuxd_device_info_t));
184 if (!devinfo) {
185 fprintf(stderr, "Out of memory!\n");
186 return -1;
187 }
188
189 if (hdr.length != sizeof(struct usbmuxd_header)+sizeof(struct usbmuxd_device_record)) {
190 fprintf(stderr, "WARNING: unexpected packet size%d for MESSAGE_DEVICE_ADD (expected %d)!\n", hdr.length, sizeof(struct usbmuxd_header)+sizeof(struct usbmuxd_device_record));
191 }
192 recv_len = recv_buf_timeout(sfd, &dev, hdr.length - sizeof(struct usbmuxd_header), 0, 5000);
193 if (recv_len != (hdr.length - sizeof(struct usbmuxd_header))) {
194 fprintf(stderr, "Could not receive packet\n");
195 return recv_len;
196 }
197
198 devinfo->handle = dev.device_id;
199 devinfo->product_id = dev.product_id;
200 memset(devinfo->uuid, '\0', sizeof(devinfo->uuid));
201 memcpy(devinfo->uuid, dev.serial_number, sizeof(devinfo->uuid));
202
203 collection_add(&devices, devinfo);
204 generate_event(callback, devinfo, UE_DEVICE_ADD);
205 } else if (hdr.message == MESSAGE_DEVICE_REMOVE) {
206 uint32_t handle;
207 usbmuxd_device_info_t *dev;
208
209 if (hdr.length != sizeof(struct usbmuxd_header)+sizeof(uint32_t)) {
210 fprintf(stderr, "WARNING: unexpected packet size%d for MESSAGE_DEVICE_REMOVE (expected %d)!\n", hdr.length, sizeof(struct usbmuxd_header)+sizeof(uint32_t));
211 }
212 recv_len = recv_buf_timeout(sfd, &handle, sizeof(uint32_t), 0, 5000);
213 if (recv_len != sizeof(uint32_t)) {
214 fprintf(stderr, "Could not receive packet\n");
215 return recv_len;
216 }
217
218 dev = devices_find(handle);
219 if (!dev) {
220 fprintf(stderr, "WARNING: got device remove message for handle %d, but couldn't find the corresponding handle in the device list. This event will be ignored.\n", handle);
221 } else {
222 generate_event(callback, dev, UE_DEVICE_REMOVE);
223 collection_remove(&devices, dev);
224 }
225 } else {
226 fprintf(stderr, "%s: Unknown message type %d length %d\n", __func__, hdr.message, hdr.length);
227 }
228 } else {
229 fprintf(stderr, "%s: ERROR: incomplete packet received!\n", __func__);
230 }
231 return 0;
232}
233
234/**
235 * Device Monitor thread function.
236 *
237 * This function sets up a connection to usbmuxd
238 */
239static void *device_monitor(void *data)
240{
241 collection_init(&devices);
242
243 while (event_cb) {
244
245 listenfd = usbmuxd_listen();
246 if (listenfd < 0) {
247 fprintf(stderr, "DEBUG: listenfd=%d\n", listenfd);
248 continue;
249 }
250
251 while (event_cb) {
252 printf("waiting for events\n");
253 int res = get_next_event(listenfd, event_cb);
254 if (res < 0) {
255 fprintf(stderr, "%s: closing connection (code %d)\n", __func__, res);
256 break;
257 }
258 }
259 }
260
261 collection_free(&devices);
262 printf("%s: terminated\n", __func__);
263
264 return NULL;
265}
266
267int usbmuxd_subscribe(usbmuxd_event_cb_t callback)
268{
269 int res;
270
271 if (!callback) {
272 return -EINVAL;
273 }
274 event_cb = callback;
275
276 res = pthread_create(&devmon, NULL, device_monitor, NULL);
277 if (res != 0) {
278 fprintf(stderr, "ERROR: Could not start device watcher thread!\n");
279 return res;
280 }
281 return 0;
282}
283
284int usbmuxd_unsubscribe()
285{
286 event_cb = NULL;
287
288 if (pthread_kill(devmon, 0) == 0) {
289 printf("%s: unsubscribing callback\n", __func__);
290 close(listenfd);
291 listenfd = -1;
292 pthread_kill(devmon, SIGINT);
293 pthread_join(devmon, NULL);
294 }
295
296 return 0;
297}
298
299int usbmuxd_scan(usbmuxd_device_info_t ** available_devices)
300{
301 struct usbmuxd_listen_request s_req;
302 int sfd;
303 int listen_success = 0;
52 uint32_t res; 304 uint32_t res;
53 uint32_t pktlen;
54 int recv_len; 305 int recv_len;
55 usbmuxd_scan_result *newlist = NULL; 306 usbmuxd_device_info_t *newlist = NULL;
56 struct usbmuxd_device_info_record dev_info_pkt; 307 struct usbmuxd_header hdr;
308 struct usbmuxd_device_record dev_info;
57 int dev_cnt = 0; 309 int dev_cnt = 0;
58 310
59 sfd = connect_unix_socket(USBMUXD_SOCKET_FILE); 311 sfd = connect_unix_socket(USBMUXD_SOCKET_FILE);
@@ -62,9 +314,9 @@ int usbmuxd_scan(usbmuxd_scan_result ** available_devices)
62 return sfd; 314 return sfd;
63 } 315 }
64 316
65 s_req.header.length = sizeof(struct usbmuxd_scan_request); 317 s_req.header.length = sizeof(struct usbmuxd_listen_request);
66 s_req.header.reserved = 0; 318 s_req.header.version = USBMUXD_PROTOCOL_VERSION;
67 s_req.header.type = USBMUXD_SCAN; 319 s_req.header.message = MESSAGE_LISTEN;
68 s_req.header.tag = 2; 320 s_req.header.tag = 2;
69 321
70 // send scan request packet 322 // send scan request packet
@@ -73,7 +325,7 @@ int usbmuxd_scan(usbmuxd_scan_result ** available_devices)
73 res = -1; 325 res = -1;
74 // get response 326 // get response
75 if (usbmuxd_get_result(sfd, s_req.header.tag, &res) && (res == 0)) { 327 if (usbmuxd_get_result(sfd, s_req.header.tag, &res) && (res == 0)) {
76 scan_success = 1; 328 listen_success = 1;
77 } else { 329 } else {
78 fprintf(stderr, 330 fprintf(stderr,
79 "%s: Did not get response to scan request (with result=0)...\n", 331 "%s: Did not get response to scan request (with result=0)...\n",
@@ -83,50 +335,44 @@ int usbmuxd_scan(usbmuxd_scan_result ** available_devices)
83 } 335 }
84 } 336 }
85 337
86 if (!scan_success) { 338 if (!listen_success) {
87 fprintf(stderr, "%s: Could not send scan request!\n", __func__); 339 fprintf(stderr, "%s: Could not send listen request!\n", __func__);
88 return -1; 340 return -1;
89 } 341 }
90 342
91 *available_devices = NULL; 343 *available_devices = NULL;
92 // receive device list 344 // receive device list
93 while (1) { 345 while (1) {
94 if (recv_buf_timeout(sfd, &pktlen, 4, MSG_PEEK, 1000) == 4) { 346 if (recv_buf_timeout(sfd, &hdr, sizeof(hdr), 0, 1000) == sizeof(hdr)) {
95 if (pktlen != sizeof(dev_info_pkt)) { 347 if (hdr.length != sizeof(hdr)+sizeof(dev_info)) {
96 // invalid packet size received! 348 // invalid packet size received!
97 fprintf(stderr, 349 fprintf(stderr,
98 "%s: Invalid packet size (%d) received when expecting a device info record.\n", 350 "%s: Invalid packet size (%d) received when expecting a device info record.\n",
99 __func__, pktlen); 351 __func__, hdr.length);
100 break; 352 break;
101 } 353 }
102 354
103 recv_len = recv_buf(sfd, &dev_info_pkt, pktlen); 355 recv_len = recv_buf(sfd, &dev_info, hdr.length - sizeof(hdr));
104 if (recv_len <= 0) { 356 if (recv_len <= 0) {
105 fprintf(stderr, 357 fprintf(stderr,
106 "%s: Error when receiving device info record\n", 358 "%s: Error when receiving device info record\n",
107 __func__); 359 __func__);
108 break; 360 break;
109 } else if ((uint32_t) recv_len < pktlen) { 361 } else if ((uint32_t) recv_len < hdr.length - sizeof(hdr)) {
110 fprintf(stderr, 362 fprintf(stderr,
111 "%s: received less data than specified in header!\n", 363 "%s: received less data than specified in header!\n", __func__);
112 __func__);
113 } else { 364 } else {
114 //fprintf(stderr, "%s: got device record with id %d, UUID=%s\n", __func__, dev_info_pkt.device_info.device_id, dev_info_pkt.device_info.serial_number); 365 newlist = (usbmuxd_device_info_t *) realloc(*available_devices, sizeof(usbmuxd_device_info_t) * (dev_cnt + 1));
115 newlist =
116 (usbmuxd_scan_result *) realloc(*available_devices,
117 sizeof
118 (usbmuxd_scan_result) *
119 (dev_cnt + 1));
120 if (newlist) { 366 if (newlist) {
121 newlist[dev_cnt].handle = 367 newlist[dev_cnt].handle =
122 (int) dev_info_pkt.device.device_id; 368 (int) dev_info.device_id;
123 newlist[dev_cnt].product_id = 369 newlist[dev_cnt].product_id =
124 dev_info_pkt.device.product_id; 370 dev_info.product_id;
125 memset(newlist[dev_cnt].serial_number, '\0', 371 memset(newlist[dev_cnt].uuid, '\0',
126 sizeof(newlist[dev_cnt].serial_number)); 372 sizeof(newlist[dev_cnt].uuid));
127 memcpy(newlist[dev_cnt].serial_number, 373 memcpy(newlist[dev_cnt].uuid,
128 dev_info_pkt.device.serial_number, 374 dev_info.serial_number,
129 sizeof(dev_info_pkt.device.serial_number)); 375 sizeof(newlist[dev_cnt].uuid));
130 *available_devices = newlist; 376 *available_devices = newlist;
131 dev_cnt++; 377 dev_cnt++;
132 } else { 378 } else {
@@ -144,24 +390,21 @@ int usbmuxd_scan(usbmuxd_scan_result ** available_devices)
144 } 390 }
145 391
146 // terminating zero record 392 // terminating zero record
147 newlist = 393 newlist = (usbmuxd_device_info_t*) realloc(*available_devices, sizeof(usbmuxd_device_info_t) * (dev_cnt + 1));
148 (usbmuxd_scan_result *) realloc(*available_devices, 394 memset(newlist + dev_cnt, 0, sizeof(usbmuxd_device_info_t));
149 sizeof(usbmuxd_scan_result) *
150 (dev_cnt + 1));
151 memset(newlist + dev_cnt, 0, sizeof(usbmuxd_scan_result));
152 *available_devices = newlist; 395 *available_devices = newlist;
153 396
154 return dev_cnt; 397 return dev_cnt;
155} 398}
156 399
157int usbmuxd_connect(const int handle, const unsigned short tcp_port) 400int usbmuxd_connect(const int handle, const unsigned short port)
158{ 401{
159 int sfd; 402 int sfd;
160 struct usbmuxd_connect_request c_req; 403 struct usbmuxd_connect_request c_req;
161 int connected = 0; 404 int connected = 0;
162 uint32_t res = -1; 405 uint32_t res = -1;
163 406
164 sfd = connect_unix_socket(USBMUXD_SOCKET_FILE); 407 sfd = connect_usbmuxd_socket();
165 if (sfd < 0) { 408 if (sfd < 0) {
166 fprintf(stderr, "%s: Error: Connection to usbmuxd failed: %s\n", 409 fprintf(stderr, "%s: Error: Connection to usbmuxd failed: %s\n",
167 __func__, strerror(errno)); 410 __func__, strerror(errno));
@@ -169,11 +412,11 @@ int usbmuxd_connect(const int handle, const unsigned short tcp_port)
169 } 412 }
170 413
171 c_req.header.length = sizeof(c_req); 414 c_req.header.length = sizeof(c_req);
172 c_req.header.reserved = 0; 415 c_req.header.version = USBMUXD_PROTOCOL_VERSION;
173 c_req.header.type = USBMUXD_CONNECT; 416 c_req.header.message = MESSAGE_CONNECT;
174 c_req.header.tag = 3; 417 c_req.header.tag = 3;
175 c_req.device_id = (uint32_t) handle; 418 c_req.device_id = (uint32_t) handle;
176 c_req.tcp_dport = htons(tcp_port); 419 c_req.port = htons(port);
177 c_req.reserved = 0; 420 c_req.reserved = 0;
178 421
179 if (send_buf(sfd, &c_req, sizeof(c_req)) < 0) { 422 if (send_buf(sfd, &c_req, sizeof(c_req)) < 0) {
diff --git a/libusbmuxd/usbmuxd-proto.h b/libusbmuxd/usbmuxd-proto.h
index 7f8c2d6..1ecb7bc 100644
--- a/libusbmuxd/usbmuxd-proto.h
+++ b/libusbmuxd/usbmuxd-proto.h
@@ -1,52 +1,62 @@
1/* Protocol defintion for usbmuxd proxy protocol */ 1/* Protocol defintion for usbmuxd proxy protocol */
2
3#ifndef __USBMUXD_PROTO_H 2#ifndef __USBMUXD_PROTO_H
4#define __USBMUXD_PROTO_H 3#define __USBMUXD_PROTO_H
5 4
6#include <stdint.h> 5#include <stdint.h>
6#define USBMUXD_PROTOCOL_VERSION 0
7 7
8#define USBMUXD_SOCKET_FILE "/var/run/usbmuxd" 8#define USBMUXD_SOCKET_FILE "/var/run/usbmuxd"
9 9
10enum usbmuxd_result {
11 RESULT_OK = 0,
12 RESULT_BADCOMMAND = 1,
13 RESULT_BADDEV = 2,
14 RESULT_CONNREFUSED = 3,
15 // ???
16 // ???
17 RESULT_BADVERSION = 6,
18};
19
20enum usbmuxd_msgtype {
21 MESSAGE_RESULT = 1,
22 MESSAGE_CONNECT = 2,
23 MESSAGE_LISTEN = 3,
24 MESSAGE_DEVICE_ADD = 4,
25 MESSAGE_DEVICE_REMOVE = 5,
26 //???
27 //???
28 //MESSAGE_PLIST = 8,
29};
30
10struct usbmuxd_header { 31struct usbmuxd_header {
11 uint32_t length; // length of message, including header 32 uint32_t length; // length of message, including header
12 uint32_t reserved; // always zero 33 uint32_t version; // protocol version
13 uint32_t type; // message type 34 uint32_t message; // message type
14 uint32_t tag; // responses to this query will echo back this tag 35 uint32_t tag; // responses to this query will echo back this tag
15} __attribute__((__packed__)); 36} __attribute__((__packed__));
16 37
17struct usbmuxd_result { 38struct usbmuxd_result_msg {
18 struct usbmuxd_header header; 39 struct usbmuxd_header header;
19 uint32_t result; 40 uint32_t result;
20} __attribute__((__packed__)); 41} __attribute__((__packed__));
21 42
22struct usbmuxd_connect_request { 43struct usbmuxd_connect_request {
23 struct usbmuxd_header header; 44 struct usbmuxd_header header;
24 uint32_t device_id; 45 uint32_t device_id;
25 uint16_t tcp_dport; // TCP port number 46 uint16_t port; // TCP port number
26 uint16_t reserved; // set to zero 47 uint16_t reserved; // set to zero
27} __attribute__((__packed__)); 48} __attribute__((__packed__));
28 49
29struct usbmuxd_device { 50struct usbmuxd_listen_request {
30 uint32_t device_id;
31 uint16_t product_id;
32 char serial_number[40];
33} __attribute__((__packed__));
34
35struct usbmuxd_device_info_record {
36 struct usbmuxd_header header; 51 struct usbmuxd_header header;
37 struct usbmuxd_device device;
38 char padding[222];
39} __attribute__((__packed__)); 52} __attribute__((__packed__));
40 53
41struct usbmuxd_scan_request { 54struct usbmuxd_device_record {
42 struct usbmuxd_header header; 55 uint32_t device_id;
56 uint16_t product_id;
57 char serial_number[256];
58 uint16_t padding;
59 uint32_t location;
43} __attribute__((__packed__)); 60} __attribute__((__packed__));
44 61
45enum {
46 USBMUXD_RESULT = 1,
47 USBMUXD_CONNECT = 2,
48 USBMUXD_SCAN = 3,
49 USBMUXD_DEVICE_INFO = 4,
50};
51
52#endif /* __USBMUXD_PROTO_H */ 62#endif /* __USBMUXD_PROTO_H */
diff --git a/libusbmuxd/usbmuxd.h b/libusbmuxd/usbmuxd.h
index ba45ec3..f12ae39 100644
--- a/libusbmuxd/usbmuxd.h
+++ b/libusbmuxd/usbmuxd.h
@@ -2,10 +2,7 @@
2#define __USBMUXD_H 2#define __USBMUXD_H
3 3
4/** 4/**
5 * Array entry returned by 'usbmuxd_scan()' scanning. 5 * Device information structure holding data to identify the device.
6 *
7 * If more than one device is available, 'product_id' and
8 * 'serial_number' and be analysed to help make a selection.
9 * The relevant 'handle' should be passed to 'usbmuxd_connect()', to 6 * The relevant 'handle' should be passed to 'usbmuxd_connect()', to
10 * start a proxy connection. The value 'handle' should be considered 7 * start a proxy connection. The value 'handle' should be considered
11 * opaque and no presumption made about the meaning of its value. 8 * opaque and no presumption made about the meaning of its value.
@@ -13,22 +10,58 @@
13typedef struct { 10typedef struct {
14 int handle; 11 int handle;
15 int product_id; 12 int product_id;
16 char serial_number[41]; 13 char uuid[41];
17} usbmuxd_scan_result; 14} usbmuxd_device_info_t;
15
16/**
17 * event types for event callback function
18 */
19enum usbmuxd_device_event {
20 UE_DEVICE_ADD = 1,
21 UE_DEVICE_REMOVE
22};
23
24/**
25 * Event structure that will be passed to the callback function.
26 * 'event' will contains the type of the event, and 'device' will contains
27 * information about the device.
28 */
29typedef struct {
30 int event;
31 usbmuxd_device_info_t device;
32} usbmuxd_event_t;
33
34/**
35 * Callback function prototype.
36 */
37typedef void (*usbmuxd_event_cb_t) (const usbmuxd_event_t *event);
38
39/**
40 * Subscribe a callback function so that applications get to know about
41 * device add/remove events.
42 *
43 * @param callback A callback function that is executed when an event occurs.
44 *
45 * @return 0 on success or negative on error.
46 */
47int usbmuxd_subscribe(usbmuxd_event_cb_t callback);
48
49/**
50 * Unsubscribe callback.
51 *
52 * @return only 0 for now.
53 */
54int usbmuxd_unsubscribe();
18 55
19/** 56/**
20 * Contacts usbmuxd and performs a scan for connected devices. 57 * Contacts usbmuxd and retrieves a list of connected devices.
21 * 58 *
22 * @param available_devices pointer to array of usbmuxd_scan_result. 59 * @param available_devices pointer to an array of usbmuxd_device_info_t
23 * Array of available devices. The required 'handle' 60 * that will hold records of the connected devices.
24 * should be passed to 'usbmuxd_connect()'. The returned array
25 * is zero-terminated for convenience; the final (unused)
26 * entry containing handle == 0. The returned array pointer
27 * should be freed by passing to 'free()' after use.
28 * 61 *
29 * @return number of available devices, zero on no devices, or negative on error 62 * @return number of available devices, zero on no devices, or negative on error
30 */ 63 */
31int usbmuxd_scan(usbmuxd_scan_result **available_devices); 64int usbmuxd_scan(usbmuxd_device_info_t **available_devices);
32 65
33/** 66/**
34 * Request proxy connect to 67 * Request proxy connect to
diff --git a/tools/iproxy.c b/tools/iproxy.c
index 3cb2894..657ac89 100644
--- a/tools/iproxy.c
+++ b/tools/iproxy.c
@@ -141,7 +141,7 @@ void *run_ctos_loop(void *arg)
141void *acceptor_thread(void *arg) 141void *acceptor_thread(void *arg)
142{ 142{
143 struct client_data *cdata; 143 struct client_data *cdata;
144 usbmuxd_scan_result *dev_list = NULL; 144 usbmuxd_device_info_t *dev_list = NULL;
145 pthread_t ctos; 145 pthread_t ctos;
146 int count; 146 int count;
147 147
@@ -166,7 +166,7 @@ void *acceptor_thread(void *arg)
166 return NULL; 166 return NULL;
167 } 167 }
168 168
169 fprintf(stdout, "Requesting connecion to device handle == %d (serial: %s), port %d\n", dev_list[0].handle, dev_list[0].serial_number, device_port); 169 fprintf(stdout, "Requesting connecion to device handle == %d (serial: %s), port %d\n", dev_list[0].handle, dev_list[0].uuid, device_port);
170 170
171 cdata->sfd = usbmuxd_connect(dev_list[0].handle, device_port); 171 cdata->sfd = usbmuxd_connect(dev_list[0].handle, device_port);
172 free(dev_list); 172 free(dev_list);
diff --git a/usbmuxd/CMakeLists.txt b/usbmuxd/CMakeLists.txt
index b982dc0..7d0d3d8 100644
--- a/usbmuxd/CMakeLists.txt
+++ b/usbmuxd/CMakeLists.txt
@@ -2,8 +2,12 @@ find_package(USB REQUIRED)
2include_directories(${USB_INCLUDE_DIRS}) 2include_directories(${USB_INCLUDE_DIRS})
3set(LIBS ${LIBS} ${USB_LIBRARIES}) 3set(LIBS ${LIBS} ${USB_LIBRARIES})
4 4
5add_definitions(-Wall -O2 -g) 5include_directories (${CMAKE_SOURCE_DIR}/common)
6add_executable(usbmuxd main.c usb-linux.c log.c utils.c device.c client.c) 6include_directories (${CMAKE_SOURCE_DIR}/usbmuxd)
7include_directories (${CMAKE_SOURCE_DIR}/libusbmuxd)
8
9add_definitions(-Wall -O2 -g -DUSBMUXD_DAEMON)
10add_executable(usbmuxd main.c usb-linux.c log.c ../common/utils.c device.c client.c)
7target_link_libraries(usbmuxd ${LIBS}) 11target_link_libraries(usbmuxd ${LIBS})
8 12
9install(TARGETS usbmuxd RUNTIME DESTINATION sbin) \ No newline at end of file 13install(TARGETS usbmuxd RUNTIME DESTINATION sbin) \ No newline at end of file
diff --git a/usbmuxd/client.c b/usbmuxd/client.c
index 7a3160f..0e47e84 100644
--- a/usbmuxd/client.c
+++ b/usbmuxd/client.c
@@ -150,10 +150,10 @@ void client_get_fds(struct fdlist *list)
150 } ENDFOREACH 150 } ENDFOREACH
151} 151}
152 152
153static int send_pkt(struct mux_client *client, uint32_t tag, enum client_msgtype msg, void *payload, int payload_length) 153static int send_pkt(struct mux_client *client, uint32_t tag, enum usbmuxd_msgtype msg, void *payload, int payload_length)
154{ 154{
155 struct client_header hdr; 155 struct usbmuxd_header hdr;
156 hdr.version = CLIENT_PROTOCOL_VERSION; 156 hdr.version = USBMUXD_PROTOCOL_VERSION;
157 hdr.length = sizeof(hdr) + payload_length; 157 hdr.length = sizeof(hdr) + payload_length;
158 hdr.message = msg; 158 hdr.message = msg;
159 hdr.tag = tag; 159 hdr.tag = tag;
@@ -176,7 +176,7 @@ static int send_result(struct mux_client *client, uint32_t tag, uint32_t result)
176 return send_pkt(client, tag, MESSAGE_RESULT, &result, sizeof(uint32_t)); 176 return send_pkt(client, tag, MESSAGE_RESULT, &result, sizeof(uint32_t));
177} 177}
178 178
179int client_notify_connect(struct mux_client *client, enum client_result result) 179int client_notify_connect(struct mux_client *client, enum usbmuxd_result result)
180{ 180{
181 usbmuxd_log(LL_SPEW, "client_notify_connect fd %d result %d", client->fd, result); 181 usbmuxd_log(LL_SPEW, "client_notify_connect fd %d result %d", client->fd, result);
182 if(client->state == CLIENT_DEAD) 182 if(client->state == CLIENT_DEAD)
@@ -201,13 +201,13 @@ int client_notify_connect(struct mux_client *client, enum client_result result)
201 201
202static int notify_device(struct mux_client *client, struct device_info *dev) 202static int notify_device(struct mux_client *client, struct device_info *dev)
203{ 203{
204 struct client_msg_dev dmsg; 204 struct usbmuxd_device_record dmsg;
205 memset(&dmsg, 0, sizeof(dmsg)); 205 memset(&dmsg, 0, sizeof(dmsg));
206 dmsg.device_id = dev->id; 206 dmsg.device_id = dev->id;
207 strncpy(dmsg.device_serial, dev->serial, 256); 207 strncpy(dmsg.serial_number, dev->serial, 256);
208 dmsg.device_serial[255] = 0; 208 dmsg.serial_number[255] = 0;
209 dmsg.location = dev->location; 209 dmsg.location = dev->location;
210 dmsg.device_pid = dev->pid; 210 dmsg.product_id = dev->pid;
211 return send_pkt(client, 0, MESSAGE_DEVICE_ADD, &dmsg, sizeof(dmsg)); 211 return send_pkt(client, 0, MESSAGE_DEVICE_ADD, &dmsg, sizeof(dmsg));
212} 212}
213 213
@@ -225,7 +225,7 @@ static int start_listen(struct mux_client *client)
225 count = device_get_list(devs); 225 count = device_get_list(devs);
226 226
227 // going to need a larger buffer for many devices 227 // going to need a larger buffer for many devices
228 int needed_buffer = count * (sizeof(struct client_msg_dev) + sizeof(struct client_header)) + REPLY_BUF_SIZE; 228 int needed_buffer = count * (sizeof(struct usbmuxd_device_record) + sizeof(struct usbmuxd_header)) + REPLY_BUF_SIZE;
229 if(client->ob_capacity < needed_buffer) { 229 if(client->ob_capacity < needed_buffer) {
230 usbmuxd_log(LL_DEBUG, "Enlarging client %d reply buffer %d -> %d to make space for device notifications", client->fd, client->ob_capacity, needed_buffer); 230 usbmuxd_log(LL_DEBUG, "Enlarging client %d reply buffer %d -> %d to make space for device notifications", client->fd, client->ob_capacity, needed_buffer);
231 client->ob_buf = realloc(client->ob_buf, needed_buffer); 231 client->ob_buf = realloc(client->ob_buf, needed_buffer);
@@ -242,7 +242,7 @@ static int start_listen(struct mux_client *client)
242 return count; 242 return count;
243} 243}
244 244
245static int client_command(struct mux_client *client, struct client_header *hdr, const char *payload) 245static int client_command(struct mux_client *client, struct usbmuxd_header *hdr, const char *payload)
246{ 246{
247 int res; 247 int res;
248 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); 248 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);
@@ -255,7 +255,7 @@ static int client_command(struct mux_client *client, struct client_header *hdr,
255 return -1; 255 return -1;
256 } 256 }
257 257
258 struct client_msg_connect *ch; 258 struct usbmuxd_connect_request *ch;
259 switch(hdr->message) { 259 switch(hdr->message) {
260 case MESSAGE_LISTEN: 260 case MESSAGE_LISTEN:
261 if(send_result(client, hdr->tag, 0) < 0) 261 if(send_result(client, hdr->tag, 0) < 0)
@@ -318,8 +318,8 @@ static void process_recv(struct mux_client *client)
318{ 318{
319 int res; 319 int res;
320 int did_read = 0; 320 int did_read = 0;
321 if(client->ib_size < sizeof(struct client_header)) { 321 if(client->ib_size < sizeof(struct usbmuxd_header)) {
322 res = recv(client->fd, client->ib_buf + client->ib_size, sizeof(struct client_header) - client->ib_size, 0); 322 res = recv(client->fd, client->ib_buf + client->ib_size, sizeof(struct usbmuxd_header) - client->ib_size, 0);
323 if(res <= 0) { 323 if(res <= 0) {
324 if(res < 0) 324 if(res < 0)
325 usbmuxd_log(LL_ERROR, "Receive from client fd %d failed: %s", client->fd, strerror(errno)); 325 usbmuxd_log(LL_ERROR, "Receive from client fd %d failed: %s", client->fd, strerror(errno));
@@ -329,20 +329,20 @@ static void process_recv(struct mux_client *client)
329 return; 329 return;
330 } 330 }
331 client->ib_size += res; 331 client->ib_size += res;
332 if(client->ib_size < sizeof(struct client_header)) 332 if(client->ib_size < sizeof(struct usbmuxd_header))
333 return; 333 return;
334 did_read = 1; 334 did_read = 1;
335 } 335 }
336 struct client_header *hdr = (void*)client->ib_buf; 336 struct usbmuxd_header *hdr = (void*)client->ib_buf;
337 if(hdr->version != CLIENT_PROTOCOL_VERSION) { 337 if(hdr->version != USBMUXD_PROTOCOL_VERSION) {
338 usbmuxd_log(LL_INFO, "Client %d version mismatch: expected %d, got %d", client->fd, CLIENT_PROTOCOL_VERSION, hdr->version); 338 usbmuxd_log(LL_INFO, "Client %d version mismatch: expected %d, got %d", client->fd, USBMUXD_PROTOCOL_VERSION, hdr->version);
339 client_close(client); 339 client_close(client);
340 } 340 }
341 if(hdr->length > client->ib_capacity) { 341 if(hdr->length > client->ib_capacity) {
342 usbmuxd_log(LL_INFO, "Client %d message is too long (%d bytes)", client->fd, hdr->length); 342 usbmuxd_log(LL_INFO, "Client %d message is too long (%d bytes)", client->fd, hdr->length);
343 client_close(client); 343 client_close(client);
344 } 344 }
345 if(hdr->length < sizeof(struct client_header)) { 345 if(hdr->length < sizeof(struct usbmuxd_header)) {
346 usbmuxd_log(LL_ERROR, "Client %d message is too short (%d bytes)", client->fd, hdr->length); 346 usbmuxd_log(LL_ERROR, "Client %d message is too short (%d bytes)", client->fd, hdr->length);
347 client_close(client); 347 client_close(client);
348 } 348 }
diff --git a/usbmuxd/client.h b/usbmuxd/client.h
index 0cda676..4fc1ab4 100644
--- a/usbmuxd/client.h
+++ b/usbmuxd/client.h
@@ -22,62 +22,16 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22#define __CLIENT_H__ 22#define __CLIENT_H__
23 23
24#include <stdint.h> 24#include <stdint.h>
25#include "usbmuxd-proto.h"
25 26
26struct device_info; 27struct device_info;
27struct mux_client; 28struct mux_client;
28 29
29enum client_result {
30 RESULT_OK = 0,
31 RESULT_BADCOMMAND = 1,
32 RESULT_BADDEV = 2,
33 RESULT_CONNREFUSED = 3,
34 // ???
35 // ???
36 RESULT_BADVERSION = 6,
37};
38
39enum client_msgtype {
40 MESSAGE_RESULT = 1,
41 MESSAGE_CONNECT = 2,
42 MESSAGE_LISTEN = 3,
43 MESSAGE_DEVICE_ADD = 4,
44 MESSAGE_DEVICE_REMOVE = 5,
45 //???
46 //???
47 //MESSAGE_PLIST = 8,
48};
49
50#define CLIENT_PROTOCOL_VERSION 0
51
52struct client_header {
53 uint32_t length;
54 uint32_t version;
55 uint32_t message;
56 uint32_t tag;
57};
58
59struct client_msg_result {
60 uint32_t result;
61};
62
63struct client_msg_connect {
64 uint32_t device_id;
65 uint16_t port;
66};
67
68struct client_msg_dev {
69 uint32_t device_id;
70 uint16_t device_pid;
71 char device_serial[256];
72 uint16_t padding;
73 uint32_t location;
74};
75
76int client_read(struct mux_client *client, void *buffer, int len); 30int client_read(struct mux_client *client, void *buffer, int len);
77int client_write(struct mux_client *client, void *buffer, int len); 31int client_write(struct mux_client *client, void *buffer, int len);
78int client_set_events(struct mux_client *client, short events); 32int client_set_events(struct mux_client *client, short events);
79void client_close(struct mux_client *client); 33void client_close(struct mux_client *client);
80int client_notify_connect(struct mux_client *client, enum client_result result); 34int client_notify_connect(struct mux_client *client, enum usbmuxd_result result);
81 35
82void client_device_add(struct device_info *dev); 36void client_device_add(struct device_info *dev);
83void client_device_remove(int device_id); 37void client_device_remove(int device_id);