123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- #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);
- }
|