diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/fax/modem.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/fax/modem.c')
-rwxr-xr-x | sys/src/cmd/fax/modem.c | 220 |
1 files changed, 220 insertions, 0 deletions
diff --git a/sys/src/cmd/fax/modem.c b/sys/src/cmd/fax/modem.c new file mode 100755 index 000000000..d0decc3e7 --- /dev/null +++ b/sys/src/cmd/fax/modem.c @@ -0,0 +1,220 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> + +#include "modem.h" + +typedef struct { + char *terse; + char *verbose; + int result; + int (*f)(Modem*); +} ResultCode; + +static ResultCode results[] = { + { "0", "OK", Rok, 0, }, + { "1", "CONNECT", Rconnect, 0, }, + { "2", "RING", Rring, 0, }, + { "3", "NO CARRIER", Rfailure, 0, }, + { "4", "ERROR", Rrerror, 0, }, + { "5", "CONNECT 1200", Rconnect, 0, }, + { "6", "NO DIALTONE", Rfailure, 0, }, + { "7", "BUSY", Rfailure, 0, }, + { "8", "NO ANSWER", Rfailure, 0, }, + { "9", "CONNECT 2400", Rconnect, 0, }, /* MT1432BA */ + { "10", "CONNECT 2400", Rconnect, 0, }, /* Hayes */ + { "11", "CONNECT 4800", Rconnect, 0, }, + { "12", "CONNECT 9600", Rconnect, 0, }, + { "13", "CONNECT 14400",Rconnect, 0, }, + { "23", "CONNECT 1275", Rconnect, 0, }, /* MT1432BA */ + + { "-1", "+FCON", Rcontinue, fcon, }, + { "-1", "+FTSI", Rcontinue, ftsi, }, + { "-1", "+FDCS", Rcontinue, fdcs, }, + { "-1", "+FCFR", Rcontinue, fcfr, }, + { "-1", "+FPTS", Rcontinue, fpts, }, + { "-1", "+FET", Rcontinue, fet, }, + { "-1", "+FHNG", Rcontinue, fhng, }, + + { 0 }, +}; + +void +initmodem(Modem *m, int fd, int cfd, char *type, char *id) +{ + m->fd = fd; + m->cfd = cfd; + if(id == 0) + id = "Plan 9"; + m->id = id; + m->t = type; +} + +int +rawmchar(Modem *m, char *p) +{ + Dir *d; + int n; + + if(m->icount == 0) + m->iptr = m->ibuf; + + if(m->icount){ + *p = *m->iptr++; + m->icount--; + return Eok; + } + + m->iptr = m->ibuf; + + if((d = dirfstat(m->fd)) == nil){ + verbose("rawmchar: dirfstat: %r"); + return seterror(m, Esys); + } + n = d->length; + free(d); + if(n == 0) + return Enoresponse; + + if(n > sizeof(m->ibuf)-1) + n = sizeof(m->ibuf)-1; + if((m->icount = read(m->fd, m->ibuf, n)) <= 0){ + verbose("rawmchar: read: %r"); + m->icount = 0; + return seterror(m, Esys); + } + *p = *m->iptr++; + m->icount--; + + return Eok; +} + +int +getmchar(Modem *m, char *buf, long timeout) +{ + int r, t; + + timeout += time(0); + while((t = time(0)) <= timeout){ + switch(r = rawmchar(m, buf)){ + + case Eok: + return Eok; + + case Enoresponse: + sleep(100); + continue; + + default: + return r; + } + } + verbose("getmchar: time %ud, timeout %ud", t, timeout); + + return seterror(m, Enoresponse); +} + +int +putmchar(Modem *m, char *p) +{ + if(write(m->fd, p, 1) < 0) + return seterror(m, Esys); + return Eok; +} + +/* + * lines terminate with cr-lf + */ +static int +getmline(Modem *m, char *buf, int len, long timeout) +{ + int r, t; + char *e = buf+len-1; + char last = 0; + + timeout += time(0); + while((t = time(0)) <= timeout){ + switch(r = rawmchar(m, buf)){ + + case Eok: + /* ignore ^s ^q which are used for flow */ + if(*buf == '\021' || *buf == '\023') + continue; + if(*buf == '\n'){ + /* ignore nl if its not with a cr */ + if(last == '\r'){ + *buf = 0; + return Eok; + } + continue; + } + last = *buf; + if(*buf == '\r') + continue; + buf++; + if(buf == e){ + *buf = 0; + return Eok; + } + continue; + + case Enoresponse: + sleep(100); + continue; + + default: + return r; + } + } + verbose("getmline: time %ud, timeout %ud", t, timeout); + + return seterror(m, Enoresponse); +} + +int +command(Modem *m, char *s) +{ + verbose("m->: %s", s); + if(fprint(m->fd, "%s\r", s) < 0) + return seterror(m, Esys); + return Eok; +} + +/* + * Read till we see a message or we time out. + * BUG: line lengths not checked; + * newlines + */ +int +response(Modem *m, int timeout) +{ + int r; + ResultCode *rp; + + while(getmline(m, m->response, sizeof(m->response), timeout) == Eok){ + if(m->response[0] == 0) + continue; + verbose("<-m: %s", m->response); + for(rp = results; rp->terse; rp++){ + if(strncmp(rp->verbose, m->response, strlen(rp->verbose))) + continue; + r = rp->result; + if(rp->f && (r = (*rp->f)(m)) == Rcontinue) + break; + return r; + } + } + + m->response[0] = 0; + return Rnoise; +} + +void +xonoff(Modem *m, int i) +{ + char buf[8]; + + sprint(buf, "x%d", i); + i = strlen(buf); + write(m->cfd, buf, i); +} |