diff options
| author | 2010-05-13 15:10:40 -0400 | |
|---|---|---|
| committer | 2010-05-13 15:10:40 -0400 | |
| commit | a814b04770dc83774cd705d2fc8993f24e504a01 (patch) | |
| tree | 3354669aab557d16eea95373538152c311142ca4 | |
| parent | 520c99d33e18009660f30bd38b31a2f1cd432fe6 (diff) | |
| download | libirecovery-a814b04770dc83774cd705d2fc8993f24e504a01.tar.gz libirecovery-a814b04770dc83774cd705d2fc8993f24e504a01.tar.bz2 | |
Implemented irecv_get_status() to return current iphone usb "state".
Implemented irecv_send_buffer() to upload a buffer to the device load address.
Implemented irecv_send_file() to read a file into memory and pass the buffer into irecv_send_buffer()
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | include/libirecovery.h | 7 | ||||
| -rw-r--r-- | src/irecovery.c | 15 | ||||
| -rw-r--r-- | src/libirecovery.c | 150 |
4 files changed, 166 insertions, 8 deletions
| @@ -1,4 +1,4 @@ | |||
| 1 | all: | 1 | all: static |
| 2 | @echo "Please choose either macosx, linux, or windows" | 2 | @echo "Please choose either macosx, linux, or windows" |
| 3 | 3 | ||
| 4 | static: | 4 | static: |
diff --git a/include/libirecovery.h b/include/libirecovery.h index b489011..801ad88 100644 --- a/include/libirecovery.h +++ b/include/libirecovery.h | |||
| @@ -24,6 +24,9 @@ | |||
| 24 | #define IRECV_ERROR_UNABLE_TO_CONNECT -3 | 24 | #define IRECV_ERROR_UNABLE_TO_CONNECT -3 |
| 25 | #define IRECV_ERROR_INVALID_INPUT -4 | 25 | #define IRECV_ERROR_INVALID_INPUT -4 |
| 26 | #define IRECV_ERROR_UNKNOWN -5 | 26 | #define IRECV_ERROR_UNKNOWN -5 |
| 27 | #define IRECV_ERROR_FILE_NOT_FOUND -6 | ||
| 28 | #define IRECV_ERROR_USB_UPLOAD -7 | ||
| 29 | #define IRECV_ERROR_USB_STATUS -8 | ||
| 27 | 30 | ||
| 28 | enum { | 31 | enum { |
| 29 | kAppleId = 0x05AC, | 32 | kAppleId = 0x05AC, |
| @@ -44,5 +47,5 @@ int irecv_exit(irecv_device* device); | |||
| 44 | int irecv_init(irecv_device** device); | 47 | int irecv_init(irecv_device** device); |
| 45 | int irecv_reset(irecv_device* device); | 48 | int irecv_reset(irecv_device* device); |
| 46 | int irecv_close(irecv_device* device); | 49 | int irecv_close(irecv_device* device); |
| 47 | int irecv_command(irecv_device* device, const char* command); | 50 | int irecv_send_file(irecv_device* device, const char* filename); |
| 48 | 51 | int irecv_send_command(irecv_device* device, const char* command); | |
diff --git a/src/irecovery.c b/src/irecovery.c index 51320a5..3091319 100644 --- a/src/irecovery.c +++ b/src/irecovery.c | |||
| @@ -22,7 +22,7 @@ | |||
| 22 | #include <libirecovery.h> | 22 | #include <libirecovery.h> |
| 23 | 23 | ||
| 24 | enum { | 24 | enum { |
| 25 | kResetDevice, kSendCommand | 25 | kResetDevice, kSendCommand, kSendFile |
| 26 | }; | 26 | }; |
| 27 | 27 | ||
| 28 | void print_usage() { | 28 | void print_usage() { |
| @@ -51,8 +51,13 @@ int main(int argc, char** argv) { | |||
| 51 | break; | 51 | break; |
| 52 | 52 | ||
| 53 | case 'c': | 53 | case 'c': |
| 54 | argument = optarg; | ||
| 55 | action = kSendCommand; | 54 | action = kSendCommand; |
| 55 | argument = optarg; | ||
| 56 | break; | ||
| 57 | |||
| 58 | case 'f': | ||
| 59 | action = kSendFile; | ||
| 60 | argument = optarg; | ||
| 56 | break; | 61 | break; |
| 57 | 62 | ||
| 58 | default: | 63 | default: |
| @@ -77,8 +82,12 @@ int main(int argc, char** argv) { | |||
| 77 | irecv_reset(device); | 82 | irecv_reset(device); |
| 78 | break; | 83 | break; |
| 79 | 84 | ||
| 85 | case kSendFile: | ||
| 86 | irecv_send_file(device, argument); | ||
| 87 | break; | ||
| 88 | |||
| 80 | case kSendCommand: | 89 | case kSendCommand: |
| 81 | irecv_command(device, argument); | 90 | irecv_send_command(device, argument); |
| 82 | break; | 91 | break; |
| 83 | 92 | ||
| 84 | default: | 93 | default: |
diff --git a/src/libirecovery.c b/src/libirecovery.c index 85967ec..e3d6eb6 100644 --- a/src/libirecovery.c +++ b/src/libirecovery.c | |||
| @@ -120,7 +120,7 @@ void irecv_set_debug(int level) { | |||
| 120 | irecv_debug = level; | 120 | irecv_debug = level; |
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | int irecv_command(irecv_device* device, const char* command) { | 123 | int irecv_send_command(irecv_device* device, const char* command) { |
| 124 | if(device == NULL || device->handle == NULL) { | 124 | if(device == NULL || device->handle == NULL) { |
| 125 | return IRECV_ERROR_NO_DEVICE; | 125 | return IRECV_ERROR_NO_DEVICE; |
| 126 | } | 126 | } |
| @@ -138,6 +138,152 @@ int irecv_command(irecv_device* device, const char* command) { | |||
| 138 | return IRECV_SUCCESS; | 138 | return IRECV_SUCCESS; |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | int irecv_upload(irecv_device* device, const char* filename) { | 141 | int irecv_send_file(irecv_device* device, const char* filename) { |
| 142 | FILE* file = fopen(filename, "rb"); | ||
| 143 | if (file == NULL) { | ||
| 144 | return IRECV_ERROR_FILE_NOT_FOUND; | ||
| 145 | } | ||
| 146 | |||
| 147 | fseek(file, 0, SEEK_END); | ||
| 148 | int length = ftell(file); | ||
| 149 | fseek(file, 0, SEEK_SET); | ||
| 150 | |||
| 151 | unsigned char* buffer = (unsigned char*) malloc(length); | ||
| 152 | if (buffer == NULL) { | ||
| 153 | fclose(file); | ||
| 154 | return IRECV_ERROR_OUT_OF_MEMORY; | ||
| 155 | } | ||
| 156 | |||
| 157 | int bytes = fread(buffer, 1, length, file); | ||
| 158 | fclose(file); | ||
| 159 | |||
| 160 | if(bytes != length) { | ||
| 161 | free(buffer); | ||
| 162 | return IRECV_ERROR_UNKNOWN; | ||
| 163 | } | ||
| 164 | |||
| 165 | return irecv_send_buffer(device, buffer, length); | ||
| 166 | } | ||
| 167 | |||
| 168 | unsigned int irecv_get_status(irecv_device* device) { | ||
| 169 | unsigned char status[6]; | ||
| 170 | memset(status, '\0', 6); | ||
| 171 | if(libusb_control_transfer(device->handle, 0xA1, 3, 0, 0, status, 6, 500) != 6) { | ||
| 172 | return IRECV_ERROR_USB_STATUS; | ||
| 173 | } | ||
| 174 | return (unsigned int) status[4]; | ||
| 175 | } | ||
| 176 | |||
| 177 | int irecv_send_buffer(irecv_device* device, unsigned char* buffer, int length) { | ||
| 178 | int packets = length / 0x800; | ||
| 179 | if (length % 0x800) { | ||
| 180 | packets++; | ||
| 181 | } | ||
| 182 | |||
| 183 | int last = length % 0x800; | ||
| 184 | if (!last) { | ||
| 185 | last = 0x800; | ||
| 186 | } | ||
| 187 | |||
| 188 | int i = 0; | ||
| 189 | char status[6]; | ||
| 190 | for (i = 0; i < packets; i++) { | ||
| 191 | int size = i + 1 < packets ? 0x800 : last; | ||
| 192 | int bytes = libusb_control_transfer(device->handle, 0x21, 1, i, 0, &buffer[i * 0x800], size, 500); | ||
| 193 | if (bytes != size) { | ||
| 194 | free(buffer); | ||
| 195 | return IRECV_ERROR_USB_UPLOAD; | ||
| 196 | } | ||
| 197 | |||
| 198 | if (irecv_get_status(device) != 5) { | ||
| 199 | free(buffer); | ||
| 200 | return IRECV_ERROR_USB_STATUS; | ||
| 201 | } | ||
| 202 | } | ||
| 203 | |||
| 204 | libusb_control_transfer(device->handle, 0x21, 1, i, 0, buffer, 0, 1000); | ||
| 205 | for (i = 6; i <= 8; i++) { | ||
| 206 | if (irecv_get_status(device) != i) { | ||
| 207 | free(buffer); | ||
| 208 | return IRECV_ERROR_USB_STATUS; | ||
| 209 | } | ||
| 210 | } | ||
| 211 | |||
| 212 | free(buffer); | ||
| 142 | return IRECV_SUCCESS; | 213 | return IRECV_SUCCESS; |
| 143 | } | 214 | } |
| 215 | |||
| 216 | /* | ||
| 217 | int send_file(struct libusb_device_handle *handle, const char* filename, int loadOffset) { | ||
| 218 | FILE* file = fopen(filename, "rb"); | ||
| 219 | if (file == NULL) { | ||
| 220 | printf("send_file: File %s not found.\n", filename); | ||
| 221 | return -1; | ||
| 222 | } | ||
| 223 | |||
| 224 | fseek(file, 0, SEEK_END); | ||
| 225 | int len = ftell(file); | ||
| 226 | fseek(file, 0, SEEK_SET); | ||
| 227 | |||
| 228 | char* buffer = malloc(len + loadOffset); | ||
| 229 | if (buffer == NULL) { | ||
| 230 | printf("send_file: Error allocating memory!\n"); | ||
| 231 | fclose(file); | ||
| 232 | return -1; | ||
| 233 | } | ||
| 234 | |||
| 235 | fread(&buffer[loadOffset], 1, len, file); | ||
| 236 | fclose(file); | ||
| 237 | |||
| 238 | len += loadOffset; | ||
| 239 | |||
| 240 | int packets = len / 0x800; | ||
| 241 | if (len % 0x800) { | ||
| 242 | packets++; | ||
| 243 | } | ||
| 244 | |||
| 245 | int last = len % 0x800; | ||
| 246 | if (!last) { | ||
| 247 | last = 0x800; | ||
| 248 | } | ||
| 249 | |||
| 250 | int i = 0; | ||
| 251 | char response[6]; | ||
| 252 | for (i = 0; i < packets; i++) { | ||
| 253 | int size = i + 1 < packets ? 0x800 : last; | ||
| 254 | |||
| 255 | if (!libusb_control_transfer(handle, 0x21, 1, i, 0, &buffer[i * 0x800], size, 1000)) { | ||
| 256 | printf("send_file: Error sending packet!\n"); | ||
| 257 | return -1; | ||
| 258 | } | ||
| 259 | |||
| 260 | if (libusb_control_transfer(handle, 0xA1, 3, 0, 0, response, 6, 1000) != 6) { | ||
| 261 | printf("send_file: Error receiving status!\n"); | ||
| 262 | return -1; | ||
| 263 | |||
| 264 | } else { | ||
| 265 | if (response[4] != 5) { | ||
| 266 | printf("send_file: Status error!\n"); | ||
| 267 | return -1; | ||
| 268 | } | ||
| 269 | } | ||
| 270 | } | ||
| 271 | |||
| 272 | libusb_control_transfer(handle, 0x21, 1, i, 0, buffer, 0, 1000); | ||
| 273 | for (i = 6; i <= 8; i++) { | ||
| 274 | if (libusb_control_transfer(handle, 0xA1, 3, 0, 0, response, 6, 1000) != 6) { | ||
| 275 | printf("send_file: Error receiving status!\n"); | ||
| 276 | return -1; | ||
| 277 | |||
| 278 | } else { | ||
| 279 | if (response[4] != i) { | ||
| 280 | printf("send_file: Status error!\n"); | ||
| 281 | return -1; | ||
| 282 | } | ||
| 283 | } | ||
| 284 | } | ||
| 285 | |||
| 286 | free(buffer); | ||
| 287 | return 0; | ||
| 288 | } | ||
| 289 | */ | ||
