fax2send.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include "modem.h"
  5. int
  6. faxsend(Modem *m, int argc, char *argv[])
  7. {
  8. int c, count, r, flow;
  9. char buf[128];
  10. verbose("faxsend");
  11. if((r = initfaxmodem(m)) != Eok)
  12. return r;
  13. /* telco just does the dialing */
  14. r = response(m, 120);
  15. switch(r){
  16. case Rok:
  17. break;
  18. default:
  19. r = seterror(m, Enoanswer);
  20. return r;
  21. }
  22. xonoff(m, 1);
  23. verbose("sending");
  24. m->pageno = 1;
  25. while(argc--){
  26. if(m->pageno != 1)
  27. sleep(1000); /* let the paper catch up */
  28. m->valid &= ~(Vfhng|Vfet|Vfpts|Vftsi|Vfdcs);
  29. if((r = openfaxfile(m, *argv)) != Eok)
  30. return r;
  31. verbose("sending geometry");
  32. sprint(buf, "AT+FDT=%ld,%ld,%ld,%ld", m->df, m->vr, m->wd, m->ln);
  33. if(command(m, buf) != Eok)
  34. goto buggery;
  35. if(response(m, 20) != Rconnect){
  36. r = seterror(m, Eincompatible);
  37. goto buggery;
  38. }
  39. /*
  40. * Write the data, stuffing DLE's.
  41. * After each bufferfull check if the remote
  42. * sent us anything, e.g. CAN to abort.
  43. * This also flushes out the ^S/^Q characters
  44. * which the driver insists on sending us.
  45. * (Could fix the driver, of course...).
  46. */
  47. verbose("sending data");
  48. for(;;){
  49. flow = 0;
  50. count = 0;
  51. c = 0;
  52. while(count < sizeof(buf)-1){
  53. if((c = Bgetc(m->bp)) < 0)
  54. break;
  55. buf[count++] = c;
  56. if(c == '\020')
  57. buf[count++] = c;
  58. }
  59. verbose("sending %d bytes", count);
  60. if(count && write(m->fd, buf, count) < 0){
  61. verbose("write failed: %r");
  62. r = seterror(m, Esys);
  63. goto buggery;
  64. }
  65. /*
  66. * this does really rough flow control since the
  67. * avanstar is even worse
  68. */
  69. verbose("flow control");
  70. while((r = rawmchar(m, buf)) == Eok || flow){
  71. if(r != Eok){
  72. if(flow-- == 0)
  73. break;
  74. sleep(250);
  75. continue;
  76. }
  77. switch(buf[0]){
  78. case '\030':
  79. verbose("%c", buf[0]);
  80. if(write(m->fd, "\020\003", 2) < 0){
  81. r = seterror(m, Esys);
  82. goto buggery;
  83. }
  84. goto okexit;
  85. case '\021':
  86. flow = 0;
  87. break;
  88. case '\023':
  89. flow = 4;
  90. break;
  91. case '\n':
  92. break;
  93. default:
  94. verbose("%c", buf[0]);
  95. r = seterror(m, Eproto);
  96. goto buggery;
  97. }
  98. }
  99. if(c < 0)
  100. break;
  101. }
  102. /*
  103. * End of page, send DLE+ETX,
  104. * get OK in response.
  105. */
  106. verbose("sending end of page");
  107. if(write(m->fd, "\020\003", 2) < 0){
  108. r = seterror(m, Esys);
  109. goto buggery;
  110. }
  111. verbose("waiting for OK");
  112. if(response(m, 120) != Rok){
  113. r = seterror(m, Enoresponse);
  114. goto buggery;
  115. }
  116. /*
  117. * Did you hear me? - IT'S THE END OF THE PAGE.
  118. * Argument is 0 if more pages to follow.
  119. * Should get back an FPTS with an indication
  120. * as to whether the page was successfully
  121. * transmitted or not.
  122. */
  123. sprint(buf, "AT+FET=%d", argc == 0? 2: 0);
  124. if(command(m, buf) != Eok)
  125. goto buggery;
  126. switch(response(m, 20)){
  127. case Rok:
  128. break;
  129. case Rhangup:
  130. if(m->fhng == 0 && argc == 0)
  131. break;
  132. r = seterror(m, Eproto);
  133. goto buggery;
  134. default:
  135. r = seterror(m, Enoresponse);
  136. goto buggery;
  137. }
  138. if((m->valid & Vfpts) == 0 || m->fpts[0] != 1){
  139. r = seterror(m, Eproto);
  140. goto buggery;
  141. }
  142. Bterm(m->bp);
  143. m->pageno++;
  144. argv++;
  145. }
  146. okexit:
  147. xonoff(m, 0);
  148. return Eok;
  149. buggery:
  150. xonoff(m, 0);
  151. Bterm(m->bp);
  152. command(m, "AT+FK");
  153. response(m, 5);
  154. return r;
  155. }