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