summaryrefslogtreecommitdiffstats
path: root/libusbmuxd/libusbmuxd.c
diff options
context:
space:
mode:
Diffstat (limited to 'libusbmuxd/libusbmuxd.c')
-rw-r--r--libusbmuxd/libusbmuxd.c248
1 files changed, 248 insertions, 0 deletions
diff --git a/libusbmuxd/libusbmuxd.c b/libusbmuxd/libusbmuxd.c
new file mode 100644
index 0000000..090695f
--- /dev/null
+++ b/libusbmuxd/libusbmuxd.c
@@ -0,0 +1,248 @@
1#include <stdint.h>
2#include <stdlib.h>
3#include <errno.h>
4#include <stdio.h>
5#include <string.h>
6#include <sys/socket.h>
7#include <arpa/inet.h>
8#include <unistd.h>
9
10// usbmuxd public interface
11#include "usbmuxd.h"
12// usbmuxd protocol
13#include "usbmuxd-proto.h"
14// socket utility functions
15#include "sock_stuff.h"
16
17static int usbmuxd_get_result(int sfd, uint32_t tag, uint32_t * result)
18{
19 struct usbmuxd_result res;
20 int recv_len;
21
22 if (!result) {
23 return -EINVAL;
24 }
25
26 if ((recv_len = recv_buf(sfd, &res, sizeof(res))) <= 0) {
27 perror("recv");
28 return -errno;
29 } else {
30 if ((recv_len == sizeof(res))
31 && (res.header.length == (uint32_t) recv_len)
32 && (res.header.reserved == 0)
33 && (res.header.type == USBMUXD_RESULT)
34 ) {
35 *result = res.result;
36 if (res.header.tag == tag) {
37 return 1;
38 } else {
39 return 0;
40 }
41 }
42 }
43
44 return -1;
45}
46
47int usbmuxd_scan(usbmuxd_scan_result ** available_devices)
48{
49 struct usbmuxd_scan_request s_req;
50 int sfd;
51 int scan_success = 0;
52 uint32_t res;
53 uint32_t pktlen;
54 int recv_len;
55 usbmuxd_scan_result *newlist = NULL;
56 struct usbmuxd_device_info_record dev_info_pkt;
57 int dev_cnt = 0;
58
59 sfd = connect_unix_socket(USBMUXD_SOCKET_FILE);
60 if (sfd < 0) {
61 fprintf(stderr, "%s: error opening socket!\n", __func__);
62 return sfd;
63 }
64
65 s_req.header.length = sizeof(struct usbmuxd_scan_request);
66 s_req.header.reserved = 0;
67 s_req.header.type = USBMUXD_SCAN;
68 s_req.header.tag = 2;
69
70 // send scan request packet
71 if (send_buf(sfd, &s_req, s_req.header.length) ==
72 (int) s_req.header.length) {
73 res = -1;
74 // get response
75 if (usbmuxd_get_result(sfd, s_req.header.tag, &res) && (res == 0)) {
76 scan_success = 1;
77 } else {
78 fprintf(stderr,
79 "%s: Did not get response to scan request (with result=0)...\n",
80 __func__);
81 close(sfd);
82 return res;
83 }
84 }
85
86 if (!scan_success) {
87 fprintf(stderr, "%s: Could not send scan request!\n", __func__);
88 return -1;
89 }
90
91 *available_devices = NULL;
92 // receive device list
93 while (1) {
94 if (recv_buf_timeout(sfd, &pktlen, 4, MSG_PEEK, 1000) == 4) {
95 if (pktlen != sizeof(dev_info_pkt)) {
96 // invalid packet size received!
97 fprintf(stderr,
98 "%s: Invalid packet size (%d) received when expecting a device info record.\n",
99 __func__, pktlen);
100 break;
101 }
102
103 recv_len = recv_buf(sfd, &dev_info_pkt, pktlen);
104 if (recv_len <= 0) {
105 fprintf(stderr,
106 "%s: Error when receiving device info record\n",
107 __func__);
108 break;
109 } else if ((uint32_t) recv_len < pktlen) {
110 fprintf(stderr,
111 "%s: received less data than specified in header!\n",
112 __func__);
113 } 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);
115 newlist =
116 (usbmuxd_scan_result *) realloc(*available_devices,
117 sizeof
118 (usbmuxd_scan_result) *
119 (dev_cnt + 1));
120 if (newlist) {
121 newlist[dev_cnt].handle =
122 (int) dev_info_pkt.device.device_id;
123 newlist[dev_cnt].product_id =
124 dev_info_pkt.device.product_id;
125 memset(newlist[dev_cnt].serial_number, '\0',
126 sizeof(newlist[dev_cnt].serial_number));
127 memcpy(newlist[dev_cnt].serial_number,
128 dev_info_pkt.device.serial_number,
129 sizeof(dev_info_pkt.device.serial_number));
130 *available_devices = newlist;
131 dev_cnt++;
132 } else {
133 fprintf(stderr,
134 "%s: ERROR: out of memory when trying to realloc!\n",
135 __func__);
136 break;
137 }
138 }
139 } else {
140 // we _should_ have all of them now.
141 // or perhaps an error occured.
142 break;
143 }
144 }
145
146 // terminating zero record
147 newlist =
148 (usbmuxd_scan_result *) realloc(*available_devices,
149 sizeof(usbmuxd_scan_result) *
150 (dev_cnt + 1));
151 memset(newlist + dev_cnt, 0, sizeof(usbmuxd_scan_result));
152 *available_devices = newlist;
153
154 return dev_cnt;
155}
156
157int usbmuxd_connect(const int handle, const unsigned short tcp_port)
158{
159 int sfd;
160 struct usbmuxd_connect_request c_req;
161 int connected = 0;
162 uint32_t res = -1;
163
164 sfd = connect_unix_socket(USBMUXD_SOCKET_FILE);
165 if (sfd < 0) {
166 fprintf(stderr, "%s: Error: Connection to usbmuxd failed: %s\n",
167 __func__, strerror(errno));
168 return sfd;
169 }
170
171 c_req.header.length = sizeof(c_req);
172 c_req.header.reserved = 0;
173 c_req.header.type = USBMUXD_CONNECT;
174 c_req.header.tag = 3;
175 c_req.device_id = (uint32_t) handle;
176 c_req.tcp_dport = htons(tcp_port);
177 c_req.reserved = 0;
178
179 if (send_buf(sfd, &c_req, sizeof(c_req)) < 0) {
180 perror("send");
181 } else {
182 // read ACK
183 //fprintf(stderr, "%s: Reading connect result...\n", __func__);
184 if (usbmuxd_get_result(sfd, c_req.header.tag, &res)) {
185 if (res == 0) {
186 //fprintf(stderr, "%s: Connect success!\n", __func__);
187 connected = 1;
188 } else {
189 fprintf(stderr, "%s: Connect failed, Error code=%d\n",
190 __func__, res);
191 }
192 }
193 }
194
195 if (connected) {
196 return sfd;
197 }
198
199 close(sfd);
200
201 return -1;
202}
203
204int usbmuxd_disconnect(int sfd)
205{
206 return close(sfd);
207}
208
209int usbmuxd_send(int sfd, const char *data, uint32_t len, uint32_t *sent_bytes)
210{
211 int num_sent;
212
213 if (sfd < 0) {
214 return -EINVAL;
215 }
216
217 num_sent = send(sfd, (void*)data, len, 0);
218 if (num_sent < 0) {
219 *sent_bytes = 0;
220 fprintf(stderr, "%s: Error %d when sending: %s\n", __func__, num_sent, strerror(errno));
221 return num_sent;
222 } else if ((uint32_t)num_sent < len) {
223 fprintf(stderr, "%s: Warning: Did not send enough (only %d of %d)\n", __func__, num_sent, len);
224 }
225
226 *sent_bytes = num_sent;
227
228 return 0;
229}
230
231int usbmuxd_recv_timeout(int sfd, char *data, uint32_t len, uint32_t *recv_bytes, unsigned int timeout)
232{
233 int num_recv = recv_buf_timeout(sfd, (void*)data, len, 0, timeout);
234 if (num_recv < 0) {
235 *recv_bytes = 0;
236 return num_recv;
237 }
238
239 *recv_bytes = num_recv;
240
241 return 0;
242}
243
244int usbmuxd_recv(int sfd, char *data, uint32_t len, uint32_t *recv_bytes)
245{
246 return usbmuxd_recv_timeout(sfd, data, len, recv_bytes, 5000);
247}
248