summaryrefslogtreecommitdiff
path: root/sys/src/cmd/fax/modem.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /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-xsys/src/cmd/fax/modem.c220
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);
+}