diff options
| author | 2009-08-20 03:42:52 +0200 | |
|---|---|---|
| committer | 2009-08-20 06:51:10 +0200 | |
| commit | 1a0c58e4062da7db73b4c08963f741cf016f6aa5 (patch) | |
| tree | b250f094e978d48622ecf652e28e9f3b68873893 /libusbmuxd/libusbmuxd.c | |
| parent | f4854f3fd725b5ba49cd5157d941783cffa08c04 (diff) | |
| parent | 79ca4d9a3c3a82bb5a3f9be1ac7a2533c7a89b05 (diff) | |
| download | usbmuxd-1a0c58e4062da7db73b4c08963f741cf016f6aa5.tar.gz usbmuxd-1a0c58e4062da7db73b4c08963f741cf016f6aa5.tar.bz2 | |
Merge the two development histories
Diffstat (limited to 'libusbmuxd/libusbmuxd.c')
| -rw-r--r-- | libusbmuxd/libusbmuxd.c | 248 | 
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 @@ +#include <stdint.h> +#include <stdlib.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <unistd.h> + +// usbmuxd public interface +#include "usbmuxd.h" +// usbmuxd protocol  +#include "usbmuxd-proto.h" +// socket utility functions +#include "sock_stuff.h" + +static int usbmuxd_get_result(int sfd, uint32_t tag, uint32_t * result) +{ +	struct usbmuxd_result res; +	int recv_len; + +	if (!result) { +		return -EINVAL; +	} + +	if ((recv_len = recv_buf(sfd, &res, sizeof(res))) <= 0) { +		perror("recv"); +		return -errno; +	} else { +		if ((recv_len == sizeof(res)) +			&& (res.header.length == (uint32_t) recv_len) +			&& (res.header.reserved == 0) +			&& (res.header.type == USBMUXD_RESULT) +			) { +			*result = res.result; +			if (res.header.tag == tag) { +				return 1; +			} else { +				return 0; +			} +		} +	} + +	return -1; +} + +int usbmuxd_scan(usbmuxd_scan_result ** available_devices) +{ +	struct usbmuxd_scan_request s_req; +	int sfd; +	int scan_success = 0; +	uint32_t res; +	uint32_t pktlen; +	int recv_len; +	usbmuxd_scan_result *newlist = NULL; +	struct usbmuxd_device_info_record dev_info_pkt; +	int dev_cnt = 0; + +	sfd = connect_unix_socket(USBMUXD_SOCKET_FILE); +	if (sfd < 0) { +		fprintf(stderr, "%s: error opening socket!\n", __func__); +		return sfd; +	} + +	s_req.header.length = sizeof(struct usbmuxd_scan_request); +	s_req.header.reserved = 0; +	s_req.header.type = USBMUXD_SCAN; +	s_req.header.tag = 2; + +	// send scan request packet +	if (send_buf(sfd, &s_req, s_req.header.length) == +		(int) s_req.header.length) { +		res = -1; +		// get response +		if (usbmuxd_get_result(sfd, s_req.header.tag, &res) && (res == 0)) { +			scan_success = 1; +		} else { +			fprintf(stderr, +					"%s: Did not get response to scan request (with result=0)...\n", +					__func__); +			close(sfd); +			return res; +		} +	} + +	if (!scan_success) { +		fprintf(stderr, "%s: Could not send scan request!\n", __func__); +		return -1; +	} + +	*available_devices = NULL; +	// receive device list +	while (1) { +		if (recv_buf_timeout(sfd, &pktlen, 4, MSG_PEEK, 1000) == 4) { +			if (pktlen != sizeof(dev_info_pkt)) { +				// invalid packet size received! +				fprintf(stderr, +						"%s: Invalid packet size (%d) received when expecting a device info record.\n", +						__func__, pktlen); +				break; +			} + +			recv_len = recv_buf(sfd, &dev_info_pkt, pktlen); +			if (recv_len <= 0) { +				fprintf(stderr, +						"%s: Error when receiving device info record\n", +						__func__); +				break; +			} else if ((uint32_t) recv_len < pktlen) { +				fprintf(stderr, +						"%s: received less data than specified in header!\n", +						__func__); +			} else { +				//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); +				newlist = +					(usbmuxd_scan_result *) realloc(*available_devices, +													sizeof +													(usbmuxd_scan_result) * +													(dev_cnt + 1)); +				if (newlist) { +					newlist[dev_cnt].handle = +						(int) dev_info_pkt.device.device_id; +					newlist[dev_cnt].product_id = +						dev_info_pkt.device.product_id; +					memset(newlist[dev_cnt].serial_number, '\0', +						   sizeof(newlist[dev_cnt].serial_number)); +					memcpy(newlist[dev_cnt].serial_number, +						   dev_info_pkt.device.serial_number, +						   sizeof(dev_info_pkt.device.serial_number)); +					*available_devices = newlist; +					dev_cnt++; +				} else { +					fprintf(stderr, +							"%s: ERROR: out of memory when trying to realloc!\n", +							__func__); +					break; +				} +			} +		} else { +			// we _should_ have all of them now. +			// or perhaps an error occured. +			break; +		} +	} + +	// terminating zero record +	newlist = +		(usbmuxd_scan_result *) realloc(*available_devices, +										sizeof(usbmuxd_scan_result) * +										(dev_cnt + 1)); +	memset(newlist + dev_cnt, 0, sizeof(usbmuxd_scan_result)); +	*available_devices = newlist; + +	return dev_cnt; +} + +int usbmuxd_connect(const int handle, const unsigned short tcp_port) +{ +	int sfd; +	struct usbmuxd_connect_request c_req; +	int connected = 0; +	uint32_t res = -1; + +	sfd = connect_unix_socket(USBMUXD_SOCKET_FILE); +	if (sfd < 0) { +		fprintf(stderr, "%s: Error: Connection to usbmuxd failed: %s\n", +				__func__, strerror(errno)); +		return sfd; +	} + +	c_req.header.length = sizeof(c_req); +	c_req.header.reserved = 0; +	c_req.header.type = USBMUXD_CONNECT; +	c_req.header.tag = 3; +	c_req.device_id = (uint32_t) handle; +	c_req.tcp_dport = htons(tcp_port); +	c_req.reserved = 0; + +	if (send_buf(sfd, &c_req, sizeof(c_req)) < 0) { +		perror("send"); +	} else { +		// read ACK +		//fprintf(stderr, "%s: Reading connect result...\n", __func__); +		if (usbmuxd_get_result(sfd, c_req.header.tag, &res)) { +			if (res == 0) { +				//fprintf(stderr, "%s: Connect success!\n", __func__); +				connected = 1; +			} else { +				fprintf(stderr, "%s: Connect failed, Error code=%d\n", +						__func__, res); +			} +		} +	} + +	if (connected) { +		return sfd; +	} + +	close(sfd); + +	return -1; +} + +int usbmuxd_disconnect(int sfd) +{ +	return close(sfd); +} + +int usbmuxd_send(int sfd, const char *data, uint32_t len, uint32_t *sent_bytes) +{ +	int num_sent; + +	if (sfd < 0) { +		return -EINVAL; +	} +	 +	num_sent = send(sfd, (void*)data, len, 0); +	if (num_sent < 0) { +		*sent_bytes = 0; +		fprintf(stderr, "%s: Error %d when sending: %s\n", __func__, num_sent, strerror(errno)); +		return num_sent; +	} else if ((uint32_t)num_sent < len) { +		fprintf(stderr, "%s: Warning: Did not send enough (only %d of %d)\n", __func__, num_sent, len); +	} + +	*sent_bytes = num_sent; + +	return 0; +} + +int usbmuxd_recv_timeout(int sfd, char *data, uint32_t len, uint32_t *recv_bytes, unsigned int timeout) +{ +	int num_recv = recv_buf_timeout(sfd, (void*)data, len, 0, timeout); +	if (num_recv < 0) { +		*recv_bytes = 0; +		return num_recv; +	} + +	*recv_bytes = num_recv; + +	return 0; +} + +int usbmuxd_recv(int sfd, char *data, uint32_t len, uint32_t *recv_bytes) +{ +	return usbmuxd_recv_timeout(sfd, data, len, recv_bytes, 5000); +} + | 
