summaryrefslogtreecommitdiffstats
path: root/libusbmuxd
diff options
context:
space:
mode:
Diffstat (limited to 'libusbmuxd')
-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
4 files changed, 372 insertions, 84 deletions
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