#include #include #include #include "modem.h" int faxsend(Modem *m, int argc, char *argv[]) { int c, count, r, flow; char buf[128]; verbose("faxsend"); if((r = initfaxmodem(m)) != Eok) return r; /* telco just does the dialing */ r = response(m, 120); switch(r){ case Rok: break; default: r = seterror(m, Enoanswer); return r; } xonoff(m, 1); verbose("sending"); m->pageno = 1; while(argc--){ if(m->pageno != 1) sleep(1000); /* let the paper catch up */ m->valid &= ~(Vfhng|Vfet|Vfpts|Vftsi|Vfdcs); if((r = openfaxfile(m, *argv)) != Eok) return r; verbose("sending geometry"); sprint(buf, "AT+FDT=%ld,%ld,%ld,%ld", m->df, m->vr, m->wd, m->ln); if(command(m, buf) != Eok) goto buggery; if(response(m, 20) != Rconnect){ r = seterror(m, Eincompatible); goto buggery; } /* * Write the data, stuffing DLE's. * After each bufferfull check if the remote * sent us anything, e.g. CAN to abort. * This also flushes out the ^S/^Q characters * which the driver insists on sending us. * (Could fix the driver, of course...). */ verbose("sending data"); for(;;){ flow = 0; count = 0; c = 0; while(count < sizeof(buf)-1){ if((c = Bgetc(m->bp)) < 0) break; buf[count++] = c; if(c == '\020') buf[count++] = c; } verbose("sending %d bytes", count); if(count && write(m->fd, buf, count) < 0){ verbose("write failed: %r"); r = seterror(m, Esys); goto buggery; } /* * this does really rough flow control since the * avanstar is even worse */ verbose("flow control"); while((r = rawmchar(m, buf)) == Eok || flow){ if(r != Eok){ if(flow-- == 0) break; sleep(250); continue; } switch(buf[0]){ case '\030': verbose("%c", buf[0]); if(write(m->fd, "\020\003", 2) < 0){ r = seterror(m, Esys); goto buggery; } goto okexit; case '\021': flow = 0; break; case '\023': flow = 4; break; case '\n': break; default: verbose("%c", buf[0]); r = seterror(m, Eproto); goto buggery; } } if(c < 0) break; } /* * End of page, send DLE+ETX, * get OK in response. */ verbose("sending end of page"); if(write(m->fd, "\020\003", 2) < 0){ r = seterror(m, Esys); goto buggery; } verbose("waiting for OK"); if(response(m, 120) != Rok){ r = seterror(m, Enoresponse); goto buggery; } /* * Did you hear me? - IT'S THE END OF THE PAGE. * Argument is 0 if more pages to follow. * Should get back an FPTS with an indication * as to whether the page was successfully * transmitted or not. */ sprint(buf, "AT+FET=%d", argc == 0? 2: 0); if(command(m, buf) != Eok) goto buggery; switch(response(m, 20)){ case Rok: break; case Rhangup: if(m->fhng == 0 && argc == 0) break; r = seterror(m, Eproto); goto buggery; default: r = seterror(m, Enoresponse); goto buggery; } if((m->valid & Vfpts) == 0 || m->fpts[0] != 1){ r = seterror(m, Eproto); goto buggery; } Bterm(m->bp); m->pageno++; argv++; } okexit: xonoff(m, 0); return Eok; buggery: xonoff(m, 0); Bterm(m->bp); command(m, "AT+FK"); response(m, 5); return r; }