summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/Makefile.am1
-rw-r--r--include/libimobiledevice/screenshotr.h54
-rw-r--r--src/Makefile.am1
-rw-r--r--src/screenshotr.c186
-rw-r--r--src/screenshotr.h31
-rw-r--r--tools/Makefile.am7
-rw-r--r--tools/idevicescreenshot.c111
7 files changed, 390 insertions, 1 deletions
diff --git a/include/Makefile.am b/include/Makefile.am
index 0cb3c50..9248e06 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -6,5 +6,6 @@ nobase_include_HEADERS = libimobiledevice/libimobiledevice.h \
6 libimobiledevice/installation_proxy.h \ 6 libimobiledevice/installation_proxy.h \
7 libimobiledevice/sbservices.h \ 7 libimobiledevice/sbservices.h \
8 libimobiledevice/mobile_image_mounter.h \ 8 libimobiledevice/mobile_image_mounter.h \
9 libimobiledevice/screenshotr.h \
9 libimobiledevice/mobilesync.h \ 10 libimobiledevice/mobilesync.h \
10 libimobiledevice/mobilebackup.h 11 libimobiledevice/mobilebackup.h
diff --git a/include/libimobiledevice/screenshotr.h b/include/libimobiledevice/screenshotr.h
new file mode 100644
index 0000000..077f50c
--- /dev/null
+++ b/include/libimobiledevice/screenshotr.h
@@ -0,0 +1,54 @@
1/**
2 * @file libimobiledevice/screenshotr.h
3 * @brief Screenshot service implementation
4 * \internal
5 *
6 * Copyright (c) 2010 Nikias Bassen All Rights Reserved.
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#ifndef ISCREENSHOTR_H
24#define ISCREENSHOTR_H
25
26#ifdef __cplusplus
27extern "C" {
28#endif
29
30#include <libimobiledevice/libimobiledevice.h>
31
32/* Error Codes */
33#define SCREENSHOTR_E_SUCCESS 0
34#define SCREENSHOTR_E_INVALID_ARG -1
35#define SCREENSHOTR_E_PLIST_ERROR -2
36#define SCREENSHOTR_E_MUX_ERROR -3
37#define SCREENSHOTR_E_BAD_VERSION -4
38
39#define SCREENSHOTR_E_UNKNOWN_ERROR -256
40
41typedef int16_t screenshotr_error_t;
42
43struct screenshotr_client_int;
44typedef struct screenshotr_client_int *screenshotr_client_t;
45
46screenshotr_error_t screenshotr_client_new(idevice_t device, uint16_t port, screenshotr_client_t * client);
47screenshotr_error_t screenshotr_client_free(screenshotr_client_t client);
48screenshotr_error_t screenshotr_take_screenshot(screenshotr_client_t client, char **imgdata, uint64_t *imgsize);
49
50#ifdef __cplusplus
51}
52#endif
53
54#endif
diff --git a/src/Makefile.am b/src/Makefile.am
index e847d7c..87fada0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -17,5 +17,6 @@ libimobiledevice_la_SOURCES = idevice.c idevice.h \
17 installation_proxy.c installation_proxy.h\ 17 installation_proxy.c installation_proxy.h\
18 sbservices.c sbservices.h\ 18 sbservices.c sbservices.h\
19 mobile_image_mounter.c mobile_image_mounter.h\ 19 mobile_image_mounter.c mobile_image_mounter.h\
20 screenshotr.c screenshotr.h\
20 mobilesync.c mobilesync.h\ 21 mobilesync.c mobilesync.h\
21 mobilebackup.c mobilebackup.h 22 mobilebackup.c mobilebackup.h
diff --git a/src/screenshotr.c b/src/screenshotr.c
new file mode 100644
index 0000000..f8866d0
--- /dev/null
+++ b/src/screenshotr.c
@@ -0,0 +1,186 @@
1/*
2 * screenshotr.c
3 * com.apple.mobile.screenshotr implementation.
4 *
5 * Copyright (c) 2010 Nikias Bassen All Rights Reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include <plist/plist.h>
23#include <string.h>
24#include <stdlib.h>
25#include <arpa/inet.h>
26
27#include "screenshotr.h"
28#include "device_link_service.h"
29#include "debug.h"
30
31#define SCREENSHOTR_VERSION_INT1 100
32#define SCREENSHOTR_VERSION_INT2 0
33
34/**
35 * Convert a device_link_service_error_t value to a screenshotr_error_t value.
36 * Used internally to get correct error codes.
37 *
38 * @param err An device_link_service_error_t error code
39 *
40 * @return A matching screenshotr_error_t error code,
41 * SCREENSHOTR_E_UNKNOWN_ERROR otherwise.
42 */
43static screenshotr_error_t screenshotr_error(device_link_service_error_t err)
44{
45 switch (err) {
46 case DEVICE_LINK_SERVICE_E_SUCCESS:
47 return SCREENSHOTR_E_SUCCESS;
48 case DEVICE_LINK_SERVICE_E_INVALID_ARG:
49 return SCREENSHOTR_E_INVALID_ARG;
50 case DEVICE_LINK_SERVICE_E_PLIST_ERROR:
51 return SCREENSHOTR_E_PLIST_ERROR;
52 case DEVICE_LINK_SERVICE_E_MUX_ERROR:
53 return SCREENSHOTR_E_MUX_ERROR;
54 case DEVICE_LINK_SERVICE_E_BAD_VERSION:
55 return SCREENSHOTR_E_BAD_VERSION;
56 default:
57 break;
58 }
59 return SCREENSHOTR_E_UNKNOWN_ERROR;
60}
61
62/**
63 * Makes a connection to the screenshotr service on the device.
64 *
65 * @param device The device to connect to.
66 * @param port Destination port (usually given by lockdownd_start_service).
67 * @param client Pointer that will be set to a newly allocated
68 * screenshotr_client_t upon successful return.
69 *
70 * @return SCREENSHOTR_E_SUCCESS on success, SCREENSHOTR_E_INVALID ARG if one
71 * or more parameters are invalid, or SCREENSHOTR_E_CONN_FAILED if the
72 * connection to the device could not be established.
73 */
74screenshotr_error_t screenshotr_client_new(idevice_t device, uint16_t port,
75 screenshotr_client_t * client)
76{
77 if (!device || port == 0 || !client || *client)
78 return SCREENSHOTR_E_INVALID_ARG;
79
80 device_link_service_client_t dlclient = NULL;
81 screenshotr_error_t ret = screenshotr_error(device_link_service_client_new(device, port, &dlclient));
82 if (ret != SCREENSHOTR_E_SUCCESS) {
83 return ret;
84 }
85
86 screenshotr_client_t client_loc = (screenshotr_client_t) malloc(sizeof(struct screenshotr_client_int));
87 client_loc->parent = dlclient;
88
89 /* perform handshake */
90 ret = screenshotr_error(device_link_service_version_exchange(dlclient, SCREENSHOTR_VERSION_INT1, SCREENSHOTR_VERSION_INT2));
91 if (ret != SCREENSHOTR_E_SUCCESS) {
92 debug_info("version exchange failed, error %d", ret);
93 screenshotr_client_free(client_loc);
94 return ret;
95 }
96
97 *client = client_loc;
98
99 return ret;
100}
101
102/**
103 * Disconnects a screenshotr client from the device.
104 *
105 * @param client The client to disconnect.
106 *
107 * @return SCREENSHOTR_E_SUCCESS on success, or SCREENSHOTR_E_INVALID_ARG
108 * if client is NULL.
109 */
110screenshotr_error_t screenshotr_client_free(screenshotr_client_t client)
111{
112 if (!client)
113 return SCREENSHOTR_E_INVALID_ARG;
114 device_link_service_disconnect(client->parent);
115 screenshotr_error_t err = screenshotr_error(device_link_service_client_free(client->parent));
116 free(client);
117 return err;
118}
119
120/**
121 * Get a screen shot from the connected device.
122 *
123 * @param client The connection screenshotr service client.
124 * @param imgdata Pointer that will point to a newly allocated buffer
125 * containing TIFF image data upon successful return. It is up to the
126 * caller to free the memory.
127 * @param imgsize Pointer to a uint64_t that will be set to the size of the
128 * buffer imgdata points to upon successful return.
129 *
130 * @return SCREENSHOTR_E_SUCCESS on success, SCREENSHOTR_E_INVALID_ARG if
131 * one or more parameters are invalid, or another error code if an
132 * error occured.
133 */
134screenshotr_error_t screenshotr_take_screenshot(screenshotr_client_t client, char **imgdata, uint64_t *imgsize)
135{
136 if (!client || !client->parent || !imgdata)
137 return SCREENSHOTR_E_INVALID_ARG;
138
139 screenshotr_error_t res = SCREENSHOTR_E_UNKNOWN_ERROR;
140
141 plist_t dict = plist_new_dict();
142 plist_dict_insert_item(dict, "MessageType", plist_new_string("ScreenShotRequest"));
143
144 res = screenshotr_error(device_link_service_process_message(client->parent, dict));
145 plist_free(dict);
146 if (res != SCREENSHOTR_E_SUCCESS) {
147 debug_info("could not send plist, error %d", res);
148 return res;
149 }
150
151 dict = NULL;
152 res = screenshotr_error(device_link_service_get_process_message(client->parent, &dict));
153 if (res != SCREENSHOTR_E_SUCCESS) {
154 debug_info("could not get screenshot data, error %d", res);
155 goto leave;
156 }
157 if (!dict) {
158 debug_info("did not receive screenshot data!");
159 res = SCREENSHOTR_E_PLIST_ERROR;
160 goto leave;
161 }
162
163 plist_t node = plist_dict_get_item(dict, "MessageType");
164 char *strval = NULL;
165 plist_get_string_val(node, &strval);
166 if (!strval || strcmp(strval, "ScreenShotReply")) {
167 debug_info("invalid screenshot data received!");
168 res = SCREENSHOTR_E_PLIST_ERROR;
169 goto leave;
170 }
171 node = plist_dict_get_item(dict, "ScreenShotData");
172 if (!node || plist_get_node_type(node) != PLIST_DATA) {
173 debug_info("no PNG data received!");
174 res = SCREENSHOTR_E_PLIST_ERROR;
175 goto leave;
176 }
177
178 plist_get_data_val(node, imgdata, imgsize);
179 res = SCREENSHOTR_E_SUCCESS;
180
181leave:
182 if (dict)
183 plist_free(dict);
184
185 return res;
186}
diff --git a/src/screenshotr.h b/src/screenshotr.h
new file mode 100644
index 0000000..5f842a7
--- /dev/null
+++ b/src/screenshotr.h
@@ -0,0 +1,31 @@
1/*
2 * screenshotr.h
3 * com.apple.mobile.screenshotr definitions.
4 *
5 * Copyright (c) 2010 Nikias Bassen All Rights Reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21#ifndef SCREENSHOTR_H
22#define SCREENSHOTR_H
23
24#include "libimobiledevice/screenshotr.h"
25#include "device_link_service.h"
26
27struct screenshotr_client_int {
28 device_link_service_client_t parent;
29};
30
31#endif
diff --git a/tools/Makefile.am b/tools/Makefile.am
index b4fa69e..472ebab 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -3,7 +3,7 @@ INCLUDES = -I$(top_srcdir)/include
3AM_CFLAGS = $(GLOBAL_CFLAGS) $(libglib2_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libgthread2_CFLAGS) $(LFS_CFLAGS) 3AM_CFLAGS = $(GLOBAL_CFLAGS) $(libglib2_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libgthread2_CFLAGS) $(LFS_CFLAGS)
4AM_LDFLAGS = $(libglib2_LIBS) $(libgnutls_LIBS) $(libtasn1_LIBS) $(libgthread2_LIBS) 4AM_LDFLAGS = $(libglib2_LIBS) $(libgnutls_LIBS) $(libtasn1_LIBS) $(libgthread2_LIBS)
5 5
6bin_PROGRAMS = idevice_id ideviceinfo idevicesyslog idevicebackup ideviceimagemounter 6bin_PROGRAMS = idevice_id ideviceinfo idevicesyslog idevicebackup ideviceimagemounter idevicescreenshot
7 7
8ideviceinfo_SOURCES = ideviceinfo.c 8ideviceinfo_SOURCES = ideviceinfo.c
9ideviceinfo_CFLAGS = $(AM_CFLAGS) 9ideviceinfo_CFLAGS = $(AM_CFLAGS)
@@ -29,3 +29,8 @@ ideviceimagemounter_SOURCES = ideviceimagemounter.c
29ideviceimagemounter_CFLAGS = $(AM_CFLAGS) 29ideviceimagemounter_CFLAGS = $(AM_CFLAGS)
30ideviceimagemounter_LDFLAGS = $(AM_LDFLAGS) 30ideviceimagemounter_LDFLAGS = $(AM_LDFLAGS)
31ideviceimagemounter_LDADD = ../src/libimobiledevice.la 31ideviceimagemounter_LDADD = ../src/libimobiledevice.la
32
33idevicescreenshot_SOURCES = idevicescreenshot.c
34idevicescreenshot_CFLAGS = $(AM_CFLAGS)
35idevicescreenshot_LDFLAGS = $(AM_LDFLAGS)
36idevicescreenshot_LDADD = ../src/libimobiledevice.la
diff --git a/tools/idevicescreenshot.c b/tools/idevicescreenshot.c
new file mode 100644
index 0000000..ca4454c
--- /dev/null
+++ b/tools/idevicescreenshot.c
@@ -0,0 +1,111 @@
1#include <stdio.h>
2#include <string.h>
3#include <stdlib.h>
4#include <errno.h>
5
6#include <libimobiledevice/libimobiledevice.h>
7#include <libimobiledevice/lockdown.h>
8#include <libimobiledevice/screenshotr.h>
9
10void print_usage(int argc, char **argv);
11
12int main(int argc, char **argv)
13{
14 idevice_t device = NULL;
15 lockdownd_client_t lckd = NULL;
16 screenshotr_client_t shotr = NULL;
17 uint16_t port = 0;
18 int result = -1;
19 int i;
20 char *uuid = NULL;
21
22 /* parse cmdline args */
23 for (i = 1; i < argc; i++) {
24 if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) {
25 idevice_set_debug_level(1);
26 continue;
27 }
28 else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--uuid")) {
29 i++;
30 if (!argv[i] || (strlen(argv[i]) != 40)) {
31 print_usage(argc, argv);
32 return 0;
33 }
34 uuid = strdup(argv[i]);
35 continue;
36 }
37 else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
38 print_usage(argc, argv);
39 return 0;
40 }
41 else {
42 print_usage(argc, argv);
43 return 0;
44 }
45 }
46
47 if (IDEVICE_E_SUCCESS != idevice_new(&device, uuid)) {
48 printf("No device found, is it plugged in?\n");
49 if (uuid) {
50 free(uuid);
51 }
52 return -1;
53 }
54 if (uuid) {
55 free(uuid);
56 }
57
58 if (LOCKDOWN_E_SUCCESS != lockdownd_client_new_with_handshake(device, &lckd, NULL)) {
59 idevice_free(device);
60 printf("Exiting.\n");
61 return -1;
62 }
63
64 lockdownd_start_service(lckd, "com.apple.mobile.screenshotr", &port);
65 lockdownd_client_free(lckd);
66 if (port > 0) {
67 if (screenshotr_client_new(device, port, &shotr) != SCREENSHOTR_E_SUCCESS) {
68 printf("Could not connect to screenshotr!\n");
69 } else {
70 char *imgdata = NULL;
71 uint64_t imgsize = 0;
72 if (screenshotr_take_screenshot(shotr, &imgdata, &imgsize) == SCREENSHOTR_E_SUCCESS) {
73 FILE *f = fopen("screenshot.tiff", "w");
74 if (f) {
75 if (fwrite(imgdata, 1, (size_t)imgsize, f) == (size_t)imgsize) {
76 printf("Screenshot saved to screenshot.tiff\n");
77 result = 0;
78 } else {
79 printf("Could not save screenshot to file!\n");
80 }
81 fclose(f);
82 } else {
83 printf("Could not open screenshot.tiff for writing: %s\n", strerror(errno));
84 }
85 } else {
86 printf("Could not get screenshot!\n");
87 }
88 screenshotr_client_free(shotr);
89 }
90 } else {
91 printf("Could not start screenshotr service! Remember that you have to mount the Developer disk image on your device if you want to use the screenshotr service.\n");
92 }
93 idevice_free(device);
94
95 return result;
96}
97
98void print_usage(int argc, char **argv)
99{
100 char *name = NULL;
101
102 name = strrchr(argv[0], '/');
103 printf("Usage: %s [OPTIONS]\n", (name ? name + 1: argv[0]));
104 printf("Gets a screenshot from the connected iPhone/iPod Touch.\n");
105 printf("NOTE: A mounted developer disk image is required on the device, otherwise\n");
106 printf(" the screenshotr service is not available.\n\n");
107 printf(" -d, --debug\t\tenable communication debugging\n");
108 printf(" -u, --uuid UUID\ttarget specific device by its 40-digit device UUID\n");
109 printf(" -h, --help\t\tprints usage information\n");
110 printf("\n");
111}