summaryrefslogtreecommitdiffstats
path: root/libusbmuxd/libusbmuxd.c
diff options
context:
space:
mode:
Diffstat (limited to 'libusbmuxd/libusbmuxd.c')
-rw-r--r--libusbmuxd/libusbmuxd.c782
1 files changed, 0 insertions, 782 deletions
diff --git a/libusbmuxd/libusbmuxd.c b/libusbmuxd/libusbmuxd.c
deleted file mode 100644
index 5eaf8e6..0000000
--- a/libusbmuxd/libusbmuxd.c
+++ /dev/null
@@ -1,782 +0,0 @@
1/*
2 libusbmuxd - client library to talk to usbmuxd
3
4Copyright (C) 2009-2010 Nikias Bassen <nikias@gmx.li>
5Copyright (C) 2009 Paul Sladen <libiphone@paul.sladen.org>
6Copyright (C) 2009 Martin Szulecki <opensuse@sukimashita.com>
7
8This library is free software; you can redistribute it and/or modify
9it under the terms of the GNU Lesser General Public License as
10published by the Free Software Foundation, either version 2.1 of the
11License, or (at your option) any later version.
12
13This library is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU Lesser General Public
19License along with this program; if not, write to the Free Software
20Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
22*/
23
24#include <stdint.h>
25#include <stdlib.h>
26#include <errno.h>
27#include <stdio.h>
28#include <string.h>
29#ifdef WIN32
30#include <windows.h>
31#include <winsock2.h>
32#define sleep(x) Sleep(x*1000)
33#else
34#include <sys/socket.h>
35#include <arpa/inet.h>
36#endif
37#include <unistd.h>
38#include <signal.h>
39#include <pthread.h>
40
41#ifdef HAVE_PLIST
42#include <plist/plist.h>
43#define PLIST_BUNDLE_ID "com.marcansoft.usbmuxd"
44#define PLIST_CLIENT_VERSION_STRING "usbmuxd built for freedom"
45#define PLIST_PROGNAME "libusbmuxd"
46#endif
47
48// usbmuxd public interface
49#include "usbmuxd.h"
50// usbmuxd protocol
51#include "usbmuxd-proto.h"
52// socket utility functions
53#include "sock_stuff.h"
54// misc utility functions
55#include "utils.h"
56
57static struct collection devices;
58static usbmuxd_event_cb_t event_cb = NULL;
59pthread_t devmon;
60static int listenfd = -1;
61
62static int use_tag = 0;
63static int proto_version = 0;
64
65/**
66 * Finds a device info record by its handle.
67 * if the record is not found, NULL is returned.
68 */
69static usbmuxd_device_info_t *devices_find(int handle)
70{
71 FOREACH(usbmuxd_device_info_t *dev, &devices) {
72 if (dev && dev->handle == handle) {
73 return dev;
74 }
75 } ENDFOREACH
76 return NULL;
77}
78
79/**
80 * Creates a socket connection to usbmuxd.
81 * For Mac/Linux it is a unix domain socket,
82 * for Windows it is a tcp socket.
83 */
84static int connect_usbmuxd_socket()
85{
86#if defined(WIN32) || defined(__CYGWIN__)
87 return connect_socket("127.0.0.1", USBMUXD_SOCKET_PORT);
88#else
89 return connect_unix_socket(USBMUXD_SOCKET_FILE);
90#endif
91}
92
93static int receive_packet(int sfd, struct usbmuxd_header *header, void **payload, int timeout)
94{
95 int recv_len;
96 struct usbmuxd_header hdr;
97 char *payload_loc = NULL;
98
99 header->length = 0;
100 header->version = 0;
101 header->message = 0;
102 header->tag = 0;
103
104 recv_len = recv_buf_timeout(sfd, &hdr, sizeof(hdr), 0, timeout);
105 if (recv_len < 0) {
106 return recv_len;
107 } else if (recv_len < sizeof(hdr)) {
108 return recv_len;
109 }
110
111 uint32_t payload_size = hdr.length - sizeof(hdr);
112 if (payload_size > 0) {
113 payload_loc = (char*)malloc(payload_size);
114 if (recv_buf_timeout(sfd, payload_loc, payload_size, 0, 5000) != payload_size) {
115 fprintf(stderr, "%s: Error receiving payload of size %d\n", __func__, payload_size);
116 free(payload_loc);
117 return -EBADMSG;
118 }
119 }
120
121#ifdef HAVE_PLIST
122 if (hdr.message == MESSAGE_PLIST) {
123 char *message = NULL;
124 plist_t plist = NULL;
125 plist_from_xml(payload_loc, payload_size, &plist);
126 free(payload_loc);
127
128 if (!plist) {
129 fprintf(stderr, "%s: Error getting plist from payload!\n", __func__);
130 return -EBADMSG;
131 }
132
133 plist_t node = plist_dict_get_item(plist, "MessageType");
134 if (plist_get_node_type(node) != PLIST_STRING) {
135 fprintf(stderr, "%s: Error getting message type from plist!\n", __func__);
136 free(plist);
137 return -EBADMSG;
138 }
139
140 plist_get_string_val(node, &message);
141 if (message) {
142 uint64_t val = 0;
143 if (strcmp(message, "Result") == 0) {
144 /* result message */
145 uint32_t dwval = 0;
146 plist_t n = plist_dict_get_item(plist, "Number");
147 plist_get_uint_val(n, &val);
148 *payload = malloc(sizeof(uint32_t));
149 dwval = val;
150 memcpy(*payload, &dwval, sizeof(dwval));
151 hdr.length = sizeof(hdr) + sizeof(dwval);
152 hdr.message = MESSAGE_RESULT;
153 } else if (strcmp(message, "Attached") == 0) {
154 /* device add message */
155 struct usbmuxd_device_record *dev = NULL;
156 plist_t props = plist_dict_get_item(plist, "Properties");
157 if (!props) {
158 fprintf(stderr, "%s: Could not get properties for message '%s' from plist!\n", __func__, message);
159 plist_free(plist);
160 return -EBADMSG;
161 }
162 dev = (struct usbmuxd_device_record*)malloc(sizeof(struct usbmuxd_device_record));
163 memset(dev, 0, sizeof(struct usbmuxd_device_record));
164
165 plist_t n = plist_dict_get_item(props, "DeviceID");
166 plist_get_uint_val(n, &val);
167 dev->device_id = (uint32_t)val;
168
169 n = plist_dict_get_item(props, "ProductID");
170 plist_get_uint_val(n, &val);
171 dev->product_id = (uint32_t)val;
172
173 n = plist_dict_get_item(props, "SerialNumber");
174 char *strval = NULL;
175 plist_get_string_val(n, &strval);
176 if (strval) {
177 strcpy(dev->serial_number, strval);
178 free(strval);
179 }
180 n = plist_dict_get_item(props, "LocationID");
181 plist_get_uint_val(n, &val);
182 dev->location = (uint32_t)val;
183 *payload = (void*)dev;
184 hdr.length = sizeof(hdr) + sizeof(struct usbmuxd_device_record);
185 hdr.message = MESSAGE_DEVICE_ADD;
186 } else if (strcmp(message, "Detached") == 0) {
187 /* device remove message */
188 uint32_t dwval = 0;
189 plist_t n = plist_dict_get_item(plist, "DeviceID");
190 if (n) {
191 plist_get_uint_val(n, &val);
192 *payload = malloc(sizeof(uint32_t));
193 dwval = val;
194 memcpy(*payload, &dwval, sizeof(dwval));
195 hdr.length = sizeof(hdr) + sizeof(dwval);
196 hdr.message = MESSAGE_DEVICE_REMOVE;
197 }
198 } else {
199 fprintf(stderr, "%s: Unexpected message '%s' in plist!\n", __func__, message);
200 plist_free(plist);
201 return -EBADMSG;
202 }
203 }
204 plist_free(plist);
205 } else
206#endif
207 {
208 *payload = payload_loc;
209 }
210
211 memcpy(header, &hdr, sizeof(hdr));
212
213 return hdr.length;
214}
215
216/**
217 * Retrieves the result code to a previously sent request.
218 */
219static int usbmuxd_get_result(int sfd, uint32_t tag, uint32_t * result)
220{
221 struct usbmuxd_header hdr;
222 int recv_len;
223 uint32_t *res = NULL;
224
225 if (!result) {
226 return -EINVAL;
227 }
228 *result = -1;
229
230 if ((recv_len = receive_packet(sfd, &hdr, (void**)&res, 5000)) < 0) {
231 fprintf(stderr, "%s: Error receiving packet: %d\n", __func__, errno);
232 if (res)
233 free(res);
234 return -errno;
235 }
236 if (recv_len < sizeof(hdr)) {
237 fprintf(stderr, "%s: Received packet is too small!\n", __func__);
238 if (res)
239 free(res);
240 return -EPROTO;
241 }
242
243 if (hdr.message == MESSAGE_RESULT) {
244 int ret = 0;
245 if (res && (hdr.tag == tag)) {
246 memcpy(result, res, sizeof(uint32_t));
247 ret = 1;
248 }
249 if (res)
250 free(res);
251 return ret;
252 }
253 fprintf(stderr, "%s: Unexpected message of type %d received!\n", __func__, hdr.message);
254 if (res)
255 free(res);
256 return -EPROTO;
257}
258
259static int send_packet(int sfd, uint32_t message, uint32_t tag, void *payload, uint32_t payload_size)
260{
261 struct usbmuxd_header header;
262
263 header.length = sizeof(struct usbmuxd_header);
264 header.version = proto_version;
265 header.message = message;
266 header.tag = tag;
267 if (payload && (payload_size > 0)) {
268 header.length += payload_size;
269 }
270 int sent = send_buf(sfd, &header, sizeof(header));
271 if (sent != sizeof(header)) {
272 fprintf(stderr, "%s: ERROR: could not send packet header\n", __func__);
273 return -1;
274 }
275 if (payload && (payload_size > 0)) {
276 sent += send_buf(sfd, payload, payload_size);
277 }
278 if (sent != (int)header.length) {
279 fprintf(stderr, "%s: ERROR: could not send whole packet\n", __func__);
280 close_socket(sfd);
281 return -1;
282 }
283 return sent;
284}
285
286static int send_listen_packet(int sfd, uint32_t tag)
287{
288 int res = 0;
289#ifdef HAVE_PLIST
290 if (proto_version == 1) {
291 /* plist packet */
292 char *payload = NULL;
293 uint32_t payload_size = 0;
294 plist_t plist;
295
296 /* construct message plist */
297 plist = plist_new_dict();
298 plist_dict_insert_item(plist, "BundleID", plist_new_string(PLIST_BUNDLE_ID));
299 plist_dict_insert_item(plist, "ClientVersionString", plist_new_string(PLIST_CLIENT_VERSION_STRING));
300 plist_dict_insert_item(plist, "MessageType", plist_new_string("Listen"));
301 plist_dict_insert_item(plist, "ProgName", plist_new_string(PLIST_PROGNAME));
302 plist_to_xml(plist, &payload, &payload_size);
303 plist_free(plist);
304
305 res = send_packet(sfd, MESSAGE_PLIST, tag, payload, payload_size);
306 free(payload);
307 } else
308#endif
309 {
310 /* binary packet */
311 res = send_packet(sfd, MESSAGE_LISTEN, tag, NULL, 0);
312 }
313 return res;
314}
315
316static int send_connect_packet(int sfd, uint32_t tag, uint32_t device_id, uint16_t port)
317{
318 int res = 0;
319#ifdef HAVE_PLIST
320 if (proto_version == 1) {
321 /* plist packet */
322 char *payload = NULL;
323 uint32_t payload_size = 0;
324 plist_t plist;
325
326 /* construct message plist */
327 plist = plist_new_dict();
328 plist_dict_insert_item(plist, "BundleID", plist_new_string(PLIST_BUNDLE_ID));
329 plist_dict_insert_item(plist, "ClientVersionString", plist_new_string(PLIST_CLIENT_VERSION_STRING));
330 plist_dict_insert_item(plist, "MessageType", plist_new_string("Connect"));
331 plist_dict_insert_item(plist, "DeviceID", plist_new_uint(device_id));
332 plist_dict_insert_item(plist, "PortNumber", plist_new_uint(htons(port)));
333 plist_dict_insert_item(plist, "ProgName", plist_new_string(PLIST_PROGNAME));
334 plist_to_xml(plist, &payload, &payload_size);
335 plist_free(plist);
336
337 res = send_packet(sfd, MESSAGE_PLIST, tag, (void*)payload, payload_size);
338 free(payload);
339 } else
340#endif
341 {
342 /* binary packet */
343 struct {
344 uint32_t device_id;
345 uint16_t port;
346 uint16_t reserved;
347 } conninfo;
348
349 conninfo.device_id = device_id;
350 conninfo.port = htons(port);
351 conninfo.reserved = 0;
352
353 res = send_packet(sfd, MESSAGE_CONNECT, tag, &conninfo, sizeof(conninfo));
354 }
355 return res;
356}
357
358/**
359 * Generates an event, i.e. calls the callback function.
360 * A reference to a populated usbmuxd_event_t with information about the event
361 * and the corresponding device will be passed to the callback function.
362 */
363static void generate_event(usbmuxd_event_cb_t callback, const usbmuxd_device_info_t *dev, enum usbmuxd_event_type event, void *user_data)
364{
365 usbmuxd_event_t ev;
366
367 if (!callback || !dev) {
368 return;
369 }
370
371 ev.event = event;
372 memcpy(&ev.device, dev, sizeof(usbmuxd_device_info_t));
373
374 callback(&ev, user_data);
375}
376
377/**
378 * Tries to connect to usbmuxd and wait if it is not running.
379 *
380 * TODO inotify support should come here
381 */
382static int usbmuxd_listen()
383{
384 int sfd;
385 uint32_t res = -1;
386
387#ifdef HAVE_PLIST
388retry:
389#endif
390 sfd = connect_usbmuxd_socket();
391 if (sfd < 0) {
392 while (event_cb) {
393 if ((sfd = connect_usbmuxd_socket()) > 0) {
394 break;
395 }
396 sleep(1);
397 }
398 }
399
400 if (sfd < 0) {
401 fprintf(stderr, "%s: ERROR: usbmuxd was supposed to be running here...\n", __func__);
402 return sfd;
403 }
404
405 use_tag++;
406 if (send_listen_packet(sfd, use_tag) <= 0) {
407 fprintf(stderr, "%s: ERROR: could not send listen packet\n", __func__);
408 close_socket(sfd);
409 return -1;
410 }
411 if (usbmuxd_get_result(sfd, use_tag, &res) && (res != 0)) {
412 close_socket(sfd);
413#ifdef HAVE_PLIST
414 if ((res == RESULT_BADVERSION) && (proto_version != 1)) {
415 proto_version = 1;
416 goto retry;
417 }
418#endif
419 fprintf(stderr, "%s: ERROR: did not get OK but %d\n", __func__, res);
420 return -1;
421 }
422
423 return sfd;
424}
425
426/**
427 * Waits for an event to occur, i.e. a packet coming from usbmuxd.
428 * Calls generate_event to pass the event via callback to the client program.
429 */
430int get_next_event(int sfd, usbmuxd_event_cb_t callback, void *user_data)
431{
432 struct usbmuxd_header hdr;
433 void *payload = NULL;
434
435 /* block until we receive something */
436 if (receive_packet(sfd, &hdr, &payload, 0) < 0) {
437 // when then usbmuxd connection fails,
438 // generate remove events for every device that
439 // is still present so applications know about it
440 FOREACH(usbmuxd_device_info_t *dev, &devices) {
441 generate_event(callback, dev, UE_DEVICE_REMOVE, user_data);
442 collection_remove(&devices, dev);
443 } ENDFOREACH
444 return -EIO;
445 }
446
447 if ((hdr.length > sizeof(hdr)) && !payload) {
448 fprintf(stderr, "%s: Invalid packet received, payload is missing!\n", __func__);
449 return -EBADMSG;
450 }
451
452 if (hdr.message == MESSAGE_DEVICE_ADD) {
453 struct usbmuxd_device_record *dev = payload;
454 usbmuxd_device_info_t *devinfo = (usbmuxd_device_info_t*)malloc(sizeof(usbmuxd_device_info_t));
455 if (!devinfo) {
456 fprintf(stderr, "%s: Out of memory!\n", __func__);
457 free(payload);
458 return -1;
459 }
460
461 devinfo->handle = dev->device_id;
462 devinfo->product_id = dev->product_id;
463 memset(devinfo->uuid, '\0', sizeof(devinfo->uuid));
464 memcpy(devinfo->uuid, dev->serial_number, sizeof(devinfo->uuid));
465
466 collection_add(&devices, devinfo);
467 generate_event(callback, devinfo, UE_DEVICE_ADD, user_data);
468 } else if (hdr.message == MESSAGE_DEVICE_REMOVE) {
469 uint32_t handle;
470 usbmuxd_device_info_t *devinfo;
471
472 memcpy(&handle, payload, sizeof(uint32_t));
473
474 devinfo = devices_find(handle);
475 if (!devinfo) {
476 fprintf(stderr, "%s: 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", __func__, handle);
477 } else {
478 generate_event(callback, devinfo, UE_DEVICE_REMOVE, user_data);
479 collection_remove(&devices, devinfo);
480 }
481 } else {
482 fprintf(stderr, "%s: Unexpected message type %d length %d received!\n", __func__, hdr.message, hdr.length);
483 }
484 if (payload) {
485 free(payload);
486 }
487 return 0;
488}
489
490/**
491 * Device Monitor thread function.
492 *
493 * This function sets up a connection to usbmuxd
494 */
495static void *device_monitor(void *data)
496{
497 collection_init(&devices);
498
499 while (event_cb) {
500
501 listenfd = usbmuxd_listen();
502 if (listenfd < 0) {
503 continue;
504 }
505
506 while (event_cb) {
507 int res = get_next_event(listenfd, event_cb, data);
508 if (res < 0) {
509 break;
510 }
511 }
512 }
513
514 collection_free(&devices);
515
516 return NULL;
517}
518
519int usbmuxd_subscribe(usbmuxd_event_cb_t callback, void *user_data)
520{
521 int res;
522
523 if (!callback) {
524 return -EINVAL;
525 }
526 event_cb = callback;
527
528 res = pthread_create(&devmon, NULL, device_monitor, user_data);
529 if (res != 0) {
530 fprintf(stderr, "%s: ERROR: Could not start device watcher thread!\n", __func__);
531 return res;
532 }
533 return 0;
534}
535
536int usbmuxd_unsubscribe()
537{
538 event_cb = NULL;
539
540 if (pthread_kill(devmon, 0) == 0) {
541 close_socket(listenfd);
542 listenfd = -1;
543 pthread_kill(devmon, SIGINT);
544 pthread_join(devmon, NULL);
545 }
546
547 return 0;
548}
549
550int usbmuxd_get_device_list(usbmuxd_device_info_t **device_list)
551{
552 int sfd;
553 int listen_success = 0;
554 uint32_t res;
555 usbmuxd_device_info_t *newlist = NULL;
556 struct usbmuxd_header hdr;
557 struct usbmuxd_device_record *dev_info;
558 int dev_cnt = 0;
559 void *payload = NULL;
560
561#ifdef HAVE_PLIST
562retry:
563#endif
564 sfd = connect_usbmuxd_socket();
565 if (sfd < 0) {
566 fprintf(stderr, "%s: error opening socket!\n", __func__);
567 return sfd;
568 }
569
570 use_tag++;
571 if (send_listen_packet(sfd, use_tag) > 0) {
572 res = -1;
573 // get response
574 if (usbmuxd_get_result(sfd, use_tag, &res) && (res == 0)) {
575 listen_success = 1;
576 } else {
577 close_socket(sfd);
578#ifdef HAVE_PLIST
579 if ((res == RESULT_BADVERSION) && (proto_version != 1)) {
580 proto_version = 1;
581 goto retry;
582 }
583#endif
584 fprintf(stderr,
585 "%s: Did not get response to scan request (with result=0)...\n",
586 __func__);
587 return res;
588 }
589 }
590
591 if (!listen_success) {
592 fprintf(stderr, "%s: Could not send listen request!\n", __func__);
593 return -1;
594 }
595
596 *device_list = NULL;
597 // receive device list
598 while (1) {
599 if (receive_packet(sfd, &hdr, &payload, 1000) > 0) {
600 if (hdr.message == MESSAGE_DEVICE_ADD) {
601 dev_info = payload;
602 newlist = (usbmuxd_device_info_t *) realloc(*device_list, sizeof(usbmuxd_device_info_t) * (dev_cnt + 1));
603 if (newlist) {
604 newlist[dev_cnt].handle =
605 (int) dev_info->device_id;
606 newlist[dev_cnt].product_id =
607 dev_info->product_id;
608 memset(newlist[dev_cnt].uuid, '\0',
609 sizeof(newlist[dev_cnt].uuid));
610 memcpy(newlist[dev_cnt].uuid,
611 dev_info->serial_number,
612 sizeof(newlist[dev_cnt].uuid));
613 *device_list = newlist;
614 dev_cnt++;
615 } else {
616 fprintf(stderr,
617 "%s: ERROR: out of memory when trying to realloc!\n",
618 __func__);
619 if (payload)
620 free(payload);
621 break;
622 }
623 } else {
624 fprintf(stderr, "%s: Unexpected message %d\n", __func__, hdr.message);
625 }
626 if (payload)
627 free(payload);
628 } else {
629 // we _should_ have all of them now.
630 // or perhaps an error occured.
631 break;
632 }
633 }
634
635 // explicitly close connection
636 close_socket(sfd);
637
638 // terminating zero record
639 newlist = (usbmuxd_device_info_t*) realloc(*device_list, sizeof(usbmuxd_device_info_t) * (dev_cnt + 1));
640 memset(newlist + dev_cnt, 0, sizeof(usbmuxd_device_info_t));
641 *device_list = newlist;
642
643 return dev_cnt;
644}
645
646int usbmuxd_device_list_free(usbmuxd_device_info_t **device_list)
647{
648 if (device_list) {
649 free(*device_list);
650 }
651 return 0;
652}
653
654int usbmuxd_get_device_by_uuid(const char *uuid, usbmuxd_device_info_t *device)
655{
656 usbmuxd_device_info_t *dev_list = NULL;
657
658 if (!device) {
659 return -EINVAL;
660 }
661 if (usbmuxd_get_device_list(&dev_list) < 0) {
662 return -ENODEV;
663 }
664
665 int i;
666 int result = 0;
667 for (i = 0; dev_list[i].handle > 0; i++) {
668 if (!uuid) {
669 device->handle = dev_list[i].handle;
670 device->product_id = dev_list[i].product_id;
671 strcpy(device->uuid, dev_list[i].uuid);
672 result = 1;
673 break;
674 }
675 if (!strcmp(uuid, dev_list[i].uuid)) {
676 device->handle = dev_list[i].handle;
677 device->product_id = dev_list[i].product_id;
678 strcpy(device->uuid, dev_list[i].uuid);
679 result = 1;
680 break;
681 }
682 }
683
684 free(dev_list);
685
686 return result;
687}
688
689int usbmuxd_connect(const int handle, const unsigned short port)
690{
691 int sfd;
692 int connected = 0;
693 uint32_t res = -1;
694
695#ifdef HAVE_PLIST
696retry:
697#endif
698 sfd = connect_usbmuxd_socket();
699 if (sfd < 0) {
700 fprintf(stderr, "%s: Error: Connection to usbmuxd failed: %s\n",
701 __func__, strerror(errno));
702 return sfd;
703 }
704
705 use_tag++;
706 if (send_connect_packet(sfd, use_tag, (uint32_t)handle, (uint16_t)port) <= 0) {
707 fprintf(stderr, "%s: Error sending connect message!\n", __func__);
708 } else {
709 // read ACK
710 //fprintf(stderr, "%s: Reading connect result...\n", __func__);
711 if (usbmuxd_get_result(sfd, use_tag, &res)) {
712 if (res == 0) {
713 //fprintf(stderr, "%s: Connect success!\n", __func__);
714 connected = 1;
715 } else {
716#ifdef HAVE_PLIST
717 if ((res == RESULT_BADVERSION) && (proto_version == 0)) {
718 proto_version = 1;
719 close_socket(sfd);
720 goto retry;
721 }
722#endif
723 fprintf(stderr, "%s: Connect failed, Error code=%d\n",
724 __func__, res);
725 }
726 }
727 }
728
729 if (connected) {
730 return sfd;
731 }
732
733 close_socket(sfd);
734
735 return -1;
736}
737
738int usbmuxd_disconnect(int sfd)
739{
740 return close_socket(sfd);
741}
742
743int usbmuxd_send(int sfd, const char *data, uint32_t len, uint32_t *sent_bytes)
744{
745 int num_sent;
746
747 if (sfd < 0) {
748 return -EINVAL;
749 }
750
751 num_sent = send(sfd, (void*)data, len, 0);
752 if (num_sent < 0) {
753 *sent_bytes = 0;
754 fprintf(stderr, "%s: Error %d when sending: %s\n", __func__, num_sent, strerror(errno));
755 return num_sent;
756 } else if ((uint32_t)num_sent < len) {
757 fprintf(stderr, "%s: Warning: Did not send enough (only %d of %d)\n", __func__, num_sent, len);
758 }
759
760 *sent_bytes = num_sent;
761
762 return 0;
763}
764
765int usbmuxd_recv_timeout(int sfd, char *data, uint32_t len, uint32_t *recv_bytes, unsigned int timeout)
766{
767 int num_recv = recv_buf_timeout(sfd, (void*)data, len, 0, timeout);
768 if (num_recv < 0) {
769 *recv_bytes = 0;
770 return num_recv;
771 }
772
773 *recv_bytes = num_recv;
774
775 return 0;
776}
777
778int usbmuxd_recv(int sfd, char *data, uint32_t len, uint32_t *recv_bytes)
779{
780 return usbmuxd_recv_timeout(sfd, data, len, recv_bytes, 5000);
781}
782