diff options
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/idevicediagnostics.c | 235 |
1 files changed, 200 insertions, 35 deletions
diff --git a/tools/idevicediagnostics.c b/tools/idevicediagnostics.c index e0bcb48..93211c3 100644 --- a/tools/idevicediagnostics.c +++ b/tools/idevicediagnostics.c | |||
| @@ -31,13 +31,24 @@ | |||
| 31 | #include <libimobiledevice/lockdown.h> | 31 | #include <libimobiledevice/lockdown.h> |
| 32 | #include <libimobiledevice/diagnostics_relay.h> | 32 | #include <libimobiledevice/diagnostics_relay.h> |
| 33 | 33 | ||
| 34 | enum cmd_mode { | ||
| 35 | CMD_NONE = 0, | ||
| 36 | CMD_SLEEP, | ||
| 37 | CMD_RESTART, | ||
| 38 | CMD_SHUTDOWN, | ||
| 39 | CMD_DIAGNOSTICS, | ||
| 40 | CMD_MOBILEGESTALT, | ||
| 41 | CMD_IOREGISTRY | ||
| 42 | }; | ||
| 43 | |||
| 34 | static void print_xml(plist_t node) | 44 | static void print_xml(plist_t node) |
| 35 | { | 45 | { |
| 36 | char *xml = NULL; | 46 | char *xml = NULL; |
| 37 | uint32_t len = 0; | 47 | uint32_t len = 0; |
| 38 | plist_to_xml(node, &xml, &len); | 48 | plist_to_xml(node, &xml, &len); |
| 39 | if (xml) | 49 | if (xml) { |
| 40 | puts(xml); | 50 | puts(xml); |
| 51 | } | ||
| 41 | } | 52 | } |
| 42 | 53 | ||
| 43 | void print_usage(int argc, char **argv); | 54 | void print_usage(int argc, char **argv); |
| @@ -45,12 +56,17 @@ void print_usage(int argc, char **argv); | |||
| 45 | int main(int argc, char **argv) | 56 | int main(int argc, char **argv) |
| 46 | { | 57 | { |
| 47 | idevice_t device = NULL; | 58 | idevice_t device = NULL; |
| 48 | lockdownd_client_t lckd = NULL; | 59 | lockdownd_client_t lockdown_client = NULL; |
| 49 | diagnostics_relay_client_t diagc = NULL; | 60 | diagnostics_relay_client_t diagnostics_client = NULL; |
| 61 | lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; | ||
| 50 | uint16_t port = 0; | 62 | uint16_t port = 0; |
| 51 | int result = -1; | 63 | int result = -1; |
| 52 | int i; | 64 | int i; |
| 53 | char *udid = NULL; | 65 | char *udid = NULL; |
| 66 | int cmd = CMD_NONE; | ||
| 67 | char* cmd_arg = NULL; | ||
| 68 | plist_t node = NULL; | ||
| 69 | plist_t keys = NULL; | ||
| 54 | 70 | ||
| 55 | /* parse cmdline args */ | 71 | /* parse cmdline args */ |
| 56 | for (i = 1; i < argc; i++) { | 72 | for (i = 1; i < argc; i++) { |
| @@ -62,14 +78,81 @@ int main(int argc, char **argv) | |||
| 62 | i++; | 78 | i++; |
| 63 | if (!argv[i] || (strlen(argv[i]) != 40)) { | 79 | if (!argv[i] || (strlen(argv[i]) != 40)) { |
| 64 | print_usage(argc, argv); | 80 | print_usage(argc, argv); |
| 65 | return 0; | 81 | result = 0; |
| 82 | goto cleanup; | ||
| 66 | } | 83 | } |
| 67 | udid = strdup(argv[i]); | 84 | udid = strdup(argv[i]); |
| 68 | continue; | 85 | continue; |
| 69 | } | 86 | } |
| 70 | else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { | 87 | else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { |
| 71 | print_usage(argc, argv); | 88 | print_usage(argc, argv); |
| 72 | return 0; | 89 | result = 0; |
| 90 | goto cleanup; | ||
| 91 | } | ||
| 92 | else if (!strcmp(argv[i], "sleep")) { | ||
| 93 | cmd = CMD_SLEEP; | ||
| 94 | } | ||
| 95 | else if (!strcmp(argv[i], "restart")) { | ||
| 96 | cmd = CMD_RESTART; | ||
| 97 | } | ||
| 98 | else if (!strcmp(argv[i], "shutdown")) { | ||
| 99 | cmd = CMD_SHUTDOWN; | ||
| 100 | } | ||
| 101 | else if (!strcmp(argv[i], "diagnostics")) { | ||
| 102 | cmd = CMD_DIAGNOSTICS; | ||
| 103 | /* read type */ | ||
| 104 | i++; | ||
| 105 | if (!argv[i] || ((strcmp(argv[i], "All") != 0) && (strcmp(argv[i], "WiFi") != 0) && (strcmp(argv[i], "GasGauge") != 0) && (strcmp(argv[i], "NAND") != 0))) { | ||
| 106 | if (argv[i] == NULL) { | ||
| 107 | cmd_arg = strdup("All"); | ||
| 108 | continue; | ||
| 109 | } | ||
| 110 | |||
| 111 | if (!strncmp(argv[i], "-", 1)) { | ||
| 112 | cmd_arg = strdup("All"); | ||
| 113 | i--; | ||
| 114 | continue; | ||
| 115 | } | ||
| 116 | |||
| 117 | printf("Unknown TYPE %s\n", argv[i]); | ||
| 118 | print_usage(argc, argv); | ||
| 119 | goto cleanup; | ||
| 120 | } | ||
| 121 | |||
| 122 | cmd_arg = strdup(argv[i]); | ||
| 123 | continue; | ||
| 124 | } | ||
| 125 | else if (!strcmp(argv[i], "mobilegestalt")) { | ||
| 126 | cmd = CMD_MOBILEGESTALT; | ||
| 127 | /* read keys */ | ||
| 128 | i++; | ||
| 129 | |||
| 130 | if (!argv[i] || argv[i] == NULL || (!strncmp(argv[i], "-", 1))) { | ||
| 131 | printf("Please supply the key to query.\n"); | ||
| 132 | print_usage(argc, argv); | ||
| 133 | goto cleanup; | ||
| 134 | } | ||
| 135 | |||
| 136 | keys = plist_new_array(); | ||
| 137 | while(1) { | ||
| 138 | if (argv[i] && (strlen(argv[i]) >= 2) && (strncmp(argv[i], "-", 1) != 0)) { | ||
| 139 | plist_array_append_item(keys, plist_new_string(argv[i])); | ||
| 140 | i++; | ||
| 141 | } else { | ||
| 142 | i--; | ||
| 143 | break; | ||
| 144 | } | ||
| 145 | } | ||
| 146 | continue; | ||
| 147 | } | ||
| 148 | else if (!strcmp(argv[i], "ioreg")) { | ||
| 149 | cmd = CMD_IOREGISTRY; | ||
| 150 | /* read plane */ | ||
| 151 | i++; | ||
| 152 | if (argv[i]) { | ||
| 153 | cmd_arg = strdup(argv[i]); | ||
| 154 | } | ||
| 155 | continue; | ||
| 73 | } | 156 | } |
| 74 | else { | 157 | else { |
| 75 | print_usage(argc, argv); | 158 | print_usage(argc, argv); |
| @@ -77,58 +160,140 @@ int main(int argc, char **argv) | |||
| 77 | } | 160 | } |
| 78 | } | 161 | } |
| 79 | 162 | ||
| 163 | /* verify options */ | ||
| 164 | if (cmd == CMD_NONE) { | ||
| 165 | print_usage(argc, argv); | ||
| 166 | goto cleanup; | ||
| 167 | } | ||
| 168 | |||
| 80 | if (IDEVICE_E_SUCCESS != idevice_new(&device, udid)) { | 169 | if (IDEVICE_E_SUCCESS != idevice_new(&device, udid)) { |
| 81 | printf("No device found, is it plugged in?\n"); | 170 | printf("No device found, is it plugged in?\n"); |
| 82 | if (udid) { | 171 | goto cleanup; |
| 83 | free(udid); | ||
| 84 | } | ||
| 85 | return -1; | ||
| 86 | } | 172 | } |
| 173 | |||
| 87 | if (udid) { | 174 | if (udid) { |
| 88 | free(udid); | 175 | free(udid); |
| 89 | } | 176 | } |
| 90 | 177 | ||
| 91 | if (LOCKDOWN_E_SUCCESS != lockdownd_client_new_with_handshake(device, &lckd, NULL)) { | 178 | if (LOCKDOWN_E_SUCCESS != lockdownd_client_new_with_handshake(device, &lockdown_client, NULL)) { |
| 92 | idevice_free(device); | 179 | idevice_free(device); |
| 93 | printf("Exiting.\n"); | 180 | printf("Unable to connect to lockdownd.\n"); |
| 94 | return -1; | 181 | goto cleanup; |
| 95 | } | 182 | } |
| 96 | 183 | ||
| 97 | lockdownd_start_service(lckd, "com.apple.mobile.diagnostics_relay", &port); | 184 | /* attempt to use newer diagnostics service available on iOS 5 and later */ |
| 98 | lockdownd_client_free(lckd); | 185 | ret = lockdownd_start_service(lockdown_client, "com.apple.mobile.diagnostics_relay", &port); |
| 99 | if (port > 0) { | 186 | if (ret != LOCKDOWN_E_SUCCESS) { |
| 100 | if (diagnostics_relay_client_new(device, port, &diagc) != DIAGNOSTICS_RELAY_E_SUCCESS) { | 187 | /* attempt to use older diagnostics service */ |
| 188 | ret = lockdownd_start_service(lockdown_client, "com.apple.iosdiagnostics.relay", &port); | ||
| 189 | } | ||
| 190 | |||
| 191 | lockdownd_client_free(lockdown_client); | ||
| 192 | |||
| 193 | if ((ret == LOCKDOWN_E_SUCCESS) && (port > 0)) { | ||
| 194 | if (diagnostics_relay_client_new(device, port, &diagnostics_client) != DIAGNOSTICS_RELAY_E_SUCCESS) { | ||
| 101 | printf("Could not connect to diagnostics_relay!\n"); | 195 | printf("Could not connect to diagnostics_relay!\n"); |
| 102 | result = -1; | 196 | result = -1; |
| 103 | } else { | 197 | } else { |
| 104 | plist_t node = NULL; | 198 | switch (cmd) { |
| 105 | if (diagnostics_relay_request_diagnostics(diagc, DIAGNOSTICS_RELAY_REQUEST_TYPE_ALL, &node) != DIAGNOSTICS_RELAY_E_SUCCESS) { | 199 | case CMD_SLEEP: |
| 106 | printf("Unable to retrieve diagnostics"); | 200 | if (diagnostics_relay_sleep(diagnostics_client) == DIAGNOSTICS_RELAY_E_SUCCESS) { |
| 201 | printf("Putting device into deep sleep mode.\n"); | ||
| 202 | result = EXIT_SUCCESS; | ||
| 203 | } else { | ||
| 204 | printf("Failed to put device into deep sleep mode.\n"); | ||
| 205 | } | ||
| 206 | break; | ||
| 207 | case CMD_RESTART: | ||
| 208 | if (diagnostics_relay_restart(diagnostics_client, 0) == DIAGNOSTICS_RELAY_E_SUCCESS) { | ||
| 209 | printf("Restarting device.\n"); | ||
| 210 | result = EXIT_SUCCESS; | ||
| 211 | } else { | ||
| 212 | printf("Failed to restart device.\n"); | ||
| 213 | } | ||
| 214 | break; | ||
| 215 | case CMD_SHUTDOWN: | ||
| 216 | if (diagnostics_relay_shutdown(diagnostics_client, 0) == DIAGNOSTICS_RELAY_E_SUCCESS) { | ||
| 217 | printf("Shutting down device.\n"); | ||
| 218 | result = EXIT_SUCCESS; | ||
| 219 | } else { | ||
| 220 | printf("Failed to shutdown device.\n"); | ||
| 221 | } | ||
| 222 | break; | ||
| 223 | case CMD_MOBILEGESTALT: | ||
| 224 | if (diagnostics_relay_query_mobilegestalt(diagnostics_client, keys, &node) == DIAGNOSTICS_RELAY_E_SUCCESS) { | ||
| 225 | if (node) { | ||
| 226 | print_xml(node); | ||
| 227 | result = EXIT_SUCCESS; | ||
| 228 | } | ||
| 229 | } else { | ||
| 230 | printf("Unable to query mobilegestalt keys.\n"); | ||
| 231 | } | ||
| 232 | break; | ||
| 233 | case CMD_IOREGISTRY: | ||
| 234 | if (diagnostics_relay_query_ioregistry_plane(diagnostics_client, cmd_arg == NULL ? "": cmd_arg, &node) == DIAGNOSTICS_RELAY_E_SUCCESS) { | ||
| 235 | if (node) { | ||
| 236 | print_xml(node); | ||
| 237 | result = EXIT_SUCCESS; | ||
| 238 | } | ||
| 239 | } else { | ||
| 240 | printf("Unable to retrieve IORegistry from device.\n"); | ||
| 241 | } | ||
| 242 | break; | ||
| 243 | case CMD_DIAGNOSTICS: | ||
| 244 | default: | ||
| 245 | if (diagnostics_relay_request_diagnostics(diagnostics_client, cmd_arg, &node) == DIAGNOSTICS_RELAY_E_SUCCESS) { | ||
| 246 | if (node) { | ||
| 247 | print_xml(node); | ||
| 248 | result = EXIT_SUCCESS; | ||
| 249 | } | ||
| 250 | } else { | ||
| 251 | printf("Unable to retrieve diagnostics from device.\n"); | ||
| 252 | } | ||
| 253 | break; | ||
| 107 | } | 254 | } |
| 108 | if (node) { | 255 | |
| 109 | print_xml(node); | 256 | diagnostics_relay_goodbye(diagnostics_client); |
| 110 | plist_free(node); | 257 | diagnostics_relay_client_free(diagnostics_client); |
| 111 | } | ||
| 112 | diagnostics_relay_goodbye(diagc); | ||
| 113 | diagnostics_relay_client_free(diagc); | ||
| 114 | } | 258 | } |
| 115 | } else { | 259 | } else { |
| 116 | printf("Could not start diagnostics service!\n"); | 260 | printf("Could not start diagnostics service!\n"); |
| 117 | } | 261 | } |
| 262 | |||
| 118 | idevice_free(device); | 263 | idevice_free(device); |
| 119 | 264 | ||
| 265 | cleanup: | ||
| 266 | if (udid) { | ||
| 267 | free(udid); | ||
| 268 | } | ||
| 269 | if (node) { | ||
| 270 | plist_free(node); | ||
| 271 | } | ||
| 272 | if (keys) { | ||
| 273 | plist_free(keys); | ||
| 274 | } | ||
| 275 | if (cmd_arg) { | ||
| 276 | free(cmd_arg); | ||
| 277 | } | ||
| 120 | return result; | 278 | return result; |
| 121 | } | 279 | } |
| 122 | 280 | ||
| 123 | void print_usage(int argc, char **argv) | 281 | void print_usage(int argc, char **argv) |
| 124 | { | 282 | { |
| 125 | char *name = NULL; | 283 | char *name = NULL; |
| 126 | 284 | name = strrchr(argv[0], '/'); | |
| 127 | name = strrchr(argv[0], '/'); | 285 | printf("Usage: %s COMMAND [OPTIONS]\n", (name ? name + 1: argv[0])); |
| 128 | printf("Usage: %s [OPTIONS]\n", (name ? name + 1: argv[0])); | 286 | printf("Use diagnostics interface of a device running iOS 4 or later.\n\n"); |
| 129 | printf("Retrieves diagnostics information from a device.\n\n"); | 287 | printf(" Where COMMAND is one of:\n"); |
| 130 | printf(" -d, --debug\t\tenable communication debugging\n"); | 288 | printf(" diagnostics [TYPE]\t\tprint diagnostics information from device by TYPE (All, WiFi, GasGauge, NAND)\n"); |
| 131 | printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n"); | 289 | printf(" mobilegestalt KEY [...]\tprint mobilegestalt keys passed as arguments seperated by a space.\n"); |
| 132 | printf(" -h, --help\t\tprints usage information\n"); | 290 | printf(" ioreg [PLANE]\t\t\tprint IORegistry of device, optionally by PLANE (IODeviceTree, IOPower, IOService) (iOS 5+ only)\n"); |
| 133 | printf("\n"); | 291 | printf(" shutdown\t\t\tshutdown device\n"); |
| 292 | printf(" restart\t\t\trestart device\n"); | ||
| 293 | printf(" sleep\t\t\t\tput device into sleep mode (disconnects from host)\n\n"); | ||
| 294 | printf(" The following OPTIONS are accepted:\n"); | ||
| 295 | printf(" -d, --debug\t\tenable communication debugging\n"); | ||
| 296 | printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n"); | ||
| 297 | printf(" -h, --help\t\tprints usage information\n"); | ||
| 298 | printf("\n"); | ||
| 134 | } | 299 | } |
