Created
June 8, 2015 22:49
-
-
Save xerub/2b873a4ca08820a4d4de to your computer and use it in GitHub Desktop.
blow, blow, ultrasn0w
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* ultrasn0w (D) xerub 2014 | |
| * | |
| * This program is free software; you can redistribute it and/or modify | |
| * it under the terms of the "do What The Fuck you want to Public License"; | |
| * either version 1 of the License, or whatever (the fuck) version you want. | |
| * | |
| * $ ios-clang -o ultrasn0w.o -Wno-variadic-macros -O2 -c ultrasn0w.c | |
| * $ ios-clang -o ultrasn0w.dylib -shared ultrasn0w.o -lsubstrate -lATCommandStudioDynamic | |
| * | |
| * Inject into CommCenterClassic iPhone3,1 baseband 1.59.00 | |
| */ | |
| #include <dlfcn.h> | |
| #include <fcntl.h> | |
| #include <pthread.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <sys/ioctl.h> | |
| #include <sys/utsname.h> | |
| #include <termios.h> | |
| #include <time.h> | |
| #include <unistd.h> | |
| #include <mach/mach_init.h> | |
| #include <mach/vm_map.h> | |
| #include <mach-o/getsect.h> | |
| #include <mach-o/dyld.h> | |
| #define SPEED 115200 | |
| #define BUFSIZE (65536) | |
| char *BasebandVersion(void); | |
| int atprog(const char *cmds[], int num); | |
| int my_open(const char *path, int flags, int mode); | |
| int $XLockHandler(int a1, const char **a2, int a3, int a4); | |
| int $InternalNotification(int a1, int a2, int a3, int a4, void *a5); | |
| #define UDEBUG 1 | |
| #define OPTION_USE_ATCSD_XLOCK 1 | |
| #define OPTION_NO_TEMP_TIMEOUT 1 // XXX may be dangerous | |
| #define OPTION_USE_OTHER_LOWFD 0 | |
| #define OPTION_ZAP_RESP_LENGTH 0 | |
| #define OPTION_PATCH_XCGEDPAGE 1 | |
| #define FW612 1 | |
| #define FW704 1 | |
| #define FW712 1 | |
| #define forever for (;;) | |
| void MSHookFunction(vm_address_t addr, int (*f)(), void **pf); | |
| #if UDEBUG | |
| char *timestamp(void); | |
| #define DBG(args...) do { fprintf(LogFile, args); fflush(LogFile); } while (0) | |
| static const char * | |
| noti(int a2) | |
| { | |
| static const char *names[] = { | |
| /* 0 */ "kEventCallActive", | |
| /* 1 */ "kEventCallInactive", | |
| /* 2 */ "kEventRegistered", | |
| /* 3 */ "kEventNotRegistered", | |
| /* 4 */ "kEventNewNetwork", | |
| /* 5 */ "kEventNewCell", | |
| /* 6 */ "kEventRadioOff", | |
| /* 7 */ "kEventRadioReset", | |
| /* 8 */ "kEventRadioOn", | |
| /* 9 */ "kEventRfDisabling", | |
| /* 10 */ "kEventRfDisabled", | |
| /* 11 */ "kEventSimDisabled", | |
| /* 12 */ "kEventSimUnreadable", | |
| /* 13 */ "kEventSimInitializing", | |
| /* 14 */ "kEventSimReady", | |
| /* 15 */ "kEventSimInitComplete", | |
| /* 16 */ "kEventIccidAvailable", | |
| /* 17 */ "kEventEnteringLowPower", | |
| /* 18 */ "kEventExitingLowPower", | |
| /* 19 */ "kEventSimRefresh", | |
| /* 20 */ "kEventSimFsRefresh", | |
| /* 21 */ "kEventDumpState", | |
| /* 22 */ "kEventManualSelectionDisabled", | |
| /* 23 */ "kEventHomePlmnUpdated", | |
| /* 24 */ "kEventPinBlocked", | |
| /* 25 */ "kEventPukBlocked", | |
| /* 26 */ "kEventNewOutgoingCallId", | |
| /* 27 */ "kEventSimPinEntryRequest", | |
| /* 28 */ "kEventSimPukEntryRequest", | |
| /* 29 */ "kEventSimPinAccessResponse", | |
| /* 30 */ "kEventSimPukAccessResponse", | |
| /* 31 */ "kEventEnteringBrickState", | |
| /* 32 */ "kEventExitingBrickState", | |
| /* 33 */ "kEventDataAttached", | |
| /* 34 */ "kEventDataNotAttached", | |
| /* 35 */ "kEventQuerySimStatus", | |
| /* 36 */ "kEventDataMode", | |
| /* 37 */ "kEventRadioMaxTxPower", | |
| /* 38 */ "kEventPdpContextActivated", | |
| /* 39 */ "kEventPdpContextDeactivated", | |
| /* 40 */ "kEventRAT", | |
| /* 41 */ "kEventPhoneNumberAvailable", | |
| /* 42 */ "kEventClearSimPIN", | |
| /* 43 */ "kEventSimType", | |
| /* 44 */ "kEventXSMSReady", | |
| /* 45 */ "kEventCallingLineIdRestrictionValueChanged", | |
| /* 46 */ "kEventOtaspCommitted", | |
| /* 47 */ "kEventECBMChanged", | |
| /* 48 */ "kEventEmergencyNumbersAvailbale", | |
| /* 49 */ "kEventNewCallinECBM", | |
| /* 50 */ "kEventECBMError", | |
| /* 51 */ "kEventFileTransferSuccessful", | |
| /* 52 */ "kEventFileTransferError", | |
| /* 53 */ "kEventSIMRefreshReceived", | |
| /* 54 */ "kEventServiceProvisionStateChanged", | |
| /* 55 */ "kEventActiveCallInSettingsModel", | |
| /* 56 */ "kEventCellularDataStatusAvailable" | |
| }; | |
| int n = sizeof(names) / sizeof(names[0]); | |
| if (a2 >= 0 && a2 < n) { | |
| return names[a2]; | |
| } | |
| return "???"; | |
| } | |
| #else /* !UDEBUG */ | |
| #define DBG(args...) | |
| #define noti(x) "" | |
| #endif /* !UDEBUG */ | |
| FILE *LogFile; | |
| vm_address_t XLockHandler; | |
| vm_address_t InternalNotification; | |
| int (*_XLockHandler)(int a1, const char **a2, int a3, int a4); | |
| int (*_InternalNotification)(int a1, int a2, int a3, int a4, void *a5); | |
| int (*_orig_open)(const char *pathname, int flags, mode_t mode); | |
| int fw; | |
| int lowFD; | |
| char readbuf[BUFSIZE]; | |
| struct termios term; | |
| const char *unlock_strings[4] = { | |
| "at+xapp=\"...................................." | |
| "\x88\x6a\xff\xed\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" | |
| "\x2d\x7a\x01\x60\x22\x3b\x22\x58\x58\x34\x34\x34\x34\x35\x35\x35" | |
| "\x35\x36\x36\x36\x36\x37\x37\x37\x37\xf3\xa0\x14\x60\x55\x55\x55" | |
| "\x55\x07\x48\x80\x47\xd0\x1f\xff\xff\xf1\xa0\x14\x60\x55\x55\x55" | |
| "\x55\x07\x1c\x0f\xbc\xd4\x1f\xff\xff\xf1\xa0\x14\x60\x55\x55\x55" | |
| "\x55\xd2\x18\x07\x4b\xd8\x1f\xff\xff\xf1\xa0\x14\x60\x55\x55\x55" | |
| "\x55\x98\x47\x38\x1c\xdc\x1f\xff\xff\xf1\xa0\x14\x60\x55\x55\x55" | |
| "\x55\x04\x49\x88\x47\xe0\x1f\xff\xff\xf1\xa0\x14\x60\x55\x55\x55" | |
| "\x55\x01\x49\x8d\x46\xe4\x1f\xff\xff\xf1\xa0\x14\x60\x55\x55\x55" | |
| "\x55\x48\x1a\xf0\xbd\xe8\x1f\xff\xff\xf1\xa0\x14\x60\x55\x55\x55" | |
| "\x55\x6c\x3c\x88\x72\xec\x1f\xff\xff\xf1\xa0\x14\x60\x55\x55\x55" | |
| "\x55\x5c\x13\x18\x60\xf0\x1f\xff\xff\xf1\xa0\x14\x60\x55\x55\x55" | |
| "\x55\x6c\x13\x18\x60\xf4\x1f\xff\xff\xf1\xa0\x14\x60\x55\x55\x55" | |
| "\x55\xfc\xd9\x1f\x60\xf8\x1f\xff\xff\xf1\xa0\x14\x60\x33\x33\x33" | |
| "\x33\x34\x34\x34\x34\x35\x35\x35\x35\xd1\x1f\xff\xff\xd0\x04\xff" | |
| "\xff\xbc\xa7\x87\x60\x59\x01\x01\x01\xff\xfe\xfe\xfe\x04\xf0\x1f" | |
| "\xe5\x34\x63\x73\x40\x0f\x48\x80\x38\x80\x38\x0f\x4a\x10\x60\xe4" | |
| "\x19\x0e\x48\x80\x47\x07\x1c\xaa\x19\x20\x25\x02\x35\x20\x78\xa8" | |
| "\x42\x09\xd0\xc0\x46\xff\x28\x02\xd1\x01\x34\x20\x78\x01\x30\x10" | |
| "\x70\x01\x34\x01\x32\xf2\xe7\x38\x1c\x05\x49\x88\x47\x48\x1a\x6a" | |
| "\x46\x12\x68\x10\x47\x1f\x01\xfa\x60\x80\x12\x70\x60\x5c\x13\x18" | |
| "\x60\x6c\x13\x18\x60\"", | |
| "at+xapp=\"...................................." | |
| "\xdb\xa7\x88\x61\x01\x01\xfb\x61\xff\xfe\xfe\xfe\xff\xfe\xfe\xfe" | |
| "\xd9\x04\xff\xff\x5d\x6e\x18\x60\x22\x3b\x22\xff\xff\xff\xff\x10" | |
| "\xff\xff\x45\xff\xfe\x10\xbd\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5" | |
| "\x05\x40\x2a\x80\x1c\xff\xff\x0c\xff\xff\x78\x47\xff\xff\x1c\x04" | |
| "\xf0\x1f\xe5\x1d\x40\x2a\x80\x80\xff\xff\xff\x21\xff\xff\x04\xf0" | |
| "\x1f\xe5\xff\xff\x6f\x73\x40\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5" | |
| "\xa1\x40\x2a\x80\x04\xf0\x1f\xe5\xf8\x6e\x73\x40\xf7\xff\xfe\xff" | |
| "\xfe\xea\xf2\xe7\xa4\xff\xff\xa6\xff\xff\x04\xf0\x1f\xe5\xff\x07" | |
| "\x6f\x73\x40\x04\xf0\x1f\xe5\x10\x6f\x73\x40\x04\xf0\x1f\xe5\x18" | |
| "\x6f\x73\x40\x04\xf0\x1f\xe5\x20\x6f\x73\x40\x04\xf0\x1f\xe5\x28" | |
| "\x6f\x73\x40\x04\xf0\x1f\xe5\x30\x6f\x73\x40\x04\xf0\x1f\xe5\x38" | |
| "\x6f\x73\x40\x04\xf0\x1f\xe5\x40\x6f\x73\x40\x04\xf0\x1f\xe5\x48" | |
| "\x6f\x73\x40\x04\xf0\x1f\xe5\x50\x6f\x73\x40\x04\xf0\x1f\xe5\x58" | |
| "\x6f\x73\x40\x04\xf0\x1f\xe5\x60\x6f\x73\x40\x04\xf0\x1f\xe5\x68" | |
| "\x6f\x73\x40\x04\xf0\x1f\xe5\x70\x6f\x73\x40\x04\xf0\x1f\xe5\x78" | |
| "\x6f\x73\x40\x04\xf0\x1f\xe5\x80\x6f\x73\x40\x04\xf0\x1f\xe5\x88" | |
| "\x6f\x73\x40\x04\xf0\x1f\xe5\x90\x6f\x73\x40\x04\xf0\x1f\xe5\x98" | |
| "\x6f\x73\x40\x04\xf0\x1f\xe5\xa0\x6f\x73\x40\x04\xff\xff\xff\xff" | |
| "\xea\x02\xe0\x4c\x01\x02\xff\xff\x0a\xe0\x50\x01\x20\xff\xff\x78" | |
| "\x47\xff\xff\x1c\x04\xf0\x1f\xe5\x49\x41\x2a\x80\x04\xf0\x1f\xe5" | |
| "\xa8\x6f\x73\x40\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\xb1\x6f\x73" | |
| "\x40\x44\x03\x0c\xff\xff\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\x45" | |
| "\x43\x2a\x80\x54\x03\x0c\xff\xff\x78\x47\xff\xff\x1c\x04\xf0\x1f" | |
| "\xe5\xb9\x71\x73\x40\x20\x04\x0c\xff\xff\x78\x47\xff\xff\x1c\x04" | |
| "\xf0\x1f\xe5\x21\x44\x2a\x80\xa4\x04\x0c\xff\xff\x78\x47\xff\xff" | |
| "\x1c\x04\xf0\x1f\xe5\x09\x73\x73\x40\xb4\x04\x0c\xff\xff\x78\x47" | |
| "\xff\xff\x1c\x04\xf0\x1f\xe5\xb5\x44\x2a\x80\x3c\x05\x0c\xff\xff" | |
| "\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\x3d\x45\x2a\x80\x5c\x05\x0e" | |
| "\xff\xff\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\x6d\x45\x2a\x80\xff" | |
| "\x07\xe0\x6c\x05\x02\xff\xff\xf6\xe7\x70\x05\x18\xff\xff\x78\x47" | |
| "\xff\xff\x1c\x04\xf0\x1f\xe5\x71\x45\x2a\x80\x78\x47\xff\xff\x1c" | |
| "\x04\xf0\x1f\xe5\x69\x45\x2a\x80\xf0\x06\x0c\xff\xff\x78\x47\xff" | |
| "\xff\x1c\x04\xf0\x1f\xe5\x55\x75\x73\x40\x34\x07\x0c\xff\xff\x78" | |
| "\x47\xff\xff\x1c\x04\xf0\x1f\xe5\x35\x47\x2a\x80\x5c\x07\x0c\xff" | |
| "\xff\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\x5d\x47\x2a\x80\xc0\x07" | |
| "\x10\xff\xff\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\xcd\x47\x2a\x80" | |
| "\xff\xff\x20\x70\x47\xd4\x07\x0c\xff\xff\x78\x47\xff\xff\x1c\x04" | |
| "\xf0\x1f\xe5\x39\x76\x73\x40\x88\xff\x07\x0c\xff\xff\x78\x47\xff" | |
| "\xff\x1c\x04\xf0\x1f\xe5\xed\x76\x73\x40\xcc\xff\x07\x0c\xff\xff" | |
| "\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\xcd\x48\x2a\x80\xec\xff\x07" | |
| "\x0c\xff\xff\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\x51\x77\x73\x40" | |
| "\xb4\x09\x0c\xff\xff\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\x19\x78" | |
| "\x73\x40\xb4\x0a\x0c\xff\xff\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5" | |
| "\xb5\x4a\x2a\x80\x18\x0b\x0c\xff\xff\x78\x47\xff\xff\x1c\x04\xf0" | |
| "\x1f\xe5\x7d\x79\x73\x40\x6c\x0b\x18\xff\xff\x78\x47\xff\xff\x1c" | |
| "\x04\xf0\x1f\xe5\x6d\x4b\x2a\x80\x78\x47\xff\xff\x1c\x04\xf0\x1f" | |
| "\xe5\x79\x4b\x2a\x80\xe4\x0b\x0c\xff\xff\x78\x47\xff\xff\x1c\x04" | |
| "\xf0\x1f\xe5\xe5\x4b\x2a\x80\xbc\xff\x0c\x18\xff\xff\x78\x47\xff" | |
| "\xff\x1c\x04\xf0\x1f\xe5\x21\x7c\x73\x40\x78\x47\xff\xff\x1c\x04" | |
| "\xf0\x1f\xe5\x2d\x7c\x73\x40\x64\x0e\x0c\xff\xff\x78\x47\xff\xff" | |
| "\x1c\x04\xf0\x1f\xe5\xc9\x7c\x73\x40\xdc\x0e\x0c\xff\xff\x78\x47" | |
| "\xff\xff\x1c\x04\xf0\x1f\xe5\xdd\x4e\x2a\x80\xec\x0e\x0c\xff\xff" | |
| "\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\xfb\x4e\x2a\x80\xfa\x0e\x02" | |
| "\xff\xff\xf7\xe7\x04\x0f\x0e\xff\xff\x78\x47\xff\xff\x1c\x04\xf0" | |
| "\x1f\xe5\x75\x7d\x73\x40\xf8\xe7\x18\x0f\x0c\xff\xff\x78\x47\xff" | |
| "\xff\x1c\x04\xf0\x1f\xe5\x19\x4f\x2a\x80\x2e\x0f\x0e\xff\xff\xff" | |
| "\xfe\xe7\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\x2f\x4f\x2a\x80\x4c" | |
| "\x0f\x0c\xff\xff\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\x4d\x4f\"", | |
| "at+xapp=\"...................................." | |
| "\xdb\xa7\x88\x61\x27\x04\xfb\x61\xff\xfe\xfe\xfe\xff\xfe\xfe\xfe" | |
| "\xd9\x04\xff\xff\x5d\x6e\x18\x60\x22\x3b\x22\x2a\x80\x6a\x0f\x0e" | |
| "\xff\xff\xff\xfe\xe7\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\x6b\x4f" | |
| "\x2a\x80\x7c\x0f\x0e\xff\xff\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5" | |
| "\x89\x4f\x2a\x80\xf8\xe7\x92\x0f\x0e\xff\xff\xff\xfe\xe7\x78\x47" | |
| "\xff\xff\x1c\x04\xf0\x1f\xe5\x93\x4f\x2a\x80\xa4\x0f\x24\xff\xff" | |
| "\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\xff\xfe\x4f\x2a\x80\x78\x47" | |
| "\xff\xff\x1c\x04\xf0\x1f\xe5\xb1\x4f\x2a\x80\x78\x47\xff\xff\x1c" | |
| "\x04\xf0\x1f\xe5\x21\x7e\x73\x40\xce\x0f\x0e\xff\xff\xff\xfe\xe7" | |
| "\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\xcf\x4f\x2a\x80\xe6\x0f\x0e" | |
| "\xff\xff\xff\xfe\xe7\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\xe7\x4f" | |
| "\x2a\x80\xfe\x0f\x02\xff\xff\xd1\xe7\xff\xff\xff\xff\xff\xff\xff" | |
| "\xff\"", | |
| "at+xapp=\"...................................." | |
| "\xdb\xa7\x88\x61\x9b\x0a\x01\x01\xff\xfe\xfd\xfe\xff\xfe\xfe\xfe" | |
| "\xd9\x04\xff\xff\xa9\x09\xff\xff\x22\x3b\x22\xff\xff\x1c\x78\x47" | |
| "\xff\xff\x1c\x04\xf0\x1f\xe5\xff\xfe\x67\x73\x40\xf0\xb4\xff\xff" | |
| "\xf0\x59\xf8\x58\x48\x58\x49\xff\xff\xf0\x64\xf8\x5d\x4c\x5b\x4d" | |
| "\x60\x4e\xff\xff\x2e\x09\xd0\x60\x19\xff\xff\xf0\x86\xf8\x57\x49" | |
| "\x21\x43\x01\x60\x54\x48\x24\x18\x36\x1a\xf3\xe7\x5b\x4c\x20\x1c" | |
| "\xff\xff\xf0\x7b\xf8\xff\xff\x68\x21\x1c\xff\xff\xf0\x7c\xf8\x21" | |
| "\x1c\x1f\x31\x01\x60\x40\xa3\x98\x47\x20\x1c\x53\x49\x09\xff\x0c" | |
| "\x09\x05\x1f\x31\x49\x4b\x47\x4d\xff\xff\x2b\x04\xd0\x01\x60\x5b" | |
| "\x1b\x49\x19\x04\x30\xf8\xe7\x4d\x48\xff\xff\xf0\x61\xf8\x09\x34" | |
| "\x04\x60\x20\x1c\x4a\x49\xff\xff\xf0\x60\xf8\x3c\x49\x1f\x31\x01" | |
| "\x60\x32\xa3\x98\x47\x46\x48\x3f\x49\x09\x18\xff\xff\xf0\x27\xf8" | |
| "\x46\x4c\x47\x4d\x36\x4e\x28\x88\x6a\x88\x17\x1c\xff\xff\x2a\x05" | |
| "\xd0\x04\x35\x29\x1c\x80\x19\xa0\x47\xed\x19\xf4\xe7\x44\x48\x41" | |
| "\xa1\x0c\xff\x21\xa0\x47\xff\xff\xf0\x0e\xf8\xf0\xbc\xff\xff\x20" | |
| "\x3a\x4b\x18\x47\xff\xff\xb5\x26\x48\x80\x47\x27\xa1\xff\x07\x60" | |
| "\xc0\x21\xff\x07\x43\x24\x49\x88\x47\xff\xff\xbd\xff\xff\xb5\x23" | |
| "\x48\x21\x49\x88\x47\xff\xff\xbd\xf0\xb5\x81\xb0\x05\x1c\x0e\x1c" | |
| "\x21\x4f\x3f\x68\x1f\x4c\x24\x68\xff\xff\x20\xff\xff\x90\xb8\x42" | |
| "\x0b\xd0\xe0\x68\x21\x69\x2a\x1c\x33\x1c\xff\xff\xf0\xff\x07\xf8" | |
| "\x8c\x20\x24\x58\xff\xff\x98\x01\x30\xff\xff\x90\xf1\xe7\x01\xb0" | |
| "\xf0\xbd\x30\xb5\x12\x0b\x88\x42\x0a\xd2\x04\x68\x24\x0b\x94\x42" | |
| "\x04\xd1\x04\x68\x24\x05\x24\xff\x0c\xe4\x18\x04\x60\x04\x30\xf2" | |
| "\xe7\x30\xbd\x02\xff\x0c\x92\xff\xff\x11\x4b\xd0\x18\x70\x47\x80" | |
| "\x0a\x80\x02\x09\x0b\xff\xfe\x23\x19\x40\x89\xff\xff\xff\x07\x43" | |
| "\x70\x47\x17\x0f\xff\x07\xee\x16\x0f\xff\x07\xee\xff\x14\x0f\xff" | |
| "\x07\xee\x1e\xff\xfe\x2f\xe1\x18\xb0\x38\x60\x6c\x13\x18\x60\xff" | |
| "\xfe\xff\xfe\xff\xfe\xff\xfe\x18\xff\x21\xff\xfe\xff\xfe\x1c\xff" | |
| "\x21\xff\xfe\xff\xfe\xff\xff\x10\xff\xfe\xff\xfe\x64\x6e\x73\x40" | |
| "\xff\xff\x10\xff\xff\xff\xff\xff\xff\xff\xff\x09\xff\xff\xff\xff" | |
| "\xff\xff\x10\xff\xff\x0e\x04\xff\x07\xff\xff\xff\xff\xff\xff\xff" | |
| "\xff\x20\xff\xff\xff\xff\xff\xff\x60\x54\x63\x48\x60\xb0\xec\x83" | |
| "\x60\x10\x2a\xff\xfe\xff\xfe\xff\xff\xff\xff\xff\xff\x10\xff\xff" | |
| "\x40\x2a\x60\xff\xff\xe0\xf9\x60\x5d\x6e\x18\x60\xfc\xd9\x1f\x60" | |
| "\xff\xff\xff\xff\xfa\x60\x78\x47\xff\xff\x1c\x04\xf0\x1f\xe5\xdd" | |
| "\x6d\x73\x40\x78\x0f\xff\xfe\xff\xfe\"" | |
| }; | |
| const char *activation_ticket[6] = { | |
| "at+xlck=0", | |
| "at+xlck=1,1,\"000000000000000000000000000000000000000000000000" | |
| "0000000000000000000000000000000000000000000000000000000000000000" | |
| "0000000000000000000000000000000000000000000000000000000000000000" | |
| "0000000000000000000000000000000000000000000000000000000000000000" | |
| "0000000000000000000000000000000000000000000000000000000000000000" | |
| "0000000000000000000000000000000000000000000000000000000000000000" | |
| "0000000000000000000000000000000000000000000000000000000000000000" | |
| "0000000000000000000000000000000000000000000000000000000000000000" | |
| "0000000000000000\"", | |
| "at+xlck=1,2,\"000000000000000000000000000000000000000000000000" | |
| "0000000000000000000000000000000000000000000000000000000000000000" | |
| "0000000000000000000000000000000000000000000000000000000000000000" | |
| "0000000000000000000000000000000000000000000000000000000000000000" | |
| "0000000000000000000000000000000000000000000000000000000000000000" | |
| "0000000000000000000000000000000000000000000000000000000000000000" | |
| "0000000000000000000000000000000000000000000000000000000000000000" | |
| "0000000000000000000000000000000000000000000000000000000000000000" | |
| "0000000000000000\"", | |
| "at+xlck=1,3,\"000000000000000000000000000000000000000000000000" | |
| "0000000000000000000000000000000000000000000000000000000000000000" | |
| "0000000000000000000000000000000000000000000000000000000000000000" | |
| "0000000000000000000000000000000000000000000000000000000000000000" | |
| "0000000000000000000000000000000000000000000000000000000000000000" | |
| "0000000000000000000000000000000000000000000000000000000000000000" | |
| "0000000000000000000000000000000000000000000000000000000000000000" | |
| "0000000000000000000000000000000000000000000000000000000000000000" | |
| "0000000000000000\"", | |
| "at+xlck=1,4,\"000000000000000000000000000000000000000000000000" | |
| "0000000000000000000000000000000000000000000000000000000000000000" | |
| "0000000000000000000000000000000000000000000000000000000000000000" | |
| "0000000000000000000000000000000000000000000000000000000000000000" | |
| "0000000000000000000000000000000000000000000000000000000000000000" | |
| "0000000000000000000000000000000000000000000000000000000000000000" | |
| "0000000000000000000000000000000000000000000000000000000000000000" | |
| "0000000000000000000000000000000000000000000000000000000000000000" | |
| "0000000000000000\"", | |
| "at+xlck=2" | |
| }; | |
| int IsCompatible = -1; | |
| pthread_mutex_t at_mutex = PTHREAD_MUTEX_INITIALIZER; | |
| unsigned slide = 0; | |
| int debug = 1; | |
| kern_return_t | |
| writeWord(vm_address_t addr, uint16_t val, int exec) | |
| { | |
| vm_prot_t new_protection; | |
| unsigned pagesize = getpagesize(); | |
| mach_port_t port = mach_task_self(); | |
| DBG("%s writeWord %x at %x/%x\n", timestamp(), val, addr - slide, addr); | |
| if (vm_protect(port, addr / pagesize * pagesize, pagesize, 0, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_COPY)) { | |
| return 1; | |
| } | |
| *(uint16_t *)addr = val; | |
| if (exec) { | |
| new_protection = VM_PROT_READ | VM_PROT_EXECUTE; | |
| } else { | |
| new_protection = VM_PROT_READ; | |
| } | |
| if (vm_protect(port, addr / pagesize * pagesize, pagesize, 0, new_protection)) { | |
| return 1; | |
| } | |
| DBG("%s writeWord ok: %x\n", timestamp(), *(uint16_t *)addr); | |
| return 0; | |
| } | |
| vm_address_t | |
| FindLastThumbFunction(vm_address_t addr) | |
| { | |
| uint16_t *ptr, *p; | |
| unsigned int size; | |
| if (slide) { | |
| ptr = (uint16_t *)(getsectdata("__TEXT", "__text", (unsigned long *)&size) + slide); | |
| } else { | |
| ptr = (uint16_t *)getsectdatafromheader((struct mach_header *)0x1000, "__TEXT", "__text", &size); | |
| } | |
| p = (uint16_t *)(addr & ~3); | |
| while (--p >= (uint16_t *)ptr) { | |
| if ((p[0] & 0xFF00) == 0xB500 && (p[-1] & 0xF000) != 0xF000) { | |
| return (vm_address_t)p + 1; | |
| } | |
| } | |
| return 0; | |
| } | |
| vm_address_t | |
| FindReference(vm_address_t addr) | |
| { | |
| char *ptr, *end; | |
| unsigned int size; | |
| if (slide) { | |
| ptr = getsectdata("__TEXT", "__text", (unsigned long *)&size) + slide; | |
| } else { | |
| ptr = getsectdatafromheader((struct mach_header *)0x1000, "__TEXT", "__text", &size); | |
| } | |
| end = ptr + size - 4; | |
| if (!addr) { | |
| return 0; | |
| } | |
| for (; ptr < end; ptr++) { | |
| if (!memcmp(ptr, &addr, 4)) { | |
| return (vm_address_t)ptr; | |
| } | |
| } | |
| if (addr == 0xAFBB8) { | |
| return 0x55230; | |
| } | |
| if (addr == 0xA8E3C) { | |
| return 0x2AE8C; | |
| } | |
| #define SLIDE(a, x) if (addr == slide + (a)) return (x) + slide | |
| switch (fw) { | |
| case 431: | |
| SLIDE(0xF47AC, 0x6039C); | |
| SLIDE(0xED6C0, 0x34114); | |
| SLIDE(0xF02EC, 0x458B4); | |
| break; | |
| case 432: | |
| SLIDE(0xF47AC, 0x60370); | |
| SLIDE(0xED6C0, 0x340E8); | |
| SLIDE(0xF02EC, 0x45888); | |
| break; | |
| case 433: | |
| SLIDE(0xF4738, 0x6030C); | |
| SLIDE(0xED64C, 0x34110); | |
| SLIDE(0xF0278, 0x45824); | |
| break; | |
| case 500: | |
| SLIDE(0x124DD5, 0x680B4); | |
| SLIDE(0x11CEC9, 0x35704); | |
| SLIDE(0x11FEA1, 0x4BB24); | |
| break; | |
| case 501: | |
| SLIDE(0x124DD0, 0x67B54); | |
| SLIDE(0x11CE6C, 0x34FA8); | |
| SLIDE(0x11FE60, 0x4B504); | |
| break; | |
| case 51: | |
| SLIDE(0x117DC8, 0x6B754); | |
| SLIDE(0x10FCB0, 0x38820); | |
| SLIDE(0x112CBD, 0x4EF0C); | |
| break; | |
| case 511: | |
| SLIDE(0x117BF8, 0x6B2C0); | |
| SLIDE(0x10FAE0, 0x3838C); | |
| SLIDE(0x112AED, 0x4EA78); | |
| break; | |
| #if FW612 | |
| case 612: | |
| SLIDE(0x1D0834, 0xAB308); | |
| SLIDE(0x1C813F, 0x56B1A); | |
| SLIDE(0x1CB735, 0x7DABC); | |
| #if OPTION_NO_TEMP_TIMEOUT | |
| SLIDE(0x1CE4E9, 0xA39DE); | |
| #endif | |
| break; | |
| #endif | |
| #if FW704 | |
| case 704: | |
| SLIDE(0x2E917E, 0x12C0AE); | |
| SLIDE(0x2DF714, 0x8C852); | |
| SLIDE(0x2E3373, 0xBF360); | |
| #if OPTION_NO_TEMP_TIMEOUT | |
| SLIDE(0x2E6D99, 0x122A4E); | |
| #endif | |
| break; | |
| #endif | |
| #if FW712 | |
| case 712: | |
| SLIDE(0x2FB767, 0x13216E); | |
| SLIDE(0x2F1CA5, 0x808D6); | |
| SLIDE(0x2F5938, 0xB49F8); | |
| #if OPTION_NO_TEMP_TIMEOUT | |
| SLIDE(0x2F9382, 0x128B7E); | |
| #endif | |
| break; | |
| #endif | |
| } | |
| #undef SLIDE | |
| return 0; | |
| } | |
| vm_address_t | |
| FindString(const char *str) | |
| { | |
| char *ptr, *end; | |
| unsigned int size; | |
| if (slide) { | |
| ptr = getsectdata("__TEXT", "__cstring", (unsigned long *)&size) + slide; | |
| } else { | |
| ptr = getsectdatafromheader((struct mach_header *)0x1000, "__TEXT", "__cstring", &size); | |
| } | |
| for (end = ptr + size - strlen(str); ptr < end; ptr++) { | |
| if (!strcmp(ptr, str)) { | |
| return (vm_address_t)ptr; | |
| } | |
| } | |
| return 0; | |
| } | |
| char * | |
| FindStringN(const char *str, size_t n) | |
| { | |
| char *ptr; | |
| char *end; | |
| unsigned int size; | |
| if (slide) { | |
| ptr = getsectdata("__TEXT", "__cstring", (unsigned long *)&size) + slide; | |
| } else { | |
| ptr = getsectdatafromheader((struct mach_header *)0x1000, "__TEXT", "__cstring", &size); | |
| } | |
| for (end = ptr + size - strlen(str); ptr < end; ptr++) { | |
| if (!strncmp(ptr, str, n)) { | |
| return ptr; | |
| } | |
| } | |
| return NULL; | |
| } | |
| char * | |
| timestamp(void) | |
| { | |
| static char buf[32]; | |
| time_t t = time(NULL); | |
| #if UDEBUG | |
| int len = sprintf(buf, "%u", getpid()); | |
| buf[len++] = ' '; | |
| ctime_r(&t, buf + len); | |
| buf[len + 24] = '\0'; | |
| #else | |
| ctime_r(&t, buf); | |
| buf[24] = '\0'; | |
| #endif | |
| return buf; | |
| } | |
| void __attribute__((constructor)) | |
| Start(void) | |
| { | |
| struct utsname buf; | |
| vm_address_t addr; | |
| memset(&buf, 0, sizeof(buf)); | |
| uname(&buf); | |
| if (strcmp("iPhone3,1", buf.machine)) { | |
| dlopen("/usr/share/ultrasn0w/ultrasn0w-xgold608.dylib", RTLD_LAZY | RTLD_GLOBAL); | |
| return; | |
| } | |
| LogFile = fopen("/var/wireless/Library/Logs/ultrasn0w-dylib.log", "w"); | |
| DBG("==================================================================== %u\n", getpid()); | |
| fprintf(LogFile, "%s ultrasn0w loaded via CommCenter\n", timestamp()); | |
| fflush(LogFile); | |
| slide = _dyld_get_image_vmaddr_slide(0); | |
| addr = FindString("+xsimstate=1") - slide; | |
| if (FindStringN("Mar 18 2011", 11)) { | |
| fw = 431; | |
| } | |
| if (FindStringN("Apr 4 2011", 11)) { | |
| fw = 432; | |
| } | |
| if (FindStringN("Apr 28 2011", 11)) { | |
| fw = 433; | |
| } | |
| if (addr == 0x11CF51) { | |
| fw = 500; | |
| } else if (addr == 0x11CEF4) { | |
| fw = 501; | |
| } else if (addr == 0x10FD38) { | |
| fw = 51; | |
| } else if (addr == 0x10FB68) { | |
| fw = 511; | |
| #if FW612 | |
| } else if (addr == 0x1C81C7) { | |
| fw = 612; | |
| #endif | |
| #if FW704 | |
| } else if (addr == 0x2DF79C) { | |
| fw = 704; | |
| #endif | |
| #if FW712 | |
| } else if (addr == 0x2F1D2D) { | |
| fw = 712; | |
| #endif | |
| } | |
| DBG("%s fw = %d\n", timestamp(), fw); | |
| addr = FindReference(FindString("+xcgedpage=0,1")); | |
| if (addr) { | |
| addr = FindLastThumbFunction(addr); | |
| DBG("%s xcged = %x/%x\n", timestamp(), addr - slide, addr); | |
| if (*(uint16_t *)(addr + 15) == 0xB183) { | |
| writeWord(addr + 15, 0xE010, 1); | |
| } else if (*(uint16_t *)(addr + 23) == 0xD017) { | |
| writeWord(addr + 23, 0xE017, 1); | |
| #if OPTION_PATCH_XCGEDPAGE | |
| #if FW612 | |
| } else if (*(uint16_t *)(addr + 23) == 0xD018) { | |
| writeWord(addr + 23, 0xE018, 1); | |
| #endif | |
| #if FW704 || FW712 | |
| } else if (*(uint16_t *)(addr + 19) == 0xB1C1) { | |
| writeWord(addr + 19, 0xE018, 1); | |
| #endif | |
| #endif /* OPTION_PATCH_XCGEDPAGE */ | |
| } | |
| } | |
| #if OPTION_NO_TEMP_TIMEOUT && (FW612 || FW704 || FW712) | |
| addr = FindReference(FindString("+xdrv=5,16,%d")); | |
| if (addr) { | |
| addr = FindLastThumbFunction(addr); | |
| DBG("%s xdrv5 = %x/%x\n", timestamp(), addr - slide, addr); | |
| if (0) { | |
| #if FW612 | |
| } else if (*(uint16_t *)(addr + 19) == 0x2D01) { | |
| writeWord(addr + 19, 0x2DFF, 1); | |
| #endif | |
| #if FW704 || FW712 | |
| } else if (*(uint16_t *)(addr + 23) == 0x2D01) { | |
| writeWord(addr + 23, 0x2DFF, 1); | |
| #endif | |
| } | |
| } | |
| #endif /* OPTION_NO_TEMP_TIMEOUT */ | |
| addr = FindReference(FindString("Sending internal notification %s (%d) params={%d, %d, %p}\n")); | |
| if (addr) { | |
| InternalNotification = FindLastThumbFunction(addr); | |
| DBG("%s InternalNotification = %x/%x\n", timestamp(), InternalNotification - slide, InternalNotification); | |
| addr = FindReference(FindString("activation ticket accepted... drive thru\n")); | |
| if (addr) { | |
| XLockHandler = FindLastThumbFunction(addr); | |
| DBG("%s XLockHandler = %x/%x\n", timestamp(), XLockHandler - slide, XLockHandler); | |
| MSHookFunction(InternalNotification, $InternalNotification, (void **)&_InternalNotification); | |
| MSHookFunction(XLockHandler, $XLockHandler, (void **)&_XLockHandler); | |
| MSHookFunction((vm_address_t)open, my_open, (void **)&_orig_open); | |
| fprintf(LogFile, "%s ultrasn0w hooked\n", timestamp()); | |
| fflush(LogFile); | |
| } | |
| } | |
| } | |
| int | |
| my_open(const char *path, int flags, int mode) | |
| { | |
| int fd = _orig_open(path, flags, mode); | |
| if (!strcmp(path, "/dev/dlci.spi-baseband.low")) { | |
| DBG("%s my_open(%s, 0x%x, 0%o)\n", timestamp(), path, flags, mode); | |
| if (fw == 431 | |
| #if OPTION_USE_OTHER_LOWFD | |
| || fw == 612 // XXX 612? | |
| || fw == 704 // XXX 704? | |
| || fw == 712 // XXX 712? | |
| #endif | |
| ) { | |
| lowFD = _orig_open("/dev/dlci.spi-baseband.extra_0", flags, 0); // XXX mode? | |
| } else { | |
| lowFD = fd; | |
| } | |
| DBG("%s lowFD = %d\n", timestamp(), lowFD); | |
| } | |
| return fd; | |
| } | |
| #if OPTION_USE_ATCSD_XLOCK | |
| bool _ZNK10ATResponse14isFieldPresentEiib(void *this, int index, int, bool); | |
| void _ZNK10ATResponse22getStringFieldInternalENS_11FieldFormatEiii(void *out, void *this, int/*format?*/, int index, int, int); | |
| int _ZNK10ATResponse11getIntFieldEiii(void *this, int index, int, int base); | |
| #endif | |
| int | |
| $XLockHandler(int a1, const char **a2, int a3, int a4) | |
| { | |
| pthread_mutex_lock(&at_mutex); | |
| DBG("%s XLockHandler= %p %p %p %p %p %p\n", timestamp(), a2[0], a2[1], a2[2], a2[3], a2[4], a2[5]); | |
| { | |
| #if OPTION_USE_ATCSD_XLOCK | |
| bool present = _ZNK10ATResponse14isFieldPresentEiib(a2, 0, 0, false); | |
| DBG("%s XLockHandler: isFieldPresent: %d\n", timestamp(), present); | |
| if (present) { | |
| int i; | |
| for (i = 0; _ZNK10ATResponse14isFieldPresentEiib(a2, i + 2, 0, false); i += 3) { | |
| char out[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | |
| _ZNK10ATResponse22getStringFieldInternalENS_11FieldFormatEiii(out, a2, 0, i, 0, 0); | |
| if (out) { | |
| int v7 = _ZNK10ATResponse11getIntFieldEiii(a2, i + 1, 0, 10); | |
| int v4 = _ZNK10ATResponse11getIntFieldEiii(a2, i + 2, 0, 10); | |
| if (out[0] == 4 && out[1] == 'P' && out[2] == 'N' && out[3] == '\0') { | |
| DBG("%s XLockHandler: PN %d %d\n", timestamp(), v7, v4); | |
| if (IsCompatible && v7 == 1 && v4 == 1) { | |
| DBG("%s XLockHandler: activation_ticket\n", timestamp()); | |
| write(lowFD, "at+xpow=1\r", 10); | |
| atprog(activation_ticket, 6); | |
| write(lowFD, "at+xpow=0\r", 10); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| #else /* !OPTION_USE_ATCSD_XLOCK */ | |
| const char *const *p2 = a2; | |
| #if 1 /* XXX higher FWs need this? */ | |
| if (p2[0] < (char *)0x1000 || p2[0] >= (char *)0x40000000) { | |
| p2 += 2; | |
| if (p2[0] < (char *)0x1000 || p2[0] >= (char *)0x40000000) { | |
| p2 += 2; | |
| if (p2[0] < (char *)0x1000 || p2[0] >= (char *)0x40000000) { | |
| goto done; | |
| } | |
| } | |
| } | |
| #endif | |
| DBG("%s XLockHandler: %s\n", timestamp(), p2[0]); | |
| if (IsCompatible == 1 && strstr(p2[0], "+XLOCK: \"PN\",1,1")) { | |
| DBG("%s XLockHandler: activation_ticket\n", timestamp()); | |
| write(lowFD, "at+xpow=1\r", 10); | |
| atprog(activation_ticket, 6); | |
| write(lowFD, "at+xpow=0\r", 10); | |
| } | |
| done:; | |
| #endif /* !OPTION_USE_ATCSD_XLOCK */ | |
| } | |
| pthread_mutex_unlock(&at_mutex); | |
| return _XLockHandler(a1, a2, a3, a4); | |
| } | |
| int | |
| CheckCompatibility(void) | |
| { | |
| const char *version; | |
| int i = 0; | |
| int retries = (fw >= 500) ? 2 : 5; | |
| forever { | |
| version = BasebandVersion(); | |
| if (version && *version) { | |
| break; | |
| } | |
| if (++i >= retries) { | |
| if (version && *version) { | |
| break; | |
| } | |
| if (fw >= 500) { | |
| fprintf(LogFile, "%s Unable to query baseband version...will assume it's compatible\n", timestamp()); | |
| return 1; | |
| } | |
| fprintf(LogFile, "%s Unable to query baseband version...will assume it's NOT compatible\n", timestamp()); | |
| return 0; | |
| } | |
| } | |
| if (!strcmp(version, "01.59.00")) { | |
| return 1; | |
| } | |
| fprintf(LogFile, "%s ERROR! %s works only for baseband \"%s\", but this baseband is \"%s\"\n", "ultrasn0w", timestamp(), "01.59.00", version); | |
| return 0; | |
| } | |
| int | |
| $InternalNotification(int a1, int a2, int a3, int a4, void *a5) | |
| { | |
| pthread_mutex_lock(&at_mutex); | |
| DBG("%s InternalNotification(%d:%s, %d, %d, %p)\n", timestamp(), a2, noti(a2), a3, a4, a5); | |
| if (a2 == 7) { | |
| write(lowFD, "at+xpow=1\r", 10); | |
| fprintf(LogFile, "%s Baseband reset!\n", timestamp()); | |
| fflush(LogFile); | |
| if (IsCompatible == -1) { | |
| IsCompatible = CheckCompatibility(); | |
| } | |
| if (IsCompatible == 1) { | |
| fprintf(LogFile, "%s Unlocking!\n", timestamp()); | |
| fflush(LogFile); | |
| atprog(unlock_strings, 4); | |
| fprintf(LogFile, "%s Unlocking commands sent!\n", timestamp()); | |
| fflush(LogFile); | |
| } | |
| write(lowFD, "at+xpow=0\r", 10); | |
| } | |
| pthread_mutex_unlock(&at_mutex); | |
| return _InternalNotification(a1, a2, a3, a4, a5); | |
| } | |
| int | |
| InitConn(speed_t speed) | |
| { | |
| int handshake = TIOCM_DSR | TIOCM_CTS | TIOCM_RTS | TIOCM_DTR; | |
| int blahnull = 0; | |
| int fd = open("/dev/tty.debug", O_NOCTTY | O_RDWR); | |
| if (fd == -1) { | |
| perror("open"); | |
| exit(1); | |
| } | |
| ioctl(fd, TIOCEXCL); | |
| fcntl(fd, F_SETFL, 0); | |
| tcgetattr(fd, (struct termios *)&term); | |
| ioctl(fd, _IOW('T', 10, int), &blahnull); | |
| cfsetspeed((struct termios *)&term, speed); | |
| cfmakeraw((struct termios *)&term); | |
| term.c_cc[VTIME] = 5; | |
| term.c_iflag = (term.c_iflag & ~(ICRNL | IXON | IXOFF | IXANY | INPCK | ISTRIP | IGNBRK | BRKINT | IGNPAR)) | IGNPAR | IGNBRK; | |
| term.c_cc[VMIN] = 0; | |
| term.c_oflag &= ~OPOST; | |
| term.c_cflag = (term.c_cflag & ~PARENB) | CS8; | |
| term.c_lflag &= ~(IEXTEN | ICANON | ISIG | ECHO); | |
| tcsetattr(fd, TCSANOW, &term); | |
| ioctl(fd, TIOCSDTR); | |
| ioctl(fd, TIOCCDTR); | |
| ioctl(fd, TIOCMSET, &handshake); | |
| return fd; | |
| } | |
| int | |
| ReadResp(int fd, unsigned int timeout_sec, unsigned int timeout_micro) | |
| { | |
| struct timeval timeout; | |
| struct timeval *to; | |
| fd_set readfds; | |
| int nfds; | |
| int len = 0; | |
| nfds = fd + 1; | |
| FD_ZERO(&readfds); | |
| FD_SET(fd, &readfds); | |
| timeout.tv_sec = timeout_sec; | |
| timeout.tv_usec = timeout_micro; | |
| if (timeout.tv_sec || timeout.tv_usec) { | |
| to = &timeout; | |
| } else { | |
| to = NULL; | |
| } | |
| do { | |
| if (select(nfds, &readfds, NULL, NULL, to) <= 0) { | |
| #if OPTION_ZAP_RESP_LENGTH | |
| len = 0; | |
| #endif | |
| break; | |
| } | |
| len += read(fd, readbuf + len, BUFSIZE - len); | |
| readbuf[len] = '\0'; | |
| DBG("%s we have read (%d) %.*s\n", timestamp(), len, 16, readbuf); | |
| if (strstr(readbuf, "\r\nOK\r\n")) { | |
| break; | |
| } | |
| } while (!strstr(readbuf, "\r\nERROR\r\n")); | |
| return len; | |
| } | |
| ssize_t | |
| SendCmd(int fd, const void *cmd, size_t size) | |
| { | |
| return (write(fd, cmd, size) == -1) ? -1 : 0; | |
| } | |
| ssize_t | |
| SendStrCmd(int fd, const char *cmd) | |
| { | |
| return SendCmd(fd, cmd, strlen(cmd)); | |
| } | |
| ssize_t | |
| SendAT(int fd) | |
| { | |
| return SendStrCmd(fd, "AT\r"); | |
| } | |
| int | |
| AT(int fd) | |
| { | |
| int i; | |
| SendAT(fd); | |
| i = 0; | |
| do { | |
| if (ReadResp(fd, 0, 500000)) { | |
| return 1; | |
| } | |
| i++; | |
| SendAT(fd); | |
| } while (i != 15); | |
| return 0; | |
| } | |
| int | |
| lockcheck(void) | |
| { | |
| int fd; | |
| int len; | |
| fd = InitConn(SPEED); | |
| AT(fd); | |
| forever { | |
| forever { | |
| SendStrCmd(fd, "at+cpin?\r"); | |
| len = ReadResp(fd, 0, 100000); | |
| if (len > 0) { | |
| break; | |
| } | |
| AT(fd); | |
| AT(fd); | |
| } | |
| readbuf[len] = 0; | |
| fprintf(LogFile, "%s\n", readbuf); | |
| fflush(LogFile); | |
| if (strstr(readbuf, "PH-NET")) { | |
| close(fd); | |
| return 1; | |
| } | |
| if (strstr(readbuf, "OK")) { | |
| break; | |
| } | |
| sleep(1); | |
| } | |
| close(fd); | |
| return 0; | |
| } | |
| int | |
| pincheck(void) | |
| { | |
| int fd; | |
| int len; | |
| fd = InitConn(SPEED); | |
| AT(fd); | |
| forever { | |
| do { | |
| forever { | |
| SendStrCmd(fd, "at+cpin?\r"); | |
| len = ReadResp(fd, 0, 100000); | |
| if (len > 0) { | |
| break; | |
| } | |
| AT(fd); | |
| AT(fd); | |
| } | |
| readbuf[len] = 0; | |
| } while (strstr(readbuf, "SIM PIN")); | |
| if (strstr(readbuf, "OK")) { | |
| break; | |
| } | |
| sleep(1); | |
| } | |
| close(fd); | |
| return 0; | |
| } | |
| int | |
| atping(void) | |
| { | |
| int fd; | |
| fd = InitConn(SPEED); | |
| AT(fd); | |
| return close(fd); | |
| } | |
| char * | |
| BasebandVersion(void) | |
| { | |
| static char ret[16]; | |
| int retry; | |
| int fd; | |
| int len; | |
| char *p, *ptr; | |
| retry = 0; | |
| ret[15] = '\0'; | |
| ret[0] = '\0'; | |
| fd = InitConn(SPEED); | |
| AT(fd); | |
| do { | |
| SendStrCmd(fd, "AT+XGENDATA\r"); | |
| len = ReadResp(fd, 0, 100000); | |
| if (len) { | |
| if (len > 0) { | |
| ptr = strstr(readbuf, "ICE3_MODEM_"); | |
| if (ptr) { | |
| strncpy(ret, ptr + 11, 15); | |
| for (p = ret; *p; p++) { | |
| if (*p == '_') { | |
| *p = '\0'; | |
| break; | |
| } | |
| } | |
| break; | |
| } | |
| } else { | |
| AT(fd); | |
| } | |
| } | |
| } while (++retry != 50); | |
| close(fd); | |
| DBG("%s BasebandVersion got [%s]\n", timestamp(), ret); | |
| return ret; | |
| } | |
| int | |
| atprog(const char *cmds[], int num) | |
| { | |
| int i, j; | |
| int fd; | |
| fd = InitConn(SPEED); | |
| if (!AT(fd)) { | |
| return -1; | |
| } | |
| for (i = 0; i < num; i++) { | |
| DBG("%s atprog -> %.*s\n", timestamp(), 16, cmds[i]); | |
| int txlen; | |
| char *buf = malloc(strlen(cmds[i]) + 7); | |
| strcpy(buf, cmds[i]); | |
| txlen = strlen(buf); | |
| if (buf[txlen - 1] == '\n') { | |
| buf[txlen - 1] = '\0'; | |
| } | |
| strcat(buf, "\r"); | |
| txlen = strlen(buf); | |
| if (txlen) { | |
| j = 0; | |
| forever { | |
| DBG("%s atprog... send\n", timestamp()); | |
| SendStrCmd(fd, buf); | |
| if (ReadResp(fd, 0, 100000) > 0) | |
| break; | |
| DBG("%s atprog... RETRY\n", timestamp()); | |
| AT(fd); | |
| ++j; | |
| AT(fd); | |
| if (j == 51) | |
| { | |
| DBG("%s atprog... TIMEOUT?\n", timestamp()); | |
| goto done; | |
| } | |
| } | |
| free(buf); | |
| } | |
| } | |
| done: | |
| close(fd); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment