diff options
| -rw-r--r-- | Makefile | 4 | ||||
| -rw-r--r-- | include/libirecovery.h | 19 | ||||
| -rw-r--r-- | src/irecovery.c | 60 | ||||
| -rw-r--r-- | src/libirecovery.c | 34 |
4 files changed, 90 insertions, 27 deletions
| @@ -1,4 +1,4 @@ | |||
| 1 | all: static | 1 | all: |
| 2 | @echo "Please choose either macosx, linux, or windows" | 2 | @echo "Please choose either macosx, linux, or windows" |
| 3 | 3 | ||
| 4 | static: | 4 | static: |
| @@ -20,7 +20,7 @@ windows: | |||
| 20 | gcc -o irecovery irecovery.c -I. -lirecovery | 20 | gcc -o irecovery irecovery.c -I. -lirecovery |
| 21 | 21 | ||
| 22 | clean: | 22 | clean: |
| 23 | rm -rf irecovery libirecovery.o libirecovery.so | 23 | rm -rf irecovery libirecovery.o libirecovery.so libirecovery.a |
| 24 | 24 | ||
| 25 | 25 | ||
| 26 | 26 | ||
diff --git a/include/libirecovery.h b/include/libirecovery.h index 342e99b..b489011 100644 --- a/include/libirecovery.h +++ b/include/libirecovery.h | |||
| @@ -18,14 +18,15 @@ | |||
| 18 | 18 | ||
| 19 | #include <libusb-1.0/libusb.h> | 19 | #include <libusb-1.0/libusb.h> |
| 20 | 20 | ||
| 21 | #define kAppleVendorId 0x05AC | 21 | #define IRECV_SUCCESS 0 |
| 22 | 22 | #define IRECV_ERROR_NO_DEVICE -1 | |
| 23 | #define IRECV_SUCCESS 0 | 23 | #define IRECV_ERROR_OUT_OF_MEMORY -2 |
| 24 | #define IRECV_ERROR_NO_DEVICE -1 | 24 | #define IRECV_ERROR_UNABLE_TO_CONNECT -3 |
| 25 | #define IRECV_ERROR_OUT_OF_MEMORY -2 | 25 | #define IRECV_ERROR_INVALID_INPUT -4 |
| 26 | #define IRECV_ERROR_UNABLE_TO_CONNECT -3 | 26 | #define IRECV_ERROR_UNKNOWN -5 |
| 27 | 27 | ||
| 28 | enum { | 28 | enum { |
| 29 | kAppleId = 0x05AC, | ||
| 29 | kKernelMode = 0x1294, | 30 | kKernelMode = 0x1294, |
| 30 | kRecoveryMode = 0x1281, | 31 | kRecoveryMode = 0x1281, |
| 31 | kDfuMode = 0x1227 | 32 | kDfuMode = 0x1227 |
| @@ -37,9 +38,11 @@ typedef struct { | |||
| 37 | struct libusb_device_handle* handle; | 38 | struct libusb_device_handle* handle; |
| 38 | } irecv_device; | 39 | } irecv_device; |
| 39 | 40 | ||
| 40 | int irecv_init(irecv_device** device); | 41 | void irecv_set_debug(int level); |
| 41 | int irecv_open(irecv_device* device); | 42 | int irecv_open(irecv_device* device); |
| 43 | int irecv_exit(irecv_device* device); | ||
| 44 | int irecv_init(irecv_device** device); | ||
| 42 | int irecv_reset(irecv_device* device); | 45 | int irecv_reset(irecv_device* device); |
| 43 | int irecv_close(irecv_device* device); | 46 | int irecv_close(irecv_device* device); |
| 44 | int irecv_exit(irecv_device* device); | 47 | int irecv_command(irecv_device* device, const char* command); |
| 45 | 48 | ||
diff --git a/src/irecovery.c b/src/irecovery.c index 90f975b..51320a5 100644 --- a/src/irecovery.c +++ b/src/irecovery.c | |||
| @@ -17,9 +17,50 @@ | |||
| 17 | **/ | 17 | **/ |
| 18 | 18 | ||
| 19 | #include <stdio.h> | 19 | #include <stdio.h> |
| 20 | #include <stdlib.h> | ||
| 21 | #include <unistd.h> | ||
| 20 | #include <libirecovery.h> | 22 | #include <libirecovery.h> |
| 21 | 23 | ||
| 24 | enum { | ||
| 25 | kResetDevice, kSendCommand | ||
| 26 | }; | ||
| 27 | |||
| 28 | void print_usage() { | ||
| 29 | printf("iRecovery - iDevice Recovery Utility\n"); | ||
| 30 | printf("Usage: ./irecovery [args]\n"); | ||
| 31 | exit(1); | ||
| 32 | } | ||
| 33 | |||
| 22 | int main(int argc, char** argv) { | 34 | int main(int argc, char** argv) { |
| 35 | int opt = 0; | ||
| 36 | int action = 0; | ||
| 37 | char* argument = NULL; | ||
| 38 | if(argc == 1) print_usage(); | ||
| 39 | while ((opt = getopt(argc, argv, "dhrc:f:")) > 0) { | ||
| 40 | switch (opt) { | ||
| 41 | case 'd': | ||
| 42 | irecv_set_debug(1); | ||
| 43 | break; | ||
| 44 | |||
| 45 | case 'h': | ||
| 46 | print_usage(); | ||
| 47 | break; | ||
| 48 | |||
| 49 | case 'r': | ||
| 50 | action = kResetDevice; | ||
| 51 | break; | ||
| 52 | |||
| 53 | case 'c': | ||
| 54 | argument = optarg; | ||
| 55 | action = kSendCommand; | ||
| 56 | break; | ||
| 57 | |||
| 58 | default: | ||
| 59 | fprintf(stderr, "Unknown argument\n"); | ||
| 60 | break; | ||
| 61 | } | ||
| 62 | } | ||
| 63 | |||
| 23 | irecv_device* device = NULL; | 64 | irecv_device* device = NULL; |
| 24 | if(irecv_init(&device) < 0) { | 65 | if(irecv_init(&device) < 0) { |
| 25 | fprintf(stderr, "Unable to initialize libirecovery\n"); | 66 | fprintf(stderr, "Unable to initialize libirecovery\n"); |
| @@ -31,27 +72,20 @@ int main(int argc, char** argv) { | |||
| 31 | return -1; | 72 | return -1; |
| 32 | } | 73 | } |
| 33 | 74 | ||
| 34 | switch (device->mode) { | 75 | switch(action) { |
| 35 | case kRecoveryMode: | 76 | case kResetDevice: |
| 36 | printf("Found device in recovery mode\n"); | 77 | irecv_reset(device); |
| 37 | break; | 78 | break; |
| 38 | 79 | ||
| 39 | case kDfuMode: | 80 | case kSendCommand: |
| 40 | printf("Found device in DFU mode\n"); | 81 | irecv_command(device, argument); |
| 41 | break; | ||
| 42 | |||
| 43 | case kKernelMode: | ||
| 44 | printf("Found device in kernel mode\n"); | ||
| 45 | break; | 82 | break; |
| 46 | 83 | ||
| 47 | default: | 84 | default: |
| 48 | printf("No device found\n"); | 85 | fprintf(stderr, "Unknown action\n"); |
| 49 | break; | 86 | break; |
| 50 | } | 87 | } |
| 51 | 88 | ||
| 52 | printf("Sending USB reset...\n"); | ||
| 53 | irecv_reset(device); | ||
| 54 | |||
| 55 | irecv_exit(device); | 89 | irecv_exit(device); |
| 56 | return 0; | 90 | return 0; |
| 57 | } | 91 | } |
diff --git a/src/libirecovery.c b/src/libirecovery.c index a5b5c84..85967ec 100644 --- a/src/libirecovery.c +++ b/src/libirecovery.c | |||
| @@ -23,14 +23,13 @@ | |||
| 23 | 23 | ||
| 24 | #include "libirecovery.h" | 24 | #include "libirecovery.h" |
| 25 | 25 | ||
| 26 | static unsigned int debug = 1; | 26 | static unsigned int irecv_debug = 0; |
| 27 | 27 | ||
| 28 | int irecv_init(irecv_device** p_device) { | 28 | int irecv_init(irecv_device** p_device) { |
| 29 | struct libusb_context* usb_context = NULL; | 29 | struct libusb_context* usb_context = NULL; |
| 30 | 30 | ||
| 31 | libusb_init(&usb_context); | 31 | libusb_init(&usb_context); |
| 32 | if (debug) | 32 | if (irecv_debug) libusb_set_debug(usb_context, 3); |
| 33 | libusb_set_debug(usb_context, 3); | ||
| 34 | 33 | ||
| 35 | irecv_device* device = (irecv_device*) malloc(sizeof(irecv_device)); | 34 | irecv_device* device = (irecv_device*) malloc(sizeof(irecv_device)); |
| 36 | if (device == NULL) { | 35 | if (device == NULL) { |
| @@ -60,7 +59,7 @@ int irecv_open(irecv_device* device) { | |||
| 60 | for (i = 0; i < usb_device_count; i++) { | 59 | for (i = 0; i < usb_device_count; i++) { |
| 61 | usb_device = usb_device_list[i]; | 60 | usb_device = usb_device_list[i]; |
| 62 | libusb_get_device_descriptor(usb_device, &usb_descriptor); | 61 | libusb_get_device_descriptor(usb_device, &usb_descriptor); |
| 63 | if (usb_descriptor.idVendor == kAppleVendorId) { | 62 | if (usb_descriptor.idVendor == kAppleId) { |
| 64 | 63 | ||
| 65 | libusb_open(usb_device, &usb_handle); | 64 | libusb_open(usb_device, &usb_handle); |
| 66 | if (usb_handle == NULL) { | 65 | if (usb_handle == NULL) { |
| @@ -115,3 +114,30 @@ int irecv_exit(irecv_device* device) { | |||
| 115 | 114 | ||
| 116 | return IRECV_SUCCESS; | 115 | return IRECV_SUCCESS; |
| 117 | } | 116 | } |
| 117 | |||
| 118 | void irecv_set_debug(int level) { | ||
| 119 | printf("Debug has been set to %d\n", level); | ||
| 120 | irecv_debug = level; | ||
| 121 | } | ||
| 122 | |||
| 123 | int irecv_command(irecv_device* device, const char* command) { | ||
| 124 | if(device == NULL || device->handle == NULL) { | ||
| 125 | return IRECV_ERROR_NO_DEVICE; | ||
| 126 | } | ||
| 127 | |||
| 128 | ssize_t length = strlen(command); | ||
| 129 | if(length >= 0x100) { | ||
| 130 | return IRECV_ERROR_INVALID_INPUT; | ||
| 131 | } | ||
| 132 | |||
| 133 | int ret = libusb_control_transfer(device->handle, 0x40, 0, 0, 0, (unsigned char*) command, length+1, 100); | ||
| 134 | if(ret < 0) { | ||
| 135 | return IRECV_ERROR_UNKNOWN; | ||
| 136 | } | ||
| 137 | |||
| 138 | return IRECV_SUCCESS; | ||
| 139 | } | ||
| 140 | |||
| 141 | int irecv_upload(irecv_device* device, const char* filename) { | ||
| 142 | return IRECV_SUCCESS; | ||
| 143 | } | ||
