172 lines
3.2 KiB
C
172 lines
3.2 KiB
C
#include <u.h>
|
|
#include <libc.h>
|
|
#include <bio.h>
|
|
|
|
#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;
|
|
}
|