1*219b2ee8SDavid du Colombier #include <u.h> 2*219b2ee8SDavid du Colombier #include <libc.h> 3*219b2ee8SDavid du Colombier #include <bio.h> 4*219b2ee8SDavid du Colombier 5*219b2ee8SDavid du Colombier #include "modem.h" 6*219b2ee8SDavid du Colombier 7*219b2ee8SDavid du Colombier typedef struct { 8*219b2ee8SDavid du Colombier char *terse; 9*219b2ee8SDavid du Colombier char *verbose; 10*219b2ee8SDavid du Colombier int result; 11*219b2ee8SDavid du Colombier int (*f)(Modem*); 12*219b2ee8SDavid du Colombier } ResultCode; 13*219b2ee8SDavid du Colombier 14*219b2ee8SDavid du Colombier static ResultCode results[] = { 15*219b2ee8SDavid du Colombier { "0", "OK", Rok, 0, }, 16*219b2ee8SDavid du Colombier { "1", "CONNECT", Rconnect, 0, }, 17*219b2ee8SDavid du Colombier { "2", "RING", Rring, 0, }, 18*219b2ee8SDavid du Colombier { "3", "NO CARRIER", Rfailure, 0, }, 19*219b2ee8SDavid du Colombier { "4", "ERROR", Rrerror, 0, }, 20*219b2ee8SDavid du Colombier { "5", "CONNECT 1200", Rconnect, 0, }, 21*219b2ee8SDavid du Colombier { "6", "NO DIALTONE", Rfailure, 0, }, 22*219b2ee8SDavid du Colombier { "7", "BUSY", Rfailure, 0, }, 23*219b2ee8SDavid du Colombier { "8", "NO ANSWER", Rfailure, 0, }, 24*219b2ee8SDavid du Colombier { "9", "CONNECT 2400", Rconnect, 0, }, /* MT1432BA */ 25*219b2ee8SDavid du Colombier { "10", "CONNECT 2400", Rconnect, 0, }, /* Hayes */ 26*219b2ee8SDavid du Colombier { "11", "CONNECT 4800", Rconnect, 0, }, 27*219b2ee8SDavid du Colombier { "12", "CONNECT 9600", Rconnect, 0, }, 28*219b2ee8SDavid du Colombier { "13", "CONNECT 14400",Rconnect, 0, }, 29*219b2ee8SDavid du Colombier { "23", "CONNECT 1275", Rconnect, 0, }, /* MT1432BA */ 30*219b2ee8SDavid du Colombier 31*219b2ee8SDavid du Colombier { "-1", "+FCON", Rcontinue, fcon, }, 32*219b2ee8SDavid du Colombier { "-1", "+FTSI", Rcontinue, ftsi, }, 33*219b2ee8SDavid du Colombier { "-1", "+FDCS", Rcontinue, fdcs, }, 34*219b2ee8SDavid du Colombier { "-1", "+FCFR", Rcontinue, fcfr, }, 35*219b2ee8SDavid du Colombier { "-1", "+FPTS", Rcontinue, fpts, }, 36*219b2ee8SDavid du Colombier { "-1", "+FET", Rcontinue, fet, }, 37*219b2ee8SDavid du Colombier { "-1", "+FHNG", Rcontinue, fhng, }, 38*219b2ee8SDavid du Colombier 39*219b2ee8SDavid du Colombier { 0 }, 40*219b2ee8SDavid du Colombier }; 41*219b2ee8SDavid du Colombier 42*219b2ee8SDavid du Colombier void 43*219b2ee8SDavid du Colombier initmodem(Modem *m, int fd, int cfd, char *type, char *id) 44*219b2ee8SDavid du Colombier { 45*219b2ee8SDavid du Colombier m->fd = fd; 46*219b2ee8SDavid du Colombier m->cfd = cfd; 47*219b2ee8SDavid du Colombier if(id == 0) 48*219b2ee8SDavid du Colombier id = "Plan 9"; 49*219b2ee8SDavid du Colombier m->id = id; 50*219b2ee8SDavid du Colombier m->t = type; 51*219b2ee8SDavid du Colombier } 52*219b2ee8SDavid du Colombier 53*219b2ee8SDavid du Colombier int 54*219b2ee8SDavid du Colombier rawmchar(Modem *m, char *p) 55*219b2ee8SDavid du Colombier { 56*219b2ee8SDavid du Colombier Dir d; 57*219b2ee8SDavid du Colombier 58*219b2ee8SDavid du Colombier if(m->icount == 0) 59*219b2ee8SDavid du Colombier m->iptr = m->ibuf; 60*219b2ee8SDavid du Colombier 61*219b2ee8SDavid du Colombier if(m->icount){ 62*219b2ee8SDavid du Colombier *p = *m->iptr++; 63*219b2ee8SDavid du Colombier m->icount--; 64*219b2ee8SDavid du Colombier return Eok; 65*219b2ee8SDavid du Colombier } 66*219b2ee8SDavid du Colombier 67*219b2ee8SDavid du Colombier m->iptr = m->ibuf; 68*219b2ee8SDavid du Colombier 69*219b2ee8SDavid du Colombier if(dirfstat(m->fd, &d) < 0){ 70*219b2ee8SDavid du Colombier verbose("rawmchar: dirfstat: %r"); 71*219b2ee8SDavid du Colombier return seterror(m, Esys); 72*219b2ee8SDavid du Colombier } 73*219b2ee8SDavid du Colombier if(d.length == 0) 74*219b2ee8SDavid du Colombier return Enoresponse; 75*219b2ee8SDavid du Colombier 76*219b2ee8SDavid du Colombier if(d.length > sizeof(m->ibuf)) 77*219b2ee8SDavid du Colombier d.length = sizeof(m->ibuf); 78*219b2ee8SDavid du Colombier if((m->icount = read(m->fd, m->ibuf, d.length)) <= 0){ 79*219b2ee8SDavid du Colombier verbose("rawmchar: read: %r"); 80*219b2ee8SDavid du Colombier m->icount = 0; 81*219b2ee8SDavid du Colombier return seterror(m, Esys); 82*219b2ee8SDavid du Colombier } 83*219b2ee8SDavid du Colombier *p = *m->iptr++; 84*219b2ee8SDavid du Colombier m->icount--; 85*219b2ee8SDavid du Colombier 86*219b2ee8SDavid du Colombier return Eok; 87*219b2ee8SDavid du Colombier } 88*219b2ee8SDavid du Colombier 89*219b2ee8SDavid du Colombier int 90*219b2ee8SDavid du Colombier getmchar(Modem *m, char *buf, long timeout) 91*219b2ee8SDavid du Colombier { 92*219b2ee8SDavid du Colombier int r; 93*219b2ee8SDavid du Colombier 94*219b2ee8SDavid du Colombier timeout += time(0); 95*219b2ee8SDavid du Colombier while(time(0) <= timeout){ 96*219b2ee8SDavid du Colombier switch(r = rawmchar(m, buf)){ 97*219b2ee8SDavid du Colombier 98*219b2ee8SDavid du Colombier case Eok: 99*219b2ee8SDavid du Colombier return Eok; 100*219b2ee8SDavid du Colombier 101*219b2ee8SDavid du Colombier case Enoresponse: 102*219b2ee8SDavid du Colombier sleep(100); 103*219b2ee8SDavid du Colombier continue; 104*219b2ee8SDavid du Colombier 105*219b2ee8SDavid du Colombier default: 106*219b2ee8SDavid du Colombier return r; 107*219b2ee8SDavid du Colombier } 108*219b2ee8SDavid du Colombier } 109*219b2ee8SDavid du Colombier 110*219b2ee8SDavid du Colombier return seterror(m, Enoresponse); 111*219b2ee8SDavid du Colombier } 112*219b2ee8SDavid du Colombier 113*219b2ee8SDavid du Colombier int 114*219b2ee8SDavid du Colombier putmchar(Modem *m, char *p) 115*219b2ee8SDavid du Colombier { 116*219b2ee8SDavid du Colombier if(write(m->fd, p, 1) < 0) 117*219b2ee8SDavid du Colombier return seterror(m, Esys); 118*219b2ee8SDavid du Colombier return Eok; 119*219b2ee8SDavid du Colombier } 120*219b2ee8SDavid du Colombier 121*219b2ee8SDavid du Colombier static int 122*219b2ee8SDavid du Colombier getmline(Modem *m, char *buf, int len, long timeout) 123*219b2ee8SDavid du Colombier { 124*219b2ee8SDavid du Colombier int r; 125*219b2ee8SDavid du Colombier char *e = buf+len-1; 126*219b2ee8SDavid du Colombier 127*219b2ee8SDavid du Colombier timeout += time(0); 128*219b2ee8SDavid du Colombier while(time(0) <= timeout){ 129*219b2ee8SDavid du Colombier switch(r = rawmchar(m, buf)){ 130*219b2ee8SDavid du Colombier 131*219b2ee8SDavid du Colombier case Eok: 132*219b2ee8SDavid du Colombier if(*buf == '\n') 133*219b2ee8SDavid du Colombier continue; 134*219b2ee8SDavid du Colombier if(*buf == '\r'){ 135*219b2ee8SDavid du Colombier *buf = 0; 136*219b2ee8SDavid du Colombier return Eok; 137*219b2ee8SDavid du Colombier } 138*219b2ee8SDavid du Colombier buf++; 139*219b2ee8SDavid du Colombier if(buf == e){ 140*219b2ee8SDavid du Colombier *buf = 0; 141*219b2ee8SDavid du Colombier return Eok; 142*219b2ee8SDavid du Colombier } 143*219b2ee8SDavid du Colombier continue; 144*219b2ee8SDavid du Colombier 145*219b2ee8SDavid du Colombier case Enoresponse: 146*219b2ee8SDavid du Colombier sleep(100); 147*219b2ee8SDavid du Colombier continue; 148*219b2ee8SDavid du Colombier 149*219b2ee8SDavid du Colombier default: 150*219b2ee8SDavid du Colombier return r; 151*219b2ee8SDavid du Colombier } 152*219b2ee8SDavid du Colombier } 153*219b2ee8SDavid du Colombier 154*219b2ee8SDavid du Colombier return seterror(m, Enoresponse); 155*219b2ee8SDavid du Colombier } 156*219b2ee8SDavid du Colombier 157*219b2ee8SDavid du Colombier int 158*219b2ee8SDavid du Colombier command(Modem *m, char *s) 159*219b2ee8SDavid du Colombier { 160*219b2ee8SDavid du Colombier verbose("m->: %s", s); 161*219b2ee8SDavid du Colombier if(fprint(m->fd, "%s\r", s) < 0) 162*219b2ee8SDavid du Colombier return seterror(m, Esys); 163*219b2ee8SDavid du Colombier return Eok; 164*219b2ee8SDavid du Colombier } 165*219b2ee8SDavid du Colombier 166*219b2ee8SDavid du Colombier /* 167*219b2ee8SDavid du Colombier * Read till we see a message or we time out. 168*219b2ee8SDavid du Colombier * BUG: line lengths not checked; 169*219b2ee8SDavid du Colombier * newlines 170*219b2ee8SDavid du Colombier */ 171*219b2ee8SDavid du Colombier int 172*219b2ee8SDavid du Colombier response(Modem *m, int timeout) 173*219b2ee8SDavid du Colombier { 174*219b2ee8SDavid du Colombier int r; 175*219b2ee8SDavid du Colombier ResultCode *rp; 176*219b2ee8SDavid du Colombier 177*219b2ee8SDavid du Colombier while(getmline(m, m->response, sizeof(m->response), timeout) == Eok){ 178*219b2ee8SDavid du Colombier if(m->response[0] == 0) 179*219b2ee8SDavid du Colombier continue; 180*219b2ee8SDavid du Colombier verbose("<-m: %s", m->response); 181*219b2ee8SDavid du Colombier for(rp = results; rp->terse; rp++){ 182*219b2ee8SDavid du Colombier if(strncmp(rp->verbose, m->response, strlen(rp->verbose))) 183*219b2ee8SDavid du Colombier continue; 184*219b2ee8SDavid du Colombier r = rp->result; 185*219b2ee8SDavid du Colombier if(rp->f && (r = (*rp->f)(m)) == Rcontinue) 186*219b2ee8SDavid du Colombier break; 187*219b2ee8SDavid du Colombier return r; 188*219b2ee8SDavid du Colombier } 189*219b2ee8SDavid du Colombier } 190*219b2ee8SDavid du Colombier 191*219b2ee8SDavid du Colombier m->response[0] = 0; 192*219b2ee8SDavid du Colombier return Rnoise; 193*219b2ee8SDavid du Colombier } 194*219b2ee8SDavid du Colombier 195*219b2ee8SDavid du Colombier void 196*219b2ee8SDavid du Colombier xonoff(Modem *m, int i) 197*219b2ee8SDavid du Colombier { 198*219b2ee8SDavid du Colombier char buf[8]; 199*219b2ee8SDavid du Colombier 200*219b2ee8SDavid du Colombier sprint(buf, "x%d", i); 201*219b2ee8SDavid du Colombier i = strlen(buf); 202*219b2ee8SDavid du Colombier write(m->cfd, buf, i); 203*219b2ee8SDavid du Colombier } 204