Files
minisrv/zefie_wtvp_minisrv/includes/ServiceDeps/wtv-1800/tellyscripts/base.template.tsf
2025-02-23 12:04:27 -05:00

1688 lines
48 KiB
Plaintext

/* TLLY ver=77 */
/* *=* Copyright 1996, 1997 WebTV Networks, Inc. All rights reserved. */
#ifndef FIJI
/*
* This is the "base" TellyScript Fragment. It is suppressed for FIJI
* (see comments below).
*
* This has all of the generic stuff. Fragments for each ISP should be
* appended to this one, along with the "PatternDial" function generated
* by the server.
*
* ---
*
* v1.0 (e.g. build 105+) is version() 5 (phoneSettings len = 105)
* v1.1 (e.g. build 253+) is version() 8 (phoneSettings len = 172)
* v1.2 (e.g. build 430+) is version() 9 (phoneSettings len = 336)
* v1.3 (e.g. build 1040+) is version() 9 (phoneSettings len = 336?)
* v1.4 (e.g. build 1150+) is version() 11?? (phoneSettings len = 344)
* v2.0 (e.g. build 2039+) is version() ? (phoneSettings len = ?)
* v2.1 (e.g. build 3000+) is version() 11 (phoneSettings len = ?)
* v2.2 (e.g. build 3300+) is version() 11? (phoneSettings len = ?)
*
* ---
*
* TellyScript is a lot like C, but there are a few things that the
* interpreter doesn't know about:
* const, volatile, static, extern
* switch, case, default, goto, do, continue
* long (use "int"), short, float, double, void
* Return types on functions (they just return 4-byte "int")
* Global "char blah[xx]" statements (they end up with a size of 4)
* Initialized globals ("int foo = 0" ends up as 1??)
* "if (0 && something-else)" will evaluate "something-else"
* Typecasts (don't use "(char*)foo"... assume everything is 4 bytes here)
* Bitwise '|', '&', and '^'
* Some of the intrinsics are kinda lame:
* printf() understands "%l" and "%d" but not "%ld"
* sprintf() doesn't understand things like "%.31s"
* sprintf(foostr, "%s", mystring) expands '%' chars in "mystring" (!!)
*
* Be sure to put braces around all parts of else-if clauses; in some
* cases a "return" won't come all the way out if you don't.
*
* By convention, intrinsic function names are entirely lower case, and
* script-defined function names are mixed.
*
* ---
*
* As of the "Funk" service, a limited form of pre-processing is done. We
* allow:
*
* #ifdef CLASSIC
* #ifndef CLASSIC
* #else
* #endif
* #if 1
* #if 0
*
* We silently remove:
* #include ...
*
* All directives MUST be left-aligned. Nested #ifdefs are allowed.
* Extra spaces or tab characters between the "#if" or "#ifdef" and the
* label are NOT allowed, and "# ifdef" is NOT valid.
*
* It's okay to put comments on the lines, or write "#endif FOO".
*
* ---
*
* The Rockwell chipset appears to have a 64-character line buffer. Each
* individual command (i.e. stuff that starts with "AT" and ends with "\r")
* has to fit, or the end will be truncated.
*
* ---
*
* The dial settings are copied out of NVRAM. For 1.0 boxes this was
* broken (it copied sizeof(struct), so 1.0 boot ROMs don't give you
* access to more recent fields), but a workaround exists in the
* GetPhoneSettings function.
*
* char* callWaitingPrefix = &settings[0];
* char* dialOutsidePrefix = &settings[32];
* char* accessNumber = settings[64];
* char usePulseDialing = settings[96];
* char audibleDialing = settings[97];
* char disableCallWaiting = settings[98];
* char dialOutsideLine = settings[99];
* char changedCity = settings[100];
* char waitForTone = settings[101];
* char hasCallWaiting = settings[102]; \* never used? *\
* char useCallWaitingHack = settings[103];
* char dialSpeed = settings[104];
* char cwSensitivity = settings[105]; \* version >= 7 *\
* char brokenPBX = settings[106]; \* version >= 8 *\
* char access800 = settings[108]; \* version >= 8 *\
* char* dialLDPrefix = &settings[140]; \* version >= 8 *\
* char* openISPPhoneNumber = &settings[172]; \* version >= 9 *\
* char* openISPPassword = &settings[204]; \* version >= 9 *\
* char* openISPUserName = &settings[236]; \* version >= 9 *\
* char* openISPProviderName = &settings[268]; \* version >= 9 *\
* char openISPOn = settings[300]; \* version >= 9 *\
* char* openISPPhoneNumber2 = &settings[304]; \* version >= 9 *\
* char* featureFlags = &settings[336]; \* version >= 11 *\
* char* maxFeatureFlag = &settings[340]l; \* version >= 11 *\
*
* ---
* The fiji client is short of NVRAM. Accordingly, we have preloaded all of
* ver 65 of base.tsf. All of the functionality has been replaced by
* preloaded functions, which are somewhat like intrinsics, but expressed
* in tellyscript, rather than C. They can thus call back into downloaded
* functions.
*
* Any calling in either direction between preloaded functions and
* downloaded functions requires that the function names not be abbreviated.
* However, we don't want to lose the benefits of name abbreviation for
* non-Fiji clients. We accomplish this as follows:
* - functions which are called by generated code retain their names and
* so they are added to the list of identifiers immune to abbreviation.
* (Compression will mitigate the effects of this somewhat).
* - functions not in the above list, and which may be downloaded to be
* called by preloaded functions have names which start with an underscore,
* and we suppress abbreviation for such names.
*
* We use this to allow any function to be overridden, as follows.
*
* Each of the preloaded functions calls, as its first action, a hook function.
* The name of the hook function is that of the original function, but with
* an underscore prefix. If the hook function is unimplemented (or returns the
* "unimplemented" value 0x42554646) the preloaded function will return
* immediately. This allows any or all of the functions to be overridden or
* supplemented by downloaded code.
*
* As a consequence of all of this, all of this file is simply suppressed
* for Fiji. For efficiency, this is done by one mondo #ifndef. (We're inside
* it right now.
*
* Bear in mind that if you make a change it won't automatically happen for Fiji
* clients. If you want to make a change for Fiji, you may have to add to the
* list of names for which abbreviation is suppressed.
*
* 1999/09/10 -- rule of thumb: anything added to base.tsf that is referenced
* by generated code MUST be included for FIJI as well. If you add a couple
* of globals that are set up by InitGeneratedValues, they MUST be made
* visible to FIJI.
*/
/*
* Globals. Don't count on these being initialized to zero, and don't give
* them static initializers.
*/
int gDTERate; /* connection stats, set by ParseResult() */
int gDCERate;
int gProtocol;
int gCompression;
int gConnected; /* set to 1 by ParseResult if we're considered connected */
int gUsingOpenISP; /* are we an OpenISP script? */
int gNVRAMMayBeInvalid; /* was the script sent down for a brain-dead download?*/
char* gCHAPSecret; /* box's CHAP secret, embedded in script by the service */
char* gUsername; /* box's username for login, embedded in script by the
* service */
char* gPAPPassword; /* box's PAP password, embedded in script by the
* service */
int gEnable56K; /* if set, allow 56K connections; if not, don't */
int gDisguiseRate; /* if set, reverse the DTE and DCE rates */
int gFlexKnob=5; /* 56k knob for Rockwell, 5=most aggressive (default) */
#endif /*!FIJI*/
/* FIJI doesn't have these built-in */
int gBlock911=1; /* This flag is now set for all services. */
int gWantsVideoAd; /* if set, user wants to download Video Ads */
/* This flag is not needed anymore, left here for future use */
#ifndef FIJI
/*
* ===========================================================================
* Misc utility functions (some of which are now intrinsics)
* ===========================================================================
*/
/*
* WinkDTR - bounce DTR down then up, to get the modem into a happy state.
*/
WinkDTR()
{
setdtr(0);
delay(30);
setdtr(1);
delay(30);
return 0;
}
/*
* StrLen - there's no strlen() intrinsic (in versions < 7).
*/
StrLen(char* str)
{
int len = 0;
while (*str++)
len++;
return len;
}
/*
* StrnCpy - ain't no strncpy() either (at least not for versions < 7).
*/
StrnCpy(char* dstStr, char* srcStr, int count)
{
while (*srcStr) {
if (!count--)
break;
*dstStr++ = *srcStr++;
}
if (count > 0) /* if src finished first, null-terminate the target */
*dstStr = 0;
return 0; /* for ANSI this would return dstStr */
}
/*
* 018647
* PatternCmp - compare a pattern to two supplied strings.. this is particularly
* useful for detecting 911 patterns.
*/
PatternCmp(char* pattern, char* prefix, char* number)
{
char *oldpattern = pattern;
char *oldprefix = prefix;
char *oldnumber = number;
while(*pattern){
if(*prefix){
if(*prefix != ',') {
if(*pattern != *prefix) { return 0;}
prefix++;
} else { if(*number) {
if(*pattern != *number) {
pattern = oldpattern;
number = oldnumber;
while(*pattern){
if(*pattern != *number) {return 0;}
number++;pattern++;
}return 1;
}
prefix++; number++;
} else { return 0;}
}
}else if(*number) {
if(*pattern != *number) { return 0;}
number++;
} else { return 0;}
pattern++;
}
return 1;
}
/*
* OStrChr - like strchr(), but returns an offset instead of a pointer.
* Returns -1 if not found.
*
* This does NOT treat the '\0' as part of the string. Sorry.
*
* Note the real strchr() intrinsic was added in version 8 or 9.
*/
OStrChr(char* s, int c)
{
char* orig = s;
while (*s != '\0') {
if (*s == c)
return s - orig;
s++;
}
return -1;
}
/*
* Test to see if the idx'th bit in "flags" is set. Bit 0 is the LSB.
* (The interpreter doesn't have bitwise operations.)
*/
BitTest(int flags, int idx)
{
while (idx > 0) {
flags = flags / 2;
idx--;
}
return flags % 2;
}
/*
* SetProgress - shorthand notation for three intrinsic calls:
*
* setprogresstext(message)
* setprogresspercentage(percent)
* setprogressdirty(1)
*/
SetProgress(char* message, int percent)
{
setprogresstext(message);
setprogresspercentage(percent);
setprogressdirty(1);
return 0;
}
/*
* GetPhoneSettings - hairy replacement for getphonesettings(). The values
* pointed to by this should ONLY be used for 1.1 and later options. For
* access to options present in client 1.0, you MUST use getphonesettings()
* instead. (Like C, TellyScripts are case-sensitive.)
*
* Get the phone settings. For 1.1 and later clients, we can just use
* the getphonesettings() intrinsic. For 1.0 clients, getphonesettings()
* copied sizeof(struct) rather than everything that was there, so 1.0
* boxes can't see anything added after 1.0. (This wouldn't be a big
* problem, except that the boot ROM is effectively a 1.0 client.)
*
* We work around the problem by finding the phone options in NVRAM. The
* trick is to avoid doing this when NVRAM is invalid (such as when we're
* doing a brain-dead flash download), and also to figure out what version
* of the client wrote the phone settings.
*
* As an added obstacle, editing the phone options on a box only changes
* the copy in RAM. If they've made changes, but haven't rebooted, we
* need to use the copy in RAM instead of the copy in NVRAM. As a general
* rule, we only use the NVRAM copy if the version that wrote the phone
* settings is different from the current version. I'm not *quite* sure
* how things look right after an upgrade, when the box converts the old
* options to the new format, initializing fields and whatever else. We
* might end up looking at older data on the first boot. We can fix this
* for the upgrade case by checking to see if the settings are *older*
* than the current rev, but the downgrade case looks just like a flash dl.
*
* But wait, there's more. A user doing a flash download could use the
* manual configuration options to specify an access number. If we're
* looking at NVRAM, we can't see it. The solution is to always use the
* getphonesettings() pointer for 1.0 options, and use the GetPhoneSettings
* pointer for 1.1 and later options. (Since the boot ROM is 1.0, by
* definition it can't see the later options, so there's no risk of them
* being changed.)
*
* We have to be careful that we don't go wandering through NVRAM on a
* brain-dead box. Since we never give an OpenISP script to zombies,
* we can freely do this in conjunction with OpenISP, but have to be
* very careful otherwise. Be sure gNVRAMMayBeInvalid is initialized
* correctly before calling this.
*
* Returns 0 on error.
*/
GetPhoneSettings(int* pSettingsVersion)
{
int offset;
int *len_ptr;
int *tag;
int *rom_size = 0xbf00000c;
int *rom_end;
*pSettingsVersion = 0;
/*
* If we're new enough, or we're brain-dead, return our own version
* and just use the intrinsic function.
*/
if (version() >= 9 || gNVRAMMayBeInvalid) {
*pSettingsVersion = version();
return getphonesettings();
}
/* use the Code de Rubin to find the 'FONE' chunk */
if (*rom_size == 0x80000) {
/* two mb ROM */
offset = 0xbf1fc000;
rom_end = 0xbf200000;
} else if (*rom_size == 0x100000) {
/* four mb ROM */
offset = 0xbf3fc000;
rom_end = 0xbf400000;
} else {
printf("TS: couldn't get size of ROM");
return 0;
}
offset = offset + 16; /* skip past NVRAM header */
while( (offset + 9) < rom_end) {
len_ptr = offset;
tag = offset + 4;
if (*tag == 0x464f4e45) {
if (*len_ptr == 105)
*pSettingsVersion = 5;
else if (*len_ptr == 172)
*pSettingsVersion = 8;
else if (*len_ptr == 336)
*pSettingsVersion = 9;
else if (*len_ptr == 344)
*pSettingsVersion = 11;
else
*pSettingsVersion = version(); /* punt... this is BAD */
printf("TS: FONE@%x, len=%d, vers=%d",
offset+8, *len_ptr, *pSettingsVersion);
/* if the versions match, return the RAM copy */
if (*pSettingsVersion == version()) {
return getphonesettings();
} else {
return offset + 8;
}
}
offset = offset + *len_ptr + 8;
offset = offset - (offset % 4);
}
/*
* We didn't find it in NVRAM. The only way this should be possible
* is if they just did a 32768, and the in-RAM copy of the settings
* hasn't been flushed out yet.
*/
*pSettingsVersion = version();
return getphonesettings();
}
/*
* ===========================================================================
* Initializing
* ===========================================================================
*/
#ifndef CLASSIC
/*
* GetHardwareInfo - figure out some things about the platform we're
* running on.
*
* "*pIsEarlyK56" is set if we're using Rockwell's v1.0 K56 firmware.
* "*pAcceptsS220" is set if the modem recognizes S220 as a valid S-register.
*
* Assumes that the modem is happy and in V1E0 (verbose result code, no
* echo) mode.
*
* NOTE: we don't really check for and try to handle the case where the
* modem goes out to lunch and we're hitting the getline() timeouts. Since
* we've already talked to the modem a little before getting here, I think
* it's safe to assume that we won't fail here and then succeed later. If
* the information we get from this function is more critical than what we
* have now, we should be more careful.
*
* Returns 0 if all went well, nonzero on error.
*/
GetHardwareInfo(int* pIsEarlyK56, int* pAcceptsS220, int* pIsRockwell,
int* pAcceptsAmpP, int* pAcceptsPlusMR)
{
char resultBuf[64];
/* look for v1.0 Rockwell K56 firmware... if found, limit to <= V.34 */
flush();
sendstr("ATI3\r"); /* modem firmware query */
printf("TS: SENT ATI3");
getline(resultBuf, 63, 300); /* throw out the first one */
if (!getline(resultBuf, 63, 300)) /* keep 2nd; note it has leading '\r' */
return 1;
printf("TS: fw query got '%s'", resultBuf+1);
setfirmwareversion(resultBuf+1);
resultBuf[21] = '\0'; /* me falta strncmp in 1.0 */
*pIsEarlyK56 = 0;
if (strcmp(resultBuf+1, "V1.001_WEBTV-K56_DLP") == 0)
*pIsEarlyK56 = 1;
/*
* Softmodem can't handle AT+MS, so try to detect Rockwell. Sadly,
* there doesn't seem to be a simple way to do this.
*/
*pIsRockwell = 0;
if (strcmp(resultBuf+11, "TV-K56_DLP") == 0)
*pIsRockwell = 1;
resultBuf[15] = '\0'; /* do we have strncmp in 2.0? */
if (strcmp(resultBuf+8, "K56_DLP") == 0) /* V2.200-K56_DLP_RAM */
*pIsRockwell = 1;
printf("TS: isRockwell=%d", *pIsRockwell);
/* see if it's a Rockwell that supports +MR */
*pAcceptsPlusMR = 0;
if (*pIsRockwell) {
flush();
sendstr("AT+MR=0\r");
getline(resultBuf, 63, 300); /* throw out 1st */
if (!getline(resultBuf, 63, 300)) /* keep 2nd */
return 1;
printf("TS: +MR=0 test returned '%s'", resultBuf+1);
if (strcmp(resultBuf+1, "OK") == 0)
*pAcceptsPlusMR = 1;
}
/* see if it will take an S220 command */
flush();
sendstr("ATS220=0\r"); /* JP CW --> extremely insensitive */
printf("TS: SENT ATS220=0");
getline(resultBuf, 63, 300); /* throw out 1st */
if (!getline(resultBuf, 63, 300)) /* keep 2nd */
return 1;
printf("TS: S220 test returned '%s'", resultBuf+1);
*pAcceptsS220 = 0;
if (strcmp(resultBuf+1, "OK") == 0)
*pAcceptsS220 = 1;
/* see if it will take an &Pn command -- desktop Supras won't */
flush();
sendstr("AT&P0\r");
printf("TS: SENT AT&P0");
getline(resultBuf, 63, 300); /* throw out 1st */
if (!getline(resultBuf, 63, 300)) /* keep 2nd */
return 1;
printf("TS: AT&P0 test returned '%s'", resultBuf+1);
*pAcceptsAmpP = 0;
if (strcmp(resultBuf+1, "OK") == 0)
*pAcceptsAmpP = 1;
return 0;
}
#endif
/*
* Initialize - set up the modem configuration and dialing commands, and
* set some options to defaults. Does not talk to the modem.
*
* Some of this assumes a Rockwell modem, some is generic.
*
* "staticConfigBuf" will be filled in with the commands that never
* change. "dynamicConfigBuf" gets the commands that are based on the
* user settings. The split is largely historical, but serves as a
* convenient way to keep the total length of each command under 64 chars.
*/
Initialize(char* staticConfigBuf, char* dynamicConfigBuf)
{
int settingsVersion;
char *settings = getphonesettings();
char *extendedSettings = GetPhoneSettings(&settingsVersion);
char audibleDialing = settings[97];
char waitForTone = settings[101];
char useCallWaitingHack = settings[103];
char dialSpeed = settings[104];
char cwSensitivity = extendedSettings[105]; /* version >= 7 */
char *cwValue = "14";
#ifndef CLASSIC
char *s220Value;
int isEarlyK56, acceptsS220, isRockwell, acceptsAmpP, acceptsPlusMR;
char *flexKnobStr; /* sairam testing */
#endif
/*
* Talk to the modem.
*/
enablemodem(); /* turn on ints */
setflowcontrol(3); /* hardware flow */
setbaud(57600); /* meaningless except for Mac simulator */
/* check to see if the modem is on speaking terms */
if (SendAndWaitForOK("AT&D2V1E0\r", "OK"))
return 3; /* kTellyConfigurationError */
#ifndef CLASSIC
/* figure out what we got? */
if (GetHardwareInfo(&isEarlyK56, &acceptsS220, &isRockwell, &acceptsAmpP,
&acceptsPlusMR))
return 3; /* kTellyConfigurationError */
if (isEarlyK56)
printf("TS: found v1.0 K56 fw, disabling 56K");
strcpy(staticConfigBuf, "AT");
if (isRockwell) {
if (isEarlyK56 || !gEnable56K) {
strcat(staticConfigBuf, "+MS=11,1"); /* disable 56K */
}
/*
else {
/+ Rockwell 56k Aggressiveness knob - sairam testing +/
if (isRockwell) {
sprintf(staticConfigBuf+2, "!0049=0%d", gFlexKnob);
printf("TS: setting 56k knob to %d", gFlexKnob);
}
}
*/
} else {
/* assume softmodem */
if (!gEnable56K) {
strcat(staticConfigBuf, "S51=31"); /* disable 56K */
}
}
if (acceptsPlusMR) /* suppress extended result codes we don't parse */
strcat(staticConfigBuf, "+MR=0");
#else
strcpy(staticConfigBuf, "AT"); /* CLASSIC doesn't support 56K */
#endif
/*
* Modem configuration. This sets things so we connect with V.34 only,
* and at 14.4Kbps or better. (970129: I've removed the +MS command
* in favor of handling it explicitly, because it takes a full minute
* for the modem to drop, and it gets blended into the "no carrier"
* stats.)
*
* We set V1 here and V0 later because the modem can be a little groggy
* after a reset, and returns OK even though V0 was set.
*
* If we were still doing this, "+MS=11,1,14400" is the correct string.
* The "demo" service should use "+MS=11,1,9600" instead.
*
* The "\N2" forces &Q5, but I'm leaving &Q5 in so that if we remove
* the \N2 later we won't forget to put the &Q5 back in. [ Q5 has
* returned while we evaluate the #of disconnects ]
*/
strcat(staticConfigBuf, "S38=0S30=180S95=36&D2V1E0L3&Q5&K3\r");
/* set default dialing string */
strcpy(dynamicConfigBuf, "ATV0");
/* handle audible dialing */
/* check that connectingwithvideoad() returns 1, because
* 0 or 0x42554646 mean false (the big number is from unimplemented)
*/
if (audibleDialing && (connectingwithvideoad() != 1))
strcat(dynamicConfigBuf, "M1");
else
strcat(dynamicConfigBuf, "M0");
/* add blind dialing */
if (waitForTone)
strcat(dynamicConfigBuf, "S6=10X4");
else
strcat(dynamicConfigBuf, "S6=4X3");
/* handle call waiting hack; default value of "14" means "off" */
if (settingsVersion >= 7) {
if (useCallWaitingHack) {
if (cwSensitivity == 1) /* most likely to hang up */
cwValue = "113";
else if (cwSensitivity == 2)
cwValue = "116";
else if (cwSensitivity == 3)
cwValue = "88";
else if (cwSensitivity == 4) /* most likely to ignore calls */
cwValue = "92";
else
cwValue = "92";
}
} else {
if (useCallWaitingHack)
cwValue = "92";
}
printf("TS: vers=%d/%d, cw-hack=%d, cw-sens=%d, setting S10=%s",
version(), settingsVersion, useCallWaitingHack, cwSensitivity, cwValue);
strcat(dynamicConfigBuf, "S10=");
strcat(dynamicConfigBuf, cwValue);
#ifndef CLASSIC
/* set the JP "catch-phone" sensitivity; this is *in addition* to S10 */
if (acceptsS220) {
if (cwSensitivity == 1) /* most likely to hang up */
s220Value = "32";
else if (cwSensitivity == 2)
s220Value = "21";
else if (cwSensitivity == 3)
s220Value = "11";
else /* == 4 or bogus */ /* most likely to ignore calls */
s220Value = "1";
printf("TS: setting S220=%s", s220Value);
strcat(dynamicConfigBuf, "S220=");
strcat(dynamicConfigBuf, s220Value);
} else {
printf("TS: not setting S220"); /* CLASSIC boxes; others? */
}
#endif
/*
* Set the dial speed.
*/
if (dialSpeed == 0) {
strcat(dynamicConfigBuf, "S11=200"); /* slow */
} else if (dialSpeed == 1) {
strcat(dynamicConfigBuf, "S11=110"); /* medium */
} else if (dialSpeed == 2) {
strcat(dynamicConfigBuf, "S11=60"); /* fast */
} else if (dialSpeed == 3) {
strcat(dynamicConfigBuf, "S11=1"); /* blazing (not in UI) */
}
#ifndef CLASSIC
/*
* Set the pulse speed. &P0 is default for US, but we use JP pulse
* values for now since they seem to work anyway. Some desktop Supra
* modems don't understand "&Pn", and will fail to configure, so we
* use the "acceptsAmpP" auto-detect value.
*/
if (acceptsAmpP) {
if (dialSpeed == 0 || dialSpeed == 1) {
strcat(dynamicConfigBuf, "&P1"); /* 10PPS 33% */
} else if (dialSpeed == 2 || dialSpeed == 3) {
strcat(dynamicConfigBuf, "&P3"); /* 20PPS 33% */
}
}
#endif
/* put a carriage return on the end */
strcat(dynamicConfigBuf, "\r");
/* (this is now generated) */
/*setnameservice(0xcf4cb483, 0xce439805);*/
/*
* Set the default window size. It should already be this, but there's
* little harm in being paranoid.
*/
setwindowsize(7);
return 0;
}
/*
* GetDialingPrefix - figure out what needs to be in the dialing prefix.
*
* The string will be a combination of the call waiting prefix and the
* outside line prefix. If we can't find anything to put in the string
* (i.e. no prefixes have been specified), the buffer will be set empty
* (i.e. start with '\0').
*
* This function doesn't talk to the modem; it just builds the string.
*
* "prefixBuffer" must be able to hold the cw prefix (31 bytes), the
* outside line prefix (16 bytes), and a terminating null. Total 48 bytes.
*/
GetDialingPrefix(char* prefixBuffer, int isLocal)
{
int settingsVersion;
char *settings = getphonesettings();
char *extendedSettings = GetPhoneSettings(&settingsVersion);
char *callWaitingPrefix = &settings[0];
char *dialOutsidePrefix = &settings[32];
char disableCallWaiting = settings[98];
char dialOutsideLine = settings[99];
char *dialLDPrefix = &extendedSettings[140]; /* version >= 8 */
prefixBuffer[0] = '\0';
/* handle a special char sequence to disable call waiting */
if (disableCallWaiting)
strcat(prefixBuffer, callWaitingPrefix);
/* use LD prefix or normal dial-outside-line prefix as appropriate */
if (settingsVersion >= 8) {
if (dialLDPrefix[0] && !isLocal) {
printf("TS: Using LD prefix");
strcat(prefixBuffer, dialLDPrefix);
strcat(prefixBuffer, ",");
} else {
if (dialOutsideLine) {
strcat(prefixBuffer, dialOutsidePrefix);
strcat(prefixBuffer, ",");
}
}
} else {
if (dialOutsideLine) {
strcat(prefixBuffer, dialOutsidePrefix);
strcat(prefixBuffer, ",");
}
}
return 0;
}
/*
* SendAndWaitForOK - send a string to the modem and wait for the "OK"
* response.
*
* Retries "retryCount" times, waiting for two seconds and bouncing DTR
* down and up between each.
*
* Returns 0 on success, nonzero on failure.
*/
SendAndWaitForOK(char* str, char* okstr)
{
int retries = 0;
while (retries++ < 4) {
flush(); /* flush data that's pending *from* the modem */
sendstr(str);
if (waitfor(okstr, StrLen(okstr), 120)) {
printf("TS: SENT config str '%s'", str);
break;
} else {
printf("TS: TIMEOUT waiting for OK (str='%s')", str);
WinkDTR();
}
}
if (retries >= 4 ) {
printf("TS: Couldn't get '%s' from modem", okstr);
setdtr(0);
return 3;
}
return 0;
}
/*
* InitModem - initialize the modem with "staticConfig" and "dynamicConfig".
* We do this before each time we dial.
*
* IMPORTANT: there is an assumption we're making that dropping DTR doesn't
* erase the stuff we've already sent (i.e. by reinitializing the modem).
* If it does, retries for the second string will undo the first string.
*
* Returns 0 on success. Returns nonzero and drops DTR on failure.
*/
InitModem(char* staticConfig, char* dynamicConfig)
{
setstatus(6); /* kTellyInitializingModem */
SP_PreparingToCall(13);
WinkDTR();
if (SendAndWaitForOK(staticConfig, "OK")) {
setdtr(0);
return 3; /* kTellyConfigurationError */
}
/* this assumes "dynamicConfig" enables numeric result codes */
if (SendAndWaitForOK(dynamicConfig, "0")) {
setdtr(0);
return 3; /* kTellyConfigurationError */
}
/* turn off a bad idea */
/*printf("TS: Overriding exclusion circuit...");*/
setforcehook(1);
return(0);
}
/*
* ===========================================================================
* Dialing
* ===========================================================================
*/
/*
* ParseResult - parse the return code from the modem.
*
* This is expected to work on Rockwell-based modems only. Other modems
* should implement the modem_parseresult intrinsic.
*/
ParseResult(int result)
{
int retcode;
char* comment = "";
#ifndef CLASSIC /* no CLASSIC box supports modem_parsersult() */
retcode = modem_parseresult(&result, &gDTERate, &gDCERate, &gCompression,
&gProtocol, &gConnected, &comment);
if (retcode != 0x42554646) {
printf("TS: parseresult -- %d %s (retcode=%d)", result,
comment, retcode);
if (gDCERate && gDCERate < 14400) {
retcode = 14; /* kTellyVerySlowConnect */
}
return retcode;
}
#endif
retcode = 0;
if (result == 0) /* OK */
{
comment = " OK";
retcode = 1; /* okay */
}
else if (result == 3) /* NO CARRIER */
{
comment = "NO CARRIER";
retcode = 12; /* kTellyNoCarrier */
}
else if (result == 6) /* NO DIALTONE */
{
comment = "NO DIALTONE";
retcode = 5; /* kTellyNoDialtone */
}
else if (result == 7) /* BUSY */
{
comment = "BUSY";
retcode = 7; /* kTellyBusy */
}
else if (result == 8) /* NO ANSWER */
{
comment = "NO ANSWER";
retcode = 6; /* kTellyNoAnswer */
}
else if (result >= 18 && result <= 19) /* CONNECT 57600 and 115200 */
{
comment = "Connected!";
gConnected = 1;
gDTERate = 57600 * (result - 17);
}
else if (result == 20) /* CONNECT 230400 */
{
comment = "Connected!";
gConnected = 1;
gDTERate = 230400;
}
else if (result >= 47 && result <= 51) /* CARRIER 2400 - CARRIER 12000 */
{
gDCERate = 2400 * (result - 46);
retcode = 14; /* kTellyVerySlowConnect */
}
else if (result >= 52 && result <= 58) /* CARRIER 14400 - CARRIER 28800 */
{
gDCERate = 2400 * (result - 46);
}
else if (result == 66) /* COMPRESSION: CLASS 5 */
{
gCompression = 1;
}
else if (result == 67) /* COMPRESSION: V.42bis */
{
gCompression = 2;
}
else if (result == 69) /* COMPRESSION: NONE */
{
gCompression = 0;
}
else if (result == 76) /* PROTOCOL: NONE */
{
gProtocol = 0;
}
else if (result == 77) /* PROTOCOL: LAPM */
{
gProtocol = 1;
}
else if (result == 78 || result == 60) /* CARRIER 31200 */
{
gDCERate = 31200;
}
else if (result == 79 || result == 65) /* CARRIER 33600 */
{
gDCERate = 33600;
}
else if (result == 80) /* PROTOCOL: ALT */
{
gProtocol = 2;
}
else if (result == 81) /* PROTOCOL: ALT-CELLULAR */
{
gProtocol = 3;
}
else if (result >= 150 && result <= 162) /* CARRIER 32000 - 56000 (K56) */
{
gDCERate = 2000 * (result - 134);
}
else
{
printf("TS: ParseResult -- %d unknown", result);
retcode = 9; /* kTellyUnknown */
}
printf("TS: ParseResult -- %d %s (retcode=%d)", result,
comment, retcode);
return retcode;
}
/*
* DialModem - dial "numberToDial" after first sending some optional
* dial prefixes.
*
* "isLocal" is needed to make dialLDPrefix work right.
*
* NOTE: the UI restricts the fields as follows:
* dial prefix 16 bytes (32-char buffer)
* cw prefix 31 bytes (32-char buffer)
* access number 31 bytes (32-char buffer)
*
* Returns 0 on success.
*/
DialModem(char* numberToDial, int isLocal)
{
int settingsVersion;
char *settings = getphonesettings();
char *extendedSettings = GetPhoneSettings(&settingsVersion);
char *accessNumber = &settings[64];
char usePulseDialing = settings[96];
char brokenPBX = extendedSettings[106]; /* version >= 8 */
int isTollFree, dollarOffset;
char prefixBuffer[64]; /* see GetDialingPrefix for size recommendation */
char* prefixStr; /* points into prefixBuffer */
char* afterDollar;
char buffer[32];
/*
* Set the working number. This is used by the phone logs and by
* the "&phone;" tag. We want to grab at most 32 chars (64 for
* version >= 9), or setworkingnumber() blows up.
*
* (We hijack "buffer" for a little while.)
*/
if (gUsingOpenISP) {
strcpy(buffer, "ISP-");
StrnCpy(buffer+4, numberToDial, 31-4);
} else {
StrnCpy(buffer, numberToDial, 31);
}
buffer[31] = 0;
setworkingnumber(buffer);
/* is it toll free in this locale (needed for "visible dialing")? */
isTollFree = IsTollFree(numberToDial);
/* figure out if this is one of those fancy "dollar dialing" things */
dollarOffset = OStrChr(accessNumber, '$');
if (dollarOffset >= 0) {
/* copy accessNumber, and split it at the '$' */
strcpy(buffer, accessNumber);
afterDollar = buffer + dollarOffset +1;
buffer[dollarOffset] = '\0';
}
/* strip off the leading digit under certain circumstances */
if (settingsVersion >= 8 && brokenPBX &&
(!accessNumber[0] || dollarOffset >= 0))
{
if (DoStripLeadingDigit(numberToDial)) {
/*printf("TS: BrokenPBX set, stripping digit");*/
numberToDial++;
}
}
/*
* Figure out what the dialing prefix should be. This is a
* combination of the "9," dialing prefix field and the "call
* waiting disable" prefix field. We also sneak the tone/pulse
* dial command into the front of the buffer.
*/
if (usePulseDialing)
strcpy(prefixBuffer, "ATDP");
else
strcpy(prefixBuffer, "ATDT");
prefixStr = prefixBuffer + 4;
GetDialingPrefix(prefixStr, isLocal);
/* do "visible dialing" for version>=8 if it's not toll-free */
/*setstatus(3); * kTellyDialing */
setstatus(7); /* kTellyHandshake */
if (gUsingOpenISP) {
/* always show for OpenISP */
SP_DialingNumber(prefixStr, numberToDial, 26);
} else if (version() >= 8 /*&& audibleDialing*/) {
if (accessNumber[0] && dollarOffset < 0) {
SP_DialingAccessNumber(prefixStr, numberToDial, 26);
} else if (isTollFree) {
SP_DialingWebTV(26);
} else {
/* since this isn't an accessNumber, numberToDial should be short */
SP_DialingNumber(prefixStr, numberToDial, 26);
}
} else {
SP_DialingWebTV(26);
}
/*
* Send the commands to the modem.
*
* Someday we may want to split "prefixBuffer" and "numberToDial"
* so that we detect dialtone after the prefix. This would help
* avoid inadvertent 911 calls.
*/
/* 018647
* Make sure that no 911 pattern is dialled, combination of prefix and number!
*/
if (1) {
if (PatternCmp("911", prefixStr, numberToDial)) {
/* 911 pattern.. inform user!*/
alert("Error 911: Your receiver cannot connect to WebTV. Please contact Customer Care at 1-800-469-3288.", "", 0);
}
}
if ((numberToDial[0] != 'A') && (numberToDial[0] != 'a')) {
sendstr(prefixBuffer);
printf("TS: SENT prefix '%s'", prefixBuffer);
}
if (dollarOffset < 0) {
sendstr(numberToDial);
printf("TS: SENT number '%s'", numberToDial);
} else {
sendstr(buffer);
sendstr(numberToDial);
sendstr(afterDollar);
printf("TS: SENT fancy '%s' '%s' '%s'",
buffer, numberToDial, afterDollar);
}
/* return to command mode after dialing */
sendstr(";\r");
flush(); /* this flushes data *from* the modem... needed here? */
return 0;
}
/*
* WaitForConnect - watch the modem result codes until we're connected.
*
* Returns 0 on success. Returns nonzero and drops DTR on failure.
*/
WaitForConnect()
{
char *settings = getphonesettings();
char audibleDialing = settings[97];
char buffer[32];
int i, result, count;
/* if we fail early, don't report the previous stats */
setconnectionstats(0, 0, 0, 0);
/*
* Loop until we're connected. We'll usually get four results, in this
* order (but not always!):
* 1: OK (dial string was accepted)
* 2: DCE rate (modem speed)
* 3: Compression and err correction (usually v.42bis, which implies v.42)
* 4: DTE rate (serial port speed)
*/
i = 0;
gConnected = 0;
while (!gConnected && i < 6) {
count = getline(buffer, 31, 4200);
i++;
if (count == 0) {
printf("TS: TIMEOUT waiting for modem result");
setdtr(0);
if (i == 1)
return 4; /* kTellyDialingError */
else
return 8; /* kTellyHandshakeFailure */
}
result = ParseResult(atoi(buffer));
if (result == 1) { /* OK */
if (i == 1) {
sendstr("ATD\r");
if (!audibleDialing) {
/* keep it on screen long enough to see it */
delay(180);
}
/*setstatus(7); * kTellyHandshake */
SP_WaitingToConnect(39);
result = 0;
} else {
/* probably garbage from modem that atoi() converted to zero */
setdtr(0);
printf("TS: got odd '%s'", buffer);
return 8; /* kTellyHandshakeFailure */
}
}
if (result != 0) {
/* first one handles the NO ANSWER, NO DIALTONE, etc. */
setdtr(0);
if (result == 12 && i > 2) {
/* NO CARRIER after first result becomes "handshake failure" */
return 8; /* kTellyHandshakeFailure */
}
return result;
}
if (i == 2) {
setstatus(2); /* kTellyCarrier */
if (gUsingOpenISP)
SP_ISPAnswering(52);
else
SP_WebTVAnswering(52);
}
}
printf("TS: dterate=%d, dcerate=%d, prot=%d, comp=%d",
gDTERate, gDCERate, gProtocol, gCompression);
setconnectionstats(gDTERate, gDCERate, gProtocol, gCompression);
return 0;
}
/*
* DialIAP - init the modem, dial the IAP, and report errors as appropriate.
*
* Returns 0 on success, 1 on "roll over" failure, 2 on "stop now" failure.
* The actual failure code is placed into "*pResult".
*
* *pResult will always be set nonzero when the function returns nonzero.
*/
DialIAP(char* staticConfig, char* dynamicConfig, char* iapName, char* number,
int isLocal, int* pResult)
{
*pResult = InitModem(staticConfig, dynamicConfig);
if (*pResult != 0)
return 2; /* couldn't init, bail now */
/* reset globals before each attempt */
gDTERate = gDCERate = gProtocol = gCompression = 0;
printf("TS: Calling %s/%s", iapName, number);
DialModem(number, isLocal);
*pResult = WaitForConnect();
if (*pResult)
printf("TS: dialing failure, result=%d", *pResult);
if (*pResult == 4 || *pResult == 5) {
/* kTellyDialingError or kTellyNoDialtone, bail now */
return 2; /* bail now */
} else if (*pResult) {
/* some other kind of failure; want to try next POP in line */
return 1; /* bail later */
}
return 0; /* success! */
}
/*
* ===========================================================================
* Chatting
* ===========================================================================
*/
/*
* [ ScriptedChat has been excised to reclaim space ]
*/
/*
* CHPAPCHat - common CHAP/PAP chat function.
*
* Call setpapmode(1) or setpapmode(2), then call this with the fully-formed
* user name and password.
*/
CHPAPChat(char* username, char* password)
{
setusername(username);
setpassword(password);
setstatus(5); /* kNegotiatingPPP */
SP_Connecting(88);
if (!startppp()) {
setdtr(0);
if (getpppresult() == 3) { /* authentication failure */
printf("TS: PAP/CHAP auth failure");
return 10;
}
printf("TS: PPP negotiation failed");
return 11;
}
printf("TS: Connected!");
/*printf("TS: DEBUG: %d bytes available on stack", stack());*/
setstatus(1); /* kTellyConnected */
/*
* Check free space remaining. The one place we really need this -- 1.0
* boxes -- is the one place that this trick won't work. :-(
*/
if (stack() < 512) {
printf("WARNING: TS stack low");
SP_StackLow(100);
} else if (gUsingOpenISP)
SP_ConnectedToISP(100);
else
SP_ConnectedToWebTV(100);
return 0;
}
/*
* PAPChat - do a PAP-based login.
*
* Pass in a format string to use for the username. The result from
* getserialnumber() will be placed into the first "%s" in the format.
* If "fixedPassword" is nonzero, it will be used, otherwise the FCS
* of the serial number is sent.
*
* Examples:
* WebTV 800 : PAPChat("wtv_%s", 0);
* UUNET : PAPChat("WTV/%s", 0);
* CNC : PAPChat("%s!webtv", 0);
* CNC (old) : PAPChat("artemis1", "webtv!96");
*
* Returns 0 on success. Returns nonzero and drops DTR on failure.
*/
PAPChat(char* userNameBase, char* fixedPassword)
{
char username[48];
char password[48];
sprintf(username, userNameBase, gUsername);
if (fixedPassword == 0) {
sprintf(password, "%s", gPAPPassword);
} else if (fixedPassword == 1) {
/* pad out to 8 chars for PSI */
sprintf(password, "%08d", computefcs(gUsername));
} else {
strcpy(password, fixedPassword);
}
setpapmode(1);
printf("TS: Using PAP with '%s'/'%s'", username, password);
return CHPAPChat(username, password);
}
/*
* CHAPSupported - does the box support CHAP right now?
*
* Returns a boolean value, set to "true" if the box supports CHAP.
*/
CHAPSupported()
{
int flags;
flags = system_getboxfeatureflags();
if (flags == 0x42554646)
return 0; /* don't support feature flags, must not support CHAP */
/*printf("BoxFeatureFlags = %d", flags);*/
/* feature flag 0 (0x0001) is kBoxHasChap */
if (BitTest(flags, 0))
return 1;
else
return 0;
}
/*
* CHAPChat - do a CHAP-based login.
*
* For now, just use the user name and password passed in, without further
* processing.
*/
CHAPChat(char* userNameBase, char* fixedPassword)
{
char username[48];
char password[48];
/* are we *sure* we support CHAP? */
if (!CHAPSupported()) {
printf("TS: CHAP not supported!");
return 1;
}
sprintf(username, userNameBase, gUsername);
if (fixedPassword == 0)
strcpy(password, gCHAPSecret);
else
strcpy(password, fixedPassword);
setpapmode(2);
printf("TS: Using CHAP with '%s'/'%s'", username, password);
return CHPAPChat(username, password);
}
/*
* ===========================================================================
* Command & Control
* ===========================================================================
*/
/*
* WhatTimeIsIt - figure out what time it is.
*
* The fancy "poptimized" scripts can use different POP lists based on
* the month, day of the week, or hour of the day (useful for peak vs
* off-peak).
*
* This gets a little tricky because we don't know what time it is after
* we lose power, and if we're an FCS boot ROM we don't even have the
* intrinsics defined.
*/
WhatTimeIsIt(int* pMinute, int* pHour, int* pMonth, int* pYear, int* pDayOfWeek)
{
int when, tmpyear;
parsesystemtime(7776000); /* 90 days after Jan 1 1970 */
tmpyear = getyear();
when = getdatetimelocal(); /* time in seconds, adjusted for time zone */
parsesystemtime(when);
if (tmpyear != 1970 || when < 7776000) {
/* either the clock got reset by poweroff, or we're an FCS boot ROM */
printf("TS: time not avail %d/%d", tmpyear, when);
*pDayOfWeek = 3; /* Wednesday */
*pHour = 19; /* 7pm */
*pMinute = 0;
*pMonth = 1; /* January, 1970 */
*pYear = 1970;
return 1;
}
*pDayOfWeek = getdayofweek(); /* 0-6 */
*pHour = gethour(); /* 0-23 */
*pMinute = getminute(); /* 0-60 */
*pMonth = getmonth(); /* 1-12 */
*pYear = getyear(); /* e.g. 1997 */
return 0;
}
/*
* DialByIndex - dial all numbers in a sequence.
*
* This is called from the generated PatternDial function (which has the
* sequence embedded in it), and calls two other generated functions that
* convert an index into data or a function call.
*/
DialByIndex(char* staticConfig, char* dynamicConfig, char* sequence)
{
int status, err, nextNumber, sequenceLen, idx;
if (version() >= 8) {
nextNumber = getconnectretrycount();
} else {
nextNumber = 0;
}
sequenceLen = StrLen(sequence);
printf("TS: next=%d, seqLen=%d", nextNumber, sequenceLen);
/*
* Loop through the (remaining) POPs in the sequence.
*/
err = 13; /* kTellyBlackHole - only used if nextNumber >= sequenceLen */
for (idx = nextNumber; idx < sequenceLen; idx++) {
/*printf("TS: index dialing '%c' (attempt %d)",
sequence[idx], idx);*/
status = DialIndexedPOP(staticConfig, dynamicConfig, sequence[idx],
idx, &err);
/*printf("TS: index dial returned %d, err=%d", status, err);*/
if (status == 0) {
err = ChatWithIndexedProvider(sequence[idx]);
if (!err || idx == sequenceLen-1) {
return err;
} else {
dialerror(err);
#ifndef CLASSIC
/* 101223/093628
* Make sure that MsgWatch calls are
* limited to the primary POP only,
* and to the first trial!
*/
if (idx == nextNumber) {
if (getconnectreason() == 1) {
return err;
}
}
#endif
}
} else if (status == 2 || idx == sequenceLen-1) {
return err;
} else /*status==1*/ {
dialerror(err);
#ifndef CLASSIC
/* 101223/093628
* Make sure that MsgWatch calls are
* limited to the primary POP only
*/
if (idx == nextNumber) {
if (getconnectreason() == 1) {
return err;
}
}
#endif
}
}
return err;
}
/*
* main - tellyscript interpreter starts here.
*
* Initializes the world, then invokes AccessDial or PatternDial. These
* are generated automatically right before the script is sent down.
*
* IMPORTANT: this script can be sent to a 1.2 or later client, and
* suddenly find itself executing on a 1.0 client (the boot ROM). It's
* important that we don't base flow-of-control decisions on interpreter
* version without considering all the effects.
*/
main()
{
char *settings = getphonesettings();
char *accessNumber = &settings[64];
char staticConfig[80];
char dynamicConfig[80];
int start = ticks();
int err, result = 0;
/* init globals that might be overwritten by InitGeneratedValues */
gUsingOpenISP = 0;
gNVRAMMayBeInvalid = 0;
/* do this BEFORE anything else, especially GetPhoneSettings */
err = InitGeneratedValues();
if (err)
return err;
if(version()<9)
MaybePrereg();
err = Initialize(staticConfig, dynamicConfig);
if (err)
return err;
/* take control of the status bar (version >= 8) */
setprogressmode(1);
/* clear these out every time */
setfullpopnumber("");
setconnectionstats(0, 0, 0, 0);
/*printf("DEBUG: at start, num=%d", getconnectretrycount());*/
/*
* If the user has set an access number, we use that to the exclusion
* of all else, unless they're using the magic '$' feature.
*
* (AccessDial and PatternDial are generated automatically.)
*/
if (accessNumber[0] && OStrChr(accessNumber, '$') < 0) {
result = AccessDial(staticConfig, dynamicConfig, accessNumber);
/* don't blow up if the password is wrong (always want this) */
if (result == 10 && !gUsingOpenISP) /* BadPassword */
result = 15; /* BadPasswordNR */
} else {
result = PatternDial(staticConfig, dynamicConfig);
}
if (!result) {
printf("TS: success, in %d sec",
(ticks() - start)/60);
return 2; /* kTellyLinkConnected */
} else {
setconnectretrycount(0); /* temporary fix for 1.3.x */
printf("TS: failure #%d, in %d sec", result,
(ticks() - start)/60);
setdtr(0);
return result;
}
}
#endif /* !FIJI */
/* --- base.tsf END --- */
/*
* Locale-specific stuff for USA.
*/
/*
* ===========================================================================
* Phone-system-specific stuff
* ===========================================================================
*/
/*
* Returns "true" if the number is toll free. This is important because
* we don't want to display "Dialing xxx" when we're making toll free calls.
*/
IsTollFree(char* numberToDial)
{
if ((numberToDial[1]=='8' && numberToDial[2]=='0' && numberToDial[3]=='0')||
(numberToDial[1]=='8' && numberToDial[2]=='8' && numberToDial[3]=='8')||
(numberToDial[1]=='8' && numberToDial[2]=='7' && numberToDial[3]=='7')||
(numberToDial[1]=='8' && numberToDial[2]=='6' && numberToDial[3]=='6')||
(numberToDial[1]=='8' && numberToDial[2]=='5' && numberToDial[3]=='5'))
{
/*printf("DEBUG: that looks like a toll-free number!");*/
return 1;
}
return 0;
}
/*
* Returns "true" if we want to strip off the leading digit. This should
* only be called if the "brokenPBX" flag is set.
*
* This is in "locale.tsf" because we re-used the brokenPBX flag for Japan,
* where we want to strip off the leading 0 when doing testing from the US.
*/
DoStripLeadingDigit(char* numberToDial)
{
if (*numberToDial == '1')
return 1;
else
return 0;
}
/*
* ===========================================================================
* Progress bar messages
* ===========================================================================
*/
SP_PreparingToCall(int perc)
{
SetProgress("Preparing to call", perc);
}
SP_DialingNumber(char* prefixStr, char* numberToDial, int perc)
{
char buffer[128]; /* must hold number(32) + prefix(64) + "Dialing "(8) */
sprintf(buffer, "Dialing %s%s", prefixStr, numberToDial);
SetProgress(buffer, perc);
}
SP_DialingAccessNumber(char* prefixStr, char* numberToDial, int perc)
{
char buffer[128]; /* must hold number(32)+prefix(64)+"Dialing A/N "(12) */
sprintf(buffer, "Dialing A/N %s%s", prefixStr, numberToDial);
SetProgress(buffer, perc);
}
SP_DialingWebTV(int perc)
{
SetProgress("Dialing %ServiceName%...", perc);
}
SP_WaitingToConnect(int perc)
{
SetProgress("Waiting to connect", perc);
}
SP_ISPAnswering(int perc)
{
SetProgress("ISP answering", perc);
}
SP_WebTVAnswering(int perc)
{
SetProgress("%ServiceName% answering", perc);
}
SP_Connecting(int perc)
{
SetProgress("Connecting", perc);
}
SP_ConnectedToISP(int perc)
{
SetProgress("Connecting to your ISP", perc);
}
SP_ConnectedToWebTV(int perc)
{
SetProgress("Connecting to %ServiceName%", perc);
}
SP_StackLow(int perc)
{
SetProgress("Warning: stack low", perc);
}