www.pudn.com > slow.zip > main.C
/********************************************************* ********************************************************** main.c ********************************************************** **********************************************************/ /* Modem for MIPS AJF January 1995 Main program */ #include#include #include #include #include #include #include #include #include "modem.h" #define TOFN "/dev/ttyd2" global int numpages; global uint options, bitrates; global vmode veemode; struct vminfo { char *s; vmode v; }; static vminfo vmodes[] = { { "-V21o", V21o }, { "-V21a", V21a }, { "-V23o", V23o }, { "-V23a", V23a }, { "-V32o", V32o }, { "-V34o", V34o }, { NULL, (vmode) 0 }, /* terminator */ }; static char *telno; static void newhandler(), catchsignal(int), sighandler(int); static bool legaltelno(char*); static void setoptions(char**); static uint bitrate(int), legalbps(vmode); static void checkoptions(), usage(int); static void seizeline(), sendanswer(); inline bool isdigit(char ch) { return (ch >= '0') && (ch <= '9'); } global void main(int argc, char **argv) { set_new_handler(newhandler); catchsignal(SIGINT); catchsignal(SIGTERM); catchsignal(SIGUSR1); catchsignal(SIGABRT); setoptions(argv); checkoptions(); if ((options & opt_org) && !legaltelno(telno)) giveup("Illegal telephone number"); if (options & opt_mod) { uint b = legalbps(veemode); unless (options & opt_bps) bitrates = b; /* default is the full set */ if (bitrates & ~b) giveup("illegal mode-bitrate combination"); } if (options & opt_fax) { initdoc(); if (options & opt_org) readdoc(); /* read whole doc before time-critical part */ } openaudio(); atexit(closeaudio); seizeline(); if (options & opt_org) dialnumber(telno); if (options & (opt_fax | opt_mod)) { if (options & opt_org) waitfortone(CONN_TONE); /* wait for answer (connect) tone */ if (options & opt_ans) sendanswer(); /* send answer tone */ int contime = time(NULL); infomsg("Connected"); if (options & opt_v8) startsession(); /* V.8 procedures */ if (options & opt_fax) becomefax(); if (options & opt_mod) becomemodem(); infomsg("Call duration: %d secs", time(NULL) - contime); } if ((options & opt_fax) && !(options & opt_org)) writedoc(); /* write whole doc after time-critical part */ exit(0); } static void newhandler() { giveup("No room"); } static void catchsignal(int sig) { signal(sig, (SIG_PF) sighandler); } static void sighandler(int sig) { switch (sig) { default: giveup("Killed by signal %d.", sig); case SIGUSR1: giveup("Remote modem is not responding."); } } static bool legaltelno(char *vec) { int n = 0; char *dstr = "0123456789*#ABCD"; if (vec[n] == '+' || vec[n] == '=') n++; until (vec[n] == '\0' || strchr(dstr, vec[n]) == NULL) n++; return (n <= 20 && vec[n] == '\0'); } static void setoptions(char **argv) { int ap = 0; unless (argv[ap] == NULL) ap++; options = bitrates = 0; until (argv[ap] == NULL) { char *s = argv[ap++]; if (s[0] == '+' || s[0] == '=') { if (options & opt_org) usage(1); telno = s; options |= opt_org; } else if (seq(s, "-ans")) options |= opt_ans; else if (seq(s, "-fax")) options |= opt_fax; else if (seq(s, "-bps")) { while (argv[ap] != NULL && isdigit(argv[ap][0])) { int bps = atoi(argv[ap++]); bitrates |= bitrate(bps); } options |= opt_bps; } else if (seq(s,"-V8")) options |= opt_v8; else { int k = 0; unless (s[k++] == '-') usage(2); if (s[k] == 'V') { if (options & opt_mod) usage(3); int m = 0; until (vmodes[m].s == NULL || seq(vmodes[m].s, s)) m++; if (vmodes[m].s == NULL) usage(4); veemode = vmodes[m].v; options |= opt_mod; if (veemode == V34o) options |= opt_v8; /* V.34 requires V.8 */ } else { until (s[k] == '\0') { char ch = s[k++]; if (ch == 'v') options |= opt_v; else usage(5); } } } } } static uint bitrate(int n) { /* see bitrates.h */ unless (n >= 2400 && n <= 28800 && n%2400 == 0) giveup("unknown bit rate %d", n); return 1 << (n/2400 - 1); } static uint legalbps(vmode m) { switch (m) { default: return 0; case V32o: return bps_4800 | bps_7200 | bps_9600 | bps_12000 | bps_14400; case V34o: return bps_2400 | bps_4800 | bps_7200 | bps_9600 | bps_12000 | bps_14400 | bps_16800 | bps_19200 | bps_21600 | bps_24000 | bps_26400 | bps_28800; } } static void checkoptions() { unless (options & (opt_org | opt_ans)) usage(6); /* need either org/ans */ unless (~options & (opt_org | opt_ans)) usage(7); /* but not both */ unless (~options & (opt_fax | opt_mod)) usage(8); /* mustn't have both fax and mod */ } static void usage(int n) { fprintf(stderr, "Modem Vsn. 5.1 from \n"); fprintf(stderr, "Usage(%d): modem [-v] [-V8] {- | -fax} [-bps ...] [+ | -ans]\n", n); fprintf(stderr, "Modes:"); for (int i = 0; vmodes[i].s != NULL; i++) fprintf(stderr, " %s", vmodes[i].s); putc('\n', stderr); exit(2); } static void seizeline() { sleep(2); /* wait in case line has only just been dropped */ int fd = open(TOFN, O_RDWR); /* this asserts DTR */ if (fd < 0) giveup("Can't open %s", TOFN); } static void sendanswer() /* send V.25 answer sequence */ { sendpause(2.15); /* silence for 2.15 sec */ sinegen *sgen = new sinegen(2100.0); for (int i = 0; i < 7; i++) { int ns = (int) (0.45 * SAMPLERATE); /* 2100 Hz for 450 ms */ for (int j = 0; j < ns; j++) { float val = sgen -> fnext(); outsample(val); } sgen -> flipphase(); /* flip phase for next segment */ } delete sgen; sendpause(0.075); /* silence for 75 ms */ }