1 /*	$Id$ */
2 /*
3  * Copyright (c) 1990-1996 Sam Leffler
4  * Copyright (c) 1991-1996 Silicon Graphics, Inc.
5  * HylaFAX is a trademark of Silicon Graphics
6  *
7  * Permission to use, copy, modify, distribute, and sell this software and
8  * its documentation for any purpose is hereby granted without fee, provided
9  * that (i) the above copyright notices and this permission notice appear in
10  * all copies of the software and related documentation, and (ii) the names of
11  * Sam Leffler and Silicon Graphics may not be used in any advertising or
12  * publicity relating to the software without the specific, prior written
13  * permission of Sam Leffler and Silicon Graphics.
14  *
15  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
17  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
18  *
19  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
20  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
21  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
22  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
23  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
24  * OF THIS SOFTWARE.
25  */
26 
27 /*
28  * EIA/TIA-578 (Class 1) Modem Driver.
29  */
30 #include "Sys.h"
31 #include "Class1.h"
32 #include "ModemConfig.h"
33 #include "HDLCFrame.h"
34 #include "t.30.h"
35 #include "tiffio.h"
36 
37 #include <stdlib.h>
38 #include <ctype.h>
39 
40 const char* Class1Modem::modulationNames[6] = {
41     "v.21, chan 2",
42     "v.27ter fallback mode",
43     "v.27ter",
44     "v.29",
45     "v.17",
46     "v.33",
47 };
48 /*
49  * Modem capabilities are queried at startup and a
50  * table based on this is created for each modem.
51  * This information is used to negotiate T.30 session
52  * parameters (e.g. signalling rate).
53  *
54  * NB: v.17 w/ long training is the same as v.33, at
55  *     least at 12000 and 14400.
56  */
57 const Class1Cap Class1Modem::basicCaps[15] = {
58     {  3,  0,	 	0,		     V21,   false }, // v.21
59     {  24, BR_2400,	DCSSIGRATE_2400V27,  V27FB, false }, // v.27 ter
60     {  48, BR_4800,	DCSSIGRATE_4800V27,  V27,   false }, // v.27 ter
61     {  72, BR_7200,	DCSSIGRATE_7200V29,  V29,   false }, // v.29
62     {  73, BR_7200,	DCSSIGRATE_7200V17,  V17,   false }, // v.17
63     {  74, BR_7200,	DCSSIGRATE_7200V17,  V17,   false }, // v.17 w/st
64     {  96, BR_9600,	DCSSIGRATE_9600V29,  V29,   false }, // v.29
65     {  97, BR_9600,	DCSSIGRATE_9600V17,  V17,   false }, // v.17
66     {  98, BR_9600,	DCSSIGRATE_9600V17,  V17,   false }, // v.17 w/st
67     { 121, BR_12000,	DCSSIGRATE_12000V33, V33,   false }, // v.33
68     { 121, BR_12000,	DCSSIGRATE_12000V17, V17,   false }, // v.17
69     { 122, BR_12000,	DCSSIGRATE_12000V17, V17,   false }, // v.17 w/st
70     { 145, BR_14400,	DCSSIGRATE_14400V33, V33,   false }, // v.33
71     { 145, BR_14400,	DCSSIGRATE_14400V17, V17,   false }, // v.17
72     { 146, BR_14400,	DCSSIGRATE_14400V17, V17,   false }, // v.17 w/st
73 };
74 #define	NCAPS	(sizeof (basicCaps) / sizeof (basicCaps[0]))
75 
76 const char* Class1Modem::tmCmdFmt = "AT+FTM=%u";
77 const char* Class1Modem::rmCmdFmt = "AT+FRM=%u";
78 
Class1Modem(FaxServer & s,const ModemConfig & c)79 Class1Modem::Class1Modem(FaxServer& s, const ModemConfig& c)
80     : FaxModem(s,c)
81     , thCmd("AT+FTH=3")
82     , rhCmd("AT+FRH=3")
83 {
84     messageReceived = false;
85     memcpy(xmitCaps, basicCaps, sizeof (basicCaps));
86     memcpy(recvCaps, basicCaps, sizeof (basicCaps));
87 
88     /*
89      * Because the sending routines deliver data to the transmit functions
90      * in segments, these must be globally available to spool outgoing data
91      * until a complete ECM block can be assembled.
92      *
93      * Besides the contents of ecmBlock, ecmStuffedBlock must be able to
94      * hold all sync flag bytes, stuffed bits, and RCP frames.
95      */
96     u_int fs = 256;
97     if (conf.class1ECMFrameSize == 64) fs = 64;
98     ecmFrame = (u_char*) malloc(fs + 4);
99     fxAssert(ecmFrame != NULL, "ECM procedure error (frame).");
100     ecmBlock = (u_char*) malloc((fs + 4) * 256);
101     fxAssert(ecmBlock != NULL, "ECM procedure error (block).");
102     ecmStuffedBlock = (u_char*) malloc(fs == 256 ? 83000 : 33000);
103     fxAssert(ecmStuffedBlock != NULL, "ECM procedure error (stuffed block).");
104     gotCTRL = false;
105     repeatPhaseB = false;
106     silenceHeard = false;
107     imagefd = 0;
108 }
109 
~Class1Modem()110 Class1Modem::~Class1Modem()
111 {
112     free(ecmFrame);
113     free(ecmBlock);
114     free(ecmStuffedBlock);
115 }
116 
117 bool
atCmd(const fxStr & cmd,ATResponse r,long ms)118 Class1Modem::atCmd(const fxStr& cmd, ATResponse r, long ms)
119 {
120     silenceHeard = false;
121     return (ClassModem::atCmd(cmd, r, ms));
122 }
123 
124 /*
125  * Check if the modem is a Class 1 modem and,
126  * if so, configure it for use.
127  */
128 bool
setupModem(bool isSend)129 Class1Modem::setupModem(bool isSend)
130 {
131     if (!selectBaudRate(conf.maxRate, conf.flowControl, conf.flowControl))
132 	return (false);
133     // Query service support information
134     fxStr s;
135     if (doQuery(conf.classQueryCmd, s, 5000) && FaxModem::parseRange(s, modemServices))
136 	traceBits(modemServices & SERVICE_ALL, serviceNames);
137     if ((modemServices & serviceType) == 0)
138 	return (false);
139     atCmd(classCmd);
140 
141     /*
142      * Query manufacturer, model, and firmware revision.
143      * We use the manufacturer especially as a key to
144      * working around firmware bugs (yech!).
145      */
146     if (setupManufacturer(modemMfr)) {
147 	modemCapability("Mfr " | modemMfr);
148 	modemMfr.raisecase();
149     }
150     (void) setupModel(modemModel);
151     (void) setupRevision(modemRevision);
152     if (modemModel != "")
153 	modemCapability("Model " | modemModel);
154     if (modemRevision != "")
155 	modemCapability("Revision " | modemRevision);
156 
157     /*
158      * Get modem capabilities and calculate best signalling
159      * rate, data formatting capabilities, etc. for use in
160      * T.30 negotiations.
161      */
162     if (!class1Query(conf.class1TMQueryCmd, xmitCaps)) {
163 	serverTrace("Error parsing \"+FTM\" query response: \"%s\"", rbuf);
164 	return (false);
165     }
166     modemParams.br = 0;
167     u_int i;
168     for (i = 1; i < NCAPS; i++)
169 	if (xmitCaps[i].ok)
170 	    modemParams.br |= BIT(xmitCaps[i].br);
171     nonV34br = modemParams.br;
172     if (conf.class1EnableV34Cmd != "" && conf.class1ECMSupport) {
173 	// This is cosmetic, mostly, to state the modem supports V.34.
174 	// We could query the modem but that would require another
175 	// config option, so we just trust the enable command.
176 	primaryV34Rate = 0;
177 	u_short pos = conf.class1EnableV34Cmd.findR(conf.class1EnableV34Cmd.length(), "+F34=", 5) + 4;
178 	if (pos == 4) // Unknown class1EnableV34Cmd
179 	    modemCapability("Unable to determinate V.34 speed from class1EnableV34Cmd, V.34 faxing will be disabled!");
180 	else
181 	    primaryV34Rate = atoi(conf.class1EnableV34Cmd.extract(pos, conf.class1EnableV34Cmd.next(pos, ',') - pos));
182 	modemParams.br |= BIT(primaryV34Rate) - 1;
183     }
184     modemParams.wd = conf.class1PageWidthSupport;
185     modemParams.ln = conf.class1PageLengthSupport;
186     modemParams.df = BIT(DF_1DMH) | (conf.class1MRSupport ? BIT(DF_2DMR) : 0);
187     modemParams.bf = BF_DISABLE;
188     modemParams.st = ST_ALL;
189     modemParams.jp = 0;
190     pokeConfig(isSend);
191     traceModemParams();
192     /*
193      * Receive capabilities are maintained separately from
194      * transmit capabilities because we need to know more
195      * than the signalling rate to formulate the DIS.
196      */
197     if (!class1Query(conf.class1RMQueryCmd, recvCaps)) {
198 	serverTrace("Error parsing \"+FRM\" query response: \"%s\"", rbuf);
199 	return (false);
200     }
201     u_int mods = 0;
202     for (i = 1; i < NCAPS; i++)
203 	if (recvCaps[i].ok)
204 	    mods |= BIT(recvCaps[i].mod);
205     switch (mods) {
206     case BIT(V27FB):
207 	discap = DISSIGRATE_V27FB;
208 	break;
209     case BIT(V27FB)|BIT(V27):
210 	discap = DISSIGRATE_V27;
211 	break;
212     case BIT(V29):
213 	discap = DISSIGRATE_V29;
214 	break;
215     case BIT(V27FB)|BIT(V27)|BIT(V29):
216 	discap = DISSIGRATE_V2729;
217 	break;
218     case BIT(V27FB)|BIT(V27)|BIT(V29)|BIT(V33):
219 	discap = DISSIGRATE_V33;
220 	break;
221     case BIT(V27FB)|BIT(V27)|BIT(V29)|BIT(V17):
222     case BIT(V27FB)|BIT(V27)|BIT(V29)|BIT(V33)|BIT(V17):
223 	discap = DISSIGRATE_V17;
224 	break;
225     }
226     /*
227      * T.30 specifies that HDLC frame data are in MSB bit
228      * order except for CIG/TSI data which have LSB bit order.
229      * We compose and interpret frame data in MSB bit order
230      * and pass the frames through frameRev immediately before
231      * transmitting and upon receiving to handle modem characteristics.
232      *
233      * Class1Modem::encodeTSI and Class1Modem::decodeTSI (below)
234      * assume this work and process CIG/TSI data accordingly.
235      */
236     frameRev = TIFFGetBitRevTable(conf.frameFillOrder == FILLORDER_LSB2MSB);
237 
238     setupClass1Parameters();
239     return (true);
240 }
241 
242 /*
243  * These are potentially dynamic modem settings that can be altered on-the-fly.
244  */
245 void
pokeConfig(bool isSend)246 Class1Modem::pokeConfig(bool isSend)
247 {
248     modemParams.vr = conf.class1Resolutions;	// bitmapped by configuration
249     if (conf.class1ECMSupport) {
250 	modemParams.ec = BIT(EC_DISABLE) | BIT(EC_ENABLE64) | BIT(EC_ENABLE256);
251 	modemParams.df |= (conf.class1MMRSupport ? BIT(DF_2DMMR) : 0);
252 	switch (conf.class1JBIGSupport) {
253 	    case FaxModem::JBIG_FULL:
254 		jbigSupported = true;
255 		break;
256 	    case FaxModem::JBIG_SEND:
257 		jbigSupported = isSend;
258 		break;
259 	    case FaxModem::JBIG_RECV:
260 		jbigSupported = !isSend;
261 		break;
262 	    default:
263 		jbigSupported = false;
264 		break;
265 	}
266 	if (jbigSupported) modemParams.df |= BIT(DF_JBIG);
267 	if (conf.class1GreyJPEGSupport || conf.class1ColorJPEGSupport)
268 	    modemParams.jp |= BIT(JP_GREY);
269 	if (conf.class1ColorJPEGSupport)
270 	    modemParams.jp |= BIT(JP_COLOR);
271     } else
272 	modemParams.ec = BIT(EC_DISABLE);
273 }
274 
275 /*
276  * Send the modem the Class 1 configuration commands.
277  */
278 bool
setupClass1Parameters()279 Class1Modem::setupClass1Parameters()
280 {
281     if (modemServices & serviceType) {
282 	setupFlowControl(flowControl);
283 	atCmd(conf.setupAACmd);
284     }
285     return (true);
286 }
287 
288 void
hangup()289 Class1Modem::hangup()
290 {
291     if (useV34) {
292 	// terminate V.34 channel
293 	u_char buf[2];
294 	buf[0] = DLE; buf[1] = EOT;		// <DLE><EOT>
295 	putModemData(buf, 2);
296 	// T.31-A1 samples indicate an OK response, but anything is acceptable
297 	(void) atResponse(rbuf, 60000);
298     }
299     atCmd(conf.onHookCmd, AT_OK, 5000);
300 }
301 
302 /*
303  * Setup receive-specific parameters.
304  */
305 bool
setupReceive()306 Class1Modem::setupReceive()
307 {
308     return (true);			// nothing to do
309 }
310 
311 /*
312  * Send the modem any commands needed to force use of
313  * the specified flow control scheme.
314  */
315 bool
setupFlowControl(FlowControl fc)316 Class1Modem::setupFlowControl(FlowControl fc)
317 {
318     switch (fc) {
319     case FLOW_NONE:	return atCmd(conf.class1NFLOCmd);
320     case FLOW_XONXOFF:	return atCmd(conf.class1SFLOCmd);
321     case FLOW_RTSCTS:	return atCmd(conf.class1HFLOCmd);
322     }
323     return (true);
324 }
325 
326 /*
327  * Place the modem into the appropriate state
328  * for sending facsimile.
329  */
330 bool
faxService(bool enableV34,bool enableV17)331 Class1Modem::faxService(bool enableV34, bool enableV17)
332 {
333     if (!atCmd(classCmd)) return (false);
334     if (conf.class1EnableV34Cmd != "" && enableV34)
335 	atCmd(conf.class1EnableV34Cmd);
336     useV34 = false;	// only when V.8 handshaking is used
337     gotEOT = false;
338     return (setupFlowControl(flowControl));
339 }
340 
341 /*
342  * The modem is initialized. Now set it to ready for answer.
343  */
344 bool
ready(long ms)345 Class1Modem::ready(long ms)
346 {
347     gotEOT = false;
348     useV34 = false;     // only when V.8 handshaking is used
349     if (conf.class1EnableV34Cmd != "" && conf.class1ECMSupport)
350         if (!atCmd(conf.class1EnableV34Cmd))
351 	    return (false);
352     if (conf.class1AdaptRecvCmd != "")
353 	if (!atCmd(conf.class1AdaptRecvCmd))
354 	    return (false);
355     return (FaxModem::ready(ms));
356 }
357 
358 
359 /*
360  * Set the local subscriber identification.
361  */
362 void
setLID(const fxStr & number)363 Class1Modem::setLID(const fxStr& number)
364 {
365     encodeTSI(lid, number);
366 }
367 
368 bool
supportsPolling() const369 Class1Modem::supportsPolling() const
370 {
371     return (true);
372 }
373 
374 /*
375  * Construct a binary TSI/CIG string for transmission.  Note
376  * that we do not enforce the specification that restricts
377  * the alphabet to that of Table 3/T.30 (numeric digits,
378  * hyphen, period, and space), but instead permit any
379  * printable ASCII string of at most 20 characters to be
380  * used.  Note also that the bit reversal is done with the
381  * understanding that the encoded string is processed again
382  * using frameRev (see above) when forming the transmitted
383  * HDLC frame.
384  */
385 void
encodeTSI(fxStr & binary,const fxStr & ascii)386 Class1Modem::encodeTSI(fxStr& binary, const fxStr& ascii)
387 {
388     u_int i, j;
389     u_char buf[20];
390     u_int n = fxmin(ascii.length(),(u_int) 20);
391     for (i = 0, j = 0; i < n; i++) {
392 	char c = ascii[i];
393 	if (isprint(c) || c == ' ')
394 	    buf[j++] = frameRev[c];
395     }
396     /*
397      * Now ``reverse copy'' the string.
398      */
399     binary.resize(20);
400     for (i = 0; j > 0; i++, j--)
401 	binary[i] = buf[j-1];
402     for (; i < 20; i++)
403 	binary[i] = frameRev[' '];	// blank pad remainder
404 }
405 
406 /*
407  * Encode an NSF string for transmission.
408  */
409 void
encodeNSF(fxStr & binary,const fxStr & ascii)410 Class1Modem::encodeNSF(fxStr& binary, const fxStr& ascii)
411 {
412     u_int i, j;
413     u_int n = ascii.length();
414     binary.resize(n);
415     for (i = 0, j = 0; i < n; i++) {
416 	char c = ascii[i];
417 	if (isprint(c) || c == ' ')
418 	    binary[j++] = frameRev[c];
419     }
420 }
421 
422 /*
423  * Do the inverse of encodeTSI; i.e. convert a binary
424  * string of encoded digits into the equivalent ascii.
425  * Note that as above (and per the spec) bytes are
426  * presumed to be transmitted in LSB2MSB bit order and
427  * then reversed on receipt according to the host bit
428  * order.
429  */
430 const fxStr&
decodeTSI(fxStr & ascii,const HDLCFrame & binary)431 Class1Modem::decodeTSI(fxStr& ascii, const HDLCFrame& binary)
432 {
433     int n = binary.getFrameDataLength();
434     if (n > 20)			// spec says no more than 20 digits
435 	n = 20;
436     else n--;			// trim FCF
437     ascii.resize(n);
438     u_int d = 0;
439     bool seenDigit = false;
440     for (const u_char* cp = binary.getFrameData() + n-1; n > 0; cp--, n--) {
441 	/*
442 	 * Accept any printable ascii.
443 	 */
444 	u_char c = frameRev[*cp];
445         if (isprint(c) || c == ' ') {
446 	    if (c != ' ')
447 		seenDigit = true;
448 	    if (seenDigit)
449 		ascii[d++] = c;
450 	}
451     }
452     ascii.resize(d);
453     return ascii;
454 }
455 
456 /*
457  * Construct a binary PWD/SUB/SEP string for transmission.
458  */
459 void
encodePWD(fxStr & binary,const fxStr & ascii)460 Class1Modem::encodePWD(fxStr& binary, const fxStr& ascii)
461 {
462     encodeTSI(binary, ascii);
463 }
464 
465 /*
466  * Do the inverse of encodePWD; i.e. convert a binary
467  * string of encoded digits into the equivalent ascii.
468  */
469 const fxStr&
decodePWD(fxStr & ascii,const HDLCFrame & binary)470 Class1Modem::decodePWD(fxStr& ascii, const HDLCFrame& binary)
471 {
472     return decodeTSI(ascii, binary);
473 }
474 
475 bool
switchingPause(Status & eresult,u_int times)476 Class1Modem::switchingPause(Status& eresult, u_int times)
477 {
478     /*
479      * If class1SwitchingCmd is of the AT+FRS=n form we honor
480      * the caller's indicattion for a multiplication of the
481      * configured silence detection.  This is primarily used
482      * to avoid sending CRP as a receiver during a sender's TCF,
483      * but it could also be used in places where we find a
484      * longer wait often necessary.
485      */
486     fxStr scmd = fxStr(conf.class1SwitchingCmd);
487     if (times != 1) {
488 	fxStr ncmd = fxStr(scmd);
489 	ncmd.raiseatcmd();
490 	if (ncmd.length() > 7 && ncmd.head(7) == "AT+FRS=") {
491 	    int dur = atoi(ncmd.tail(ncmd.length()-7)) * times;
492 	    scmd = scmd.head(7) | fxStr(dur, "%d");
493 	}
494     }
495     if (!silenceHeard && !atCmd(scmd, AT_OK)) {
496 	eresult = Status(100, "Failure to receive silence (synchronization failure).");
497 	protoTrace(eresult.string());
498 	if (wasTimeout()) abortReceive();
499 	return (false);
500     }
501     /*
502      * We necessarily use class1SwitchingCmd rather frequently...
503      * sometimes this is programmed to be immediately before our signalling,
504      * and sometimes this is programmed to be immediately after the remote
505      * signalling.  That doesn't therefore give us very good control on
506      * ensuring that class1SwitchingCmd is not issued in duplicate in some
507      * kinds of program flow.
508      *
509      * Ideally we'd be able to standardize on issuing class1SwitchingCmd
510      * only in one case or another (but not both), but that's not particularly
511      * an easy ideal to realize given the number of exceptions to that rule
512      * that would neccesarily be required.
513      *
514      * So for now we just set this flag here, and we unset it in atCmd, and
515      * if the flag is set when we come back here, then we can avoid duplication.
516      */
517     silenceHeard = true;
518     return (true);
519 }
520 
521 /*
522  * Pass data to modem, filtering DLE's and
523  * optionally including the end-of-data
524  * marker <DLE><ETX>.
525  *
526  * If the data transfer is aborted by the user
527  * then we must take care to send <DLE><ETX>
528  * in order to exit gracefully.
529  */
530 bool
sendClass1Data(const u_char * data,u_int cc,const u_char * bitrev,bool eod,long ms)531 Class1Modem::sendClass1Data(const u_char* data, u_int cc,
532     const u_char* bitrev, bool eod, long ms)
533 {
534     bool ok = putModemDLEData(data, cc, bitrev, ms, conf.doPhaseCDebug);
535     if (eod || abortRequested()) {
536 	u_char buf[2];
537 	buf[0] = DLE;
538 	buf[1] = ETX;
539 	ok = putModemData(buf, 2);
540 	return (ok && !abortRequested());
541     } else
542 	return (ok);
543 }
544 
545 /*
546  * Receive timed out, abort the operation
547  * and resynchronize before returning.
548  */
549 void
abortReceive()550 Class1Modem::abortReceive()
551 {
552     if (useV34) return;			// nothing to do in V.34
553     bool b = wasTimeout();
554     char c = CAN;			// anything other than DC1/DC3
555     putModem(&c, 1, 1);
556     /*
557      * If the modem handles abort properly, then just
558      * wait for an OK result.  Otherwise, wait a short
559      * period of time, flush any input, and then send
560      * "AT" and wait for the return "OK".
561      */
562     if (conf.class1RecvAbortOK == 0) {	// modem doesn't send OK response
563 	pause(200);
564 	flushModemInput();
565 	(void) atCmd("AT", AT_OK, 100);
566     } else
567 	while (!waitFor(AT_OK, conf.class1RecvAbortOK) && lastResponse == AT_OTHER && !wasTimeout());
568     setTimeout(b);			// XXX putModem clobbers timeout state
569 }
570 
571 /*
572  * Request a primary rate renegotiation.
573  */
574 bool
renegotiatePrimary(bool constrain)575 Class1Modem::renegotiatePrimary(bool constrain)
576 {
577     u_char buf[4];
578     u_short size = 0;
579     buf[size++] = DLE;
580     if (constrain) {
581 	// don't neotiate a faster rate
582 	if (primaryV34Rate == 1) buf[size++] = 0x70;	// 2400 bit/s
583 	else if (primaryV34Rate == 2 || primaryV34Rate == 3) {
584 	    /*
585 	     * V.34 bitspeed 2400 is only possible with symbolrate 2400, and
586 	     * as we have no way of determining the symbolrate, we cannot
587 	     * wisely instruct the modem to use 2400 bps unless the modem
588 	     * negotiates it independently.
589 	     */
590 	    buf[size++] = 0x71;				// 4800 bit/s
591 	} else buf[size++] = primaryV34Rate + 0x6D;	// drop 4800 bit/s
592 	buf[size++] = DLE;
593     }
594     buf[size++] = 0x6C;					// <DLE><pph>
595     if (!putModemData(buf, size)) return (false);
596     if (constrain)
597 	protoTrace("Request primary rate renegotiation (limit %u bit/s).",
598 	    primaryV34Rate == 1 ? 2400 : primaryV34Rate > 3 ? (primaryV34Rate-2)*2400 : 4800);
599     else
600 	protoTrace("Request primary rate renegotiation.");
601     return (true);
602 }
603 
604 /*
605  * Wait for a <DLE><ctrl> response per T.31-A1 B.8.4.
606  */
607 bool
waitForDCEChannel(bool awaitctrl)608 Class1Modem::waitForDCEChannel(bool awaitctrl)
609 {
610     time_t start = Sys::now();
611     int c;
612     fxStr garbage;
613     bool gotresponse = false;
614     gotRTNC = false;
615     ctrlFrameRcvd = fxStr::null;
616     do {
617 	c = getModemChar(60000);
618 	if (c == DLE) {
619 	    /*
620 	     * With V.34-faxing we expect <DLE><command>
621 	     * Refer to T.31-A1 Table B.1.  Except for EOT
622 	     * these are merely indicators and do not require
623 	     * action.
624 	     */
625 	    c = getModemChar(60000);
626 	    switch (c) {
627 		case EOT:
628 		    protoTrace("EOT received (end of transmission)");
629 		    gotEOT = true;
630 		    recvdDCN = true;
631 		    return (false);
632 		case 0x69:
633 		    protoTrace("Control channel retrain");
634 		    // wait for the control channel to reappear
635 		    // should we reset the timeout setting?
636 		    gotresponse = waitForDCEChannel(true);
637 		    gotRTNC = true;
638 		    return ((awaitctrl ? gotresponse : false));
639 		case 0x6B:
640 		    protoTrace("Primary channel selected");
641 		    gotCTRL = false;
642 		    continue;
643 		case 0x6D:
644 		    protoTrace("Control channel selected");
645 		    gotCTRL = true;
646 		    continue;
647 		case 0x6E:			// 1200 bit/s
648 		case 0x6F:			// 2400 bit/s
649 		    // control rate indication
650 		    if (controlV34Rate != (c - 0x6D)) {
651 			controlV34Rate = (c - 0x6D);
652 			protoTrace("Control channel rate now %u bit/s", controlV34Rate*1200);
653 		    }
654 		    if (awaitctrl) gotresponse = true;
655 		    continue;
656 		case 0x70:			//  2400 bit/s
657 		case 0x71:			//  4800 bit/s
658 		case 0x72:			//  7200 bit/s
659 		case 0x73:			//  9600 bit/s
660 		case 0x74:			// 12000 bit/s
661 		case 0x75:			// 14400 bit/s
662 		case 0x76:			// 16800 bit/s
663 		case 0x77:			// 19200 bit/s
664 		case 0x78:			// 21600 bit/s
665 		case 0x79:			// 24000 bit/s
666 		case 0x7A:			// 26400 bit/s
667 		case 0x7B:			// 28800 bit/s
668 		case 0x7C:			// 31200 bit/s
669 		case 0x7D:			// 33600 bit/s
670 		    // primary rate indication
671 		    if (primaryV34Rate != (c - 0x6F)) {
672 			primaryV34Rate = (c - 0x6F);
673 			protoTrace("Primary channel rate now %u bit/s", primaryV34Rate*2400);
674 		    }
675 		    if (!awaitctrl) gotresponse = true;
676 		    continue;
677 		default:
678 		    // unexpected <DLE><command>, deem as garbage
679 		    garbage.append(DLE);
680 		    garbage.append(c);
681 		    break;
682 	    }
683 	} else garbage.append(c);
684 	if (gotCTRL && garbage.length() > 2 && (garbage[0] & 0xFF) == 0xFF &&
685 	    (garbage[garbage.length()-2] & 0xFF) == 0x10 &&
686 	    (garbage[garbage.length()-1] & 0xFF) == 0x03) {
687 	    // We got a control frame and won't get the channel change...
688 	    for (u_int i = 0; i < garbage.length()-2; i++) {
689 		if ((garbage[i] & 0xFF) == DLE && ++i < garbage.length()) {
690 		    /*
691 		     * We've got a frame and must apply T.31-A1 Table B.1.
692 		     */
693 		    if ((garbage[i] & 0xFF) == 0x07) {	// end of HDLC frame w/FCS error
694 			// what to do? send CRP? discard frame?
695 			continue;
696 		    }
697 		    switch (garbage[i] & 0xFF) {
698 			case DLE:	// <DLE><DLE> => <DLE>
699 			    ctrlFrameRcvd.append(DLE);
700 			    break;
701 			case SUB:	// <DLE><SUB> => <DLE><DLE>
702 			    ctrlFrameRcvd.append(DLE);
703 			    ctrlFrameRcvd.append(DLE);
704 			    break;
705 			case 0x51:	// <DLE><0x51> => <DC1>
706 			    ctrlFrameRcvd.append(DC1);
707 			    break;
708 			case 0x53:	// <DLE><0x53> => <DC3>
709 			    ctrlFrameRcvd.append(0x13);
710 			    break;
711 		    }
712 		} else
713 		    ctrlFrameRcvd.append(garbage[i] & 0xFF);
714 	    }
715 	    return (false);
716 	}
717 	fxStr rcpsignal;
718 	rcpsignal.append(0xFF);	rcpsignal.append(0x03);	rcpsignal.append(0x86);	rcpsignal.append(0x69);
719 	rcpsignal.append(0xCB);	rcpsignal.append(0x10);	rcpsignal.append(0x03);
720 	if (!gotCTRL && garbage == rcpsignal) {
721 	    // We anticipate getting "extra" RCP frames since we
722 	    // only look for one but usually we will see three.
723 	    garbage.cut(0, 7);
724 	}
725     } while (!gotresponse && Sys::now()-start < 60);
726     if (getHDLCTracing() && garbage.length()) {
727 	fxStr buf;
728 	u_int j = 0;
729 	for (u_int i = 0; i < garbage.length(); i++) {
730 	    if (j > 0)
731 		buf.append(' ');
732 	    buf.append(fxStr(garbage[i] & 0xFF, "%2.2X"));
733 	    j++;
734 	    if (j > 19) {
735 		protoTrace("--> [%u:%.*s]",
736 		    j, buf.length(), (const char*) buf);
737 		buf = "";
738 		j = 0;
739 	    }
740 	}
741 	if (j)
742 	    protoTrace("--> [%u:%.*s]",
743 		j, buf.length(), (const char*) buf);
744     }
745     return (gotresponse);
746 }
747 
748 /*
749  * Receive an HDLC frame. The frame itself must
750  * be received within 3 seconds (per the spec).
751  * If a carrier is received, but the complete frame
752  * is not received before the timeout, the receive
753  * is aborted.
754  */
755 bool
recvRawFrame(HDLCFrame & frame)756 Class1Modem::recvRawFrame(HDLCFrame& frame)
757 {
758     /*
759      * The spec says that a frame that takes between
760      * 2.55 and 3.45 seconds to be received may be
761      * discarded; we also add some time for DCE
762      * to detect and strip flags.
763      * We need to be generous here ... given that
764      * some frames can be long and some devices
765      * can add lots of flags to the signalling.
766      * The previous value of 5 seconds appears
767      * to have been too conservative; if the modem
768      * has said CONNECT, then it should be
769      * responsible enough to carry-through with
770      * things.  A timeout here is only needed to
771      * reign in modems that don't carry through.
772      */
773     startTimeout(10000);
774     /*
775      * Strip HDLC frame flags. This is not needed,
776      * (according to the standard DCE does the job),
777      * be we leave this legacy code unchanged
778      * for sure - D.B.
779      */
780     int c;
781     fxStr garbage;
782 
783     for (;;) {
784 	c = getModemChar(0);
785 	if (c == 0xff || c == EOF)
786 	    break;
787 	if (useV34 && c == DLE) {
788 	    c = getModemChar(0);
789 	    switch (c) {
790 		case EOT:
791 		    protoTrace("EOT received (end of transmission)");
792 		    gotEOT = true;
793 		    recvdDCN = true;
794 		    return (false);
795 		case 0x69:
796 		    protoTrace("Control channel retrain");
797 		    // wait for the control channel to reappear
798 		    // should we reset the timeout setting?
799 		    waitForDCEChannel(true);
800 		    gotRTNC = true;
801 		    return (false);
802 		default:
803 		    // unexpected <DLE><command>, deem as garbage
804 		    garbage.append(DLE);
805 		    break;
806 	    }
807 	}
808 	garbage.append(c);
809 	if ( garbage.length() >= 2 && garbage.tail(2) == "\r\n") {
810 	    /*
811 	     * CR+LF received before address field.
812 	     * We expect result code (though it's possible
813 	     * that CR+LF is a part of garbage frame)
814 	     */
815 	    garbage = garbage.head(garbage.length() - 2);
816 	    break;
817 	}
818     }
819 
820     if (getHDLCTracing() && garbage.length()) {
821 	fxStr buf;
822 	u_int j = 0;
823 	for (u_int i = 0; i < garbage.length(); i++) {
824 	    if (j > 0)
825 		buf.append(' ');
826 	    buf.append(fxStr(garbage[i] & 0xFF, "%2.2X"));
827 	    j++;
828 	    if (j > 19) {
829 		protoTrace("--> [%u:%.*s]",
830 		    j, buf.length(), (const char*) buf);
831 		buf = "";
832 		j = 0;
833 	    }
834 	}
835 	if (j)
836 	    protoTrace("--> [%u:%.*s]",
837 		j, buf.length(), (const char*) buf);
838     }
839 
840     if (c == 0xff) {			// address field received
841 	do {
842 	    if (c == DLE) {
843 		c = getModemChar(0);
844 		if (c == ETX || c == EOF)
845 		    break;
846 		if (useV34) {
847 		    /*
848 		     * T.31-A1 Table B.1
849 		     * These indicate transparancy, shielding, or delimiting.
850 		     */
851 		    if (c == 0x07) {	// end of HDLC frame w/FCS error
852 			break;
853 		    }
854 		    switch (c) {
855 			case EOT:
856 			    protoTrace("EOT received (end of transmission)");
857 			    gotEOT = true;
858 			    recvdDCN = true;
859 			    return (false);
860 			case DLE:	// <DLE><DLE> => <DLE>
861 			    break;
862 			case SUB:	// <DLE><SUB> => <DLE><DLE>
863 			    frame.put(frameRev[DLE]);
864 			    break;
865 			case 0x51:	// <DLE><0x51> => <DC1>
866 			    c = DC1;
867 			    break;
868 			case 0x53:	// <DLE><0x53> => <DC3>
869 			    c = 0x13;
870 			    break;
871 		    }
872 		} else {
873 		    /*
874 		     * Some modems may not double-up the in-data DLEs like they should.
875 		     */
876 		    if (conf.class1ModemHasDLEBug) frame.put(frameRev[DLE]);
877 		    else if (c != DLE) {
878 			protoTrace("Odd.  Modem reported meaningless <DLE><0x%X>.  Possible DLE bug indication.", c);
879 		    }
880 		}
881 	    }
882 	    frame.put(frameRev[c]);
883 	} while ((c = getModemChar(0)) != EOF);
884     }
885     stopTimeout("receiving HDLC frame data");
886     if (frame.getLength() > 0)
887 	traceHDLCFrame("-->", frame);
888     if (wasTimeout()) {
889 	abortReceive();
890 	return (false);
891     }
892     /*
893      * Now collect the "OK", "ERROR", or "FCERROR"
894      * response telling whether or not the FCS was
895      * legitimate.
896      */
897     if (!useV34 && !waitFor(AT_OK)) {
898 	if (lastResponse == AT_ERROR)
899 	    protoTrace("FCS error");
900 	return (false);
901     }
902     if (useV34 && c == 0x07) {
903 	protoTrace("FCS error");
904 	return (false);
905     }
906     if (frame.getFrameDataLength() < 1) {
907 	protoTrace("HDLC frame too short (%u bytes)", frame.getLength());
908 	return (false);
909     }
910     if ((frame[1]&0xf7) != 0xc0) {
911 	protoTrace("HDLC frame with bad control field %#x", frame[1]);
912 	return (false);
913     }
914     if (conf.class1ValidateV21Frames && !frame.checkCRC()) {
915 	protoTrace("FCS error (calculated)");
916 	return (false);
917     }
918     frameRcvd = "";
919     for (u_int i = 0; i < frame.getLength(); i++) frameRcvd.append(frame[i]);
920     frame.setOK(true);
921     return (true);
922 }
923 
924 bool
syncECMFrame()925 Class1Modem::syncECMFrame()
926 {
927     /*
928      * We explicitly look for the first sync flag so as to
929      * not get confused by any initial garbage or training.
930      */
931     int bit = 0;
932     u_short ones = 0;
933 
934     // look for the first sync flag
935 
936     time_t start = Sys::now();
937     startTimeout(60000);	// despite indications by T.4 A.3.1
938     do {
939 	if ((unsigned) Sys::now()-start >= 60) {
940 	    protoTrace("Timeout awaiting synchronization sequence");
941 	    setTimeout(true);
942 	    return (false);
943 	}
944 	bit = getModemBit(0);
945     } while (bit != 0 && !didBlockEnd());
946     do {
947 	if ((unsigned) Sys::now()-start >= 60) {
948 	    protoTrace("Timeout awaiting synchronization sequence");
949 	    setTimeout(true);
950 	    return (false);
951 	}
952 	if (bit == 0 || ones > 0xFF) ones = 0;
953 	bit = getModemBit(0);
954 	if (bit == 1) ones++;
955     } while (!(ones == 6 && bit == 0 && bit != EOF) && !didBlockEnd());
956     stopTimeout("awaiting synchronization sequence");
957     if (wasTimeout()) {
958 	return (false);
959     }
960     return (true);
961 }
962 
963 /*
964  * Receive an HDLC frame with ECM.  We must always be cautious
965  * of "stuffed" zero-bits after five sequential one-bits between
966  * flag sequences.  We assume this is called only after a
967  * successfuly received complete flag sequence.
968  *
969  * Things are significantly more simple with V.34-fax ECM since
970  * there is no synchronization or RCP frames.  In this case we
971  * simply have to handle byte transparancy and shielding, looking
972  * for byte-aligned frame delimiters.
973  */
974 bool
recvECMFrame(HDLCFrame & frame)975 Class1Modem::recvECMFrame(HDLCFrame& frame)
976 {
977     if (useV34) {
978 	int c;
979 	for (;;) {
980 	    c = getModemChar(60000);
981 	    if (wasTimeout()) {
982 		return (false);
983 	    }
984 	    if (c == DLE) {
985 		c = getModemChar(60000);
986 		if (wasTimeout()) {
987 		    return (false);
988 		}
989 		switch (c) {
990 		    case DLE:
991 			break;
992 		    case SUB:
993 			frame.put(frameRev[DLE]);
994 			break;
995 		    case 0x51:
996 			c = 0x11;
997 			break;
998 		    case 0x53:
999 			c = 0x13;
1000 			break;
1001 		    case ETX:
1002 			if (frame.getLength() > 0)
1003 			    traceHDLCFrame("-->", frame, true);
1004 			if (frame.getLength() < 5) {		// RCP frame size
1005 			    protoTrace("HDLC frame too short (%u bytes)", frame.getLength());
1006 			    return (false);
1007 			}
1008 			if (frame[0] != 0xff) {
1009 			    protoTrace("HDLC frame with bad address field %#x", frame[0]);
1010 			    return (false);
1011 			}
1012 			if ((frame[1]&0xf7) != 0xc0) {
1013 			    protoTrace("HDLC frame with bad control field %#x", frame[1]);
1014 			    return (false);
1015 			}
1016 			return (true);
1017 		    case 0x07:
1018 			protoTrace("FCS error");
1019 			return (false);
1020 		    case 0x04:
1021 			protoTrace("EOT received (end of transmission)");
1022 			gotEOT = true;
1023 			recvdDCN = true;
1024 			return (false);
1025 		    case 0x6D:
1026 			protoTrace("Control channel selected");
1027 			gotCTRL = true;
1028 			return (false);
1029 		    default:
1030 			protoTrace("got <DLE><%X>", c);
1031 			break;
1032 		}
1033 	    }
1034 	    frame.put(frameRev[c]);
1035 	}
1036     }
1037 
1038     int bit = getModemBit(60000);
1039     u_short ones = 0;
1040 
1041     // look for the last sync flag (possibly the previous one)
1042 
1043     // some senders use this as the time to do framing so we must wait longer than T.4 A.3.1 implies
1044     time_t start = Sys::now();
1045     while (bit != 1 && bit != EOF && !didBlockEnd()) {	// flag begins with zero, address begins with one
1046 	do {
1047 	    if ((unsigned) Sys::now()-start >= 300) {	// 5 minutes of synchronization is too much
1048 		protoTrace("Timeout waiting for the last synchronization flag");
1049 		return false;
1050 	    }
1051 	    if (bit == 0 || ones > 6) ones = 0;
1052 	    bit = getModemBit(60000);
1053 	    if (bit == 1) ones++;
1054 	} while (!(ones == 6 && bit == 0 && bit != EOF) && !didBlockEnd());
1055 	ones = 0;
1056 	bit = getModemBit(60000);
1057     }
1058 
1059     // receive the frame, strip stuffed zero-bits, and look for end flag
1060 
1061     ones = 1;
1062     u_short bitpos = 7;
1063     u_int byte = (bit << bitpos);
1064     bool rcpframe = false;
1065     start = Sys::now();
1066     do {
1067 	if ((unsigned) Sys::now()-start >= 3) {
1068 	    protoTrace("Timeout receiving HDLC frame");
1069 	    return (false);
1070 	}
1071 	bit = getModemBit(60000);
1072 	if (bit == 1) {
1073 	    ones++;
1074 	}
1075 	if (!(ones == 5 && bit == 0 && bit != EOF)) {	// not transparent stuffed zero-bits
1076 	    bitpos--;
1077 	    byte |= (bit << bitpos);
1078 	    if (bitpos == 0) {			// fully populated byte
1079 		frame.put(byte);
1080 		bitpos = 8;
1081 		byte = 0;
1082 	    }
1083 	}
1084 	if (bit == 0) ones = 0;
1085 	// don't wait for the terminating flag on an RCP frame
1086 	if (frame[0] == 0xff && frame[1] == 0xc0 && frame[2] == 0x61 && frame.getLength() == 5 && frame.checkCRC()) {
1087 	    protoTrace("RECV received RCP frame");
1088 	    rcpframe = true;
1089 	} else if (didBlockEnd()) {
1090 	    // sometimes RCP frames are truncated by or are missing due to premature DLE+ETX characters, sadly
1091 	    protoTrace("RECV assumed RCP frame with block end");
1092 	    // force-feed a valid RCP frame with FCS
1093 	    frame.reset();
1094 	    frame.put(0xff); frame.put(0xc0); frame.put(0x61); frame.put(0x96); frame.put(0xd3);
1095 	    rcpframe = true;
1096 	}
1097     } while (ones != 6 && bit != EOF && !rcpframe && frame.getLength() < frameSize+6);
1098     if (ones == 6) bit = getModemBit(60000);			// trailing bit on flag
1099     if (!rcpframe && frame.getLength() < frameSize+6) {
1100 	/*
1101 	 * The HDLC frame was terminated early by a flag.  T.30 A.3.5 states that
1102 	 * frame size cannot change during one page, and T.4 A.3.6.2 seems to provide
1103 	 * for padding in order to get that last frame on a block to always line up
1104 	 * on a byte and frame boundary.  However, the NOTE 2 there seemse to give
1105 	 * leniency to that requirement, and in fact many senders will send short
1106 	 * frames on the last frame of a block.  So we run a couple of additional
1107 	 * checks here (in addition to FCS checking) to limit the remote chance
1108 	 * of FCS actually checking out on corrupt data (although that may be very
1109 	 * remote indeed).  We don't do these "trailing flag" tests on normal-sized
1110 	 * frames because we deliberately don't look for a trailing flag when we
1111 	 * get enough data.
1112 	 */
1113 	if (bit) {				// should have been zero
1114 	    protoTrace("Bad HDLC terminating flag received.");
1115 	    return (false);
1116 	}
1117 	if (byte != 0x7e) {			// trailing byte should be flag
1118 	    protoTrace("HDLC frame not byte-oriented.  Trailing byte: %#x", byte);
1119 	    return (false);
1120 	}
1121     }
1122     traceHDLCFrame("-->", frame, true);
1123     if (bit == EOF) {
1124 	protoTrace("EOF received.");
1125 	return (false);
1126     }
1127     if (frame.getLength() < 5) {		// RCP frame size
1128 	protoTrace("HDLC frame too short (%u bytes)", frame.getLength());
1129 	return (false);
1130     }
1131     if (frame[0] != 0xff) {
1132 	protoTrace("HDLC frame with bad address field %#x", frame[0]);
1133 	return (false);
1134     }
1135     if ((frame[1]&0xf7) != 0xc0) {
1136 	protoTrace("HDLC frame with bad control field %#x", frame[1]);
1137 	return (false);
1138     }
1139     return (true);
1140 }
1141 
1142 bool
endECMBlock()1143 Class1Modem::endECMBlock()
1144 {
1145     if (didBlockEnd()) return (true);	// some erroniously re-use bytes
1146 
1147     int c = getLastByte();		// some erroniously re-use bits
1148     time_t start = Sys::now();
1149     setTimeout(false);
1150     do {
1151 	if ((unsigned) Sys::now()-start >= 60) {	// 60 seconds of garbage after RCP is too much
1152 	    protoTrace("Timeout waiting for DLE+ETX");
1153 	    setTimeout(true);
1154 	    return false;
1155 	}
1156 	if (c == DLE) {
1157 	    c = getModemChar(30*1000);
1158 	    if (c == ETX || c == EOF)
1159 		break;
1160 	}
1161     } while ((c = getModemChar(30*1000)) != EOF);
1162     if (c == EOF) return (false);
1163     else return (true);
1164 }
1165 
1166 #include "StackBuffer.h"
1167 
1168 /*
1169  * Log an HLDC frame along with a time stamp (secs.10ms).
1170  */
1171 void
traceHDLCFrame(const char * direction,const HDLCFrame & frame,bool isecm)1172 Class1Modem::traceHDLCFrame(const char* direction, const HDLCFrame& frame, bool isecm)
1173 {
1174     if (!isecm) {
1175 	if (!getHDLCTracing()) return;
1176     } else {
1177 	if (!getECMTracing()) return;
1178     }
1179     const char* hexdigits = "0123456789ABCDEF";
1180     fxStackBuffer buf;
1181     for (u_int i = 0; i < frame.getLength(); i++) {
1182 	u_char b = frame[i];
1183 	if (i > 0)
1184 	    buf.put(' ');
1185 	buf.put(hexdigits[b>>4]);
1186 	buf.put(hexdigits[b&0xf]);
1187     }
1188     protoTrace("%s HDLC<%u:%.*s>", direction,
1189 	frame.getLength(), buf.getLength(), (const char*) buf);
1190 }
1191 
1192 /*
1193  * Send a raw HDLC frame and wait for the modem response.
1194  * The modem is expected to be an HDLC frame sending mode
1195  * (i.e. +FTH=3 or similar has already be sent to the modem).
1196  * The T.30 max frame length is enforced with a 3 second
1197  * timeout on the send.
1198  */
1199 bool
sendRawFrame(HDLCFrame & frame)1200 Class1Modem::sendRawFrame(HDLCFrame& frame)
1201 {
1202     traceHDLCFrame("<--", frame);
1203     if (frame.getLength() < 3) {
1204 	protoTrace("HDLC frame too short (%u bytes)", frame.getLength());
1205 	return (false);
1206     }
1207     if (frame[0] != 0xff) {
1208 	protoTrace("HDLC frame with bad address field %#x", frame[0]);
1209 	return (false);
1210     }
1211     if ((frame[1]&0xf7) != 0xc0) {
1212 	protoTrace("HDLC frame with bad control field %#x", frame[1]);
1213 	return (false);
1214     }
1215     signalSent = "";
1216     for (u_int i = 0; i < frame.getLength(); i++) signalSent.append(frame[i]);
1217     /*
1218      * sendFrame() is always called with a timeout set.
1219      * Let's keep it that way
1220      */
1221     return (sendClass1Data(frame, frame.getLength(), frameRev, true, 0) &&
1222 	(useV34 ? true : waitFor(frame.moreFrames() ? AT_CONNECT : AT_OK, 0)));
1223 }
1224 
1225 /*
1226  * Send a single byte frame.
1227  */
1228 bool
sendFrame(u_char fcf,bool lastFrame)1229 Class1Modem::sendFrame(u_char fcf, bool lastFrame)
1230 {
1231     HDLCFrame frame(conf.class1FrameOverhead);
1232     frame.put(0xff);
1233     frame.put(lastFrame ? 0xc8 : 0xc0);
1234     frame.put(fcf);
1235     return (sendRawFrame(frame));
1236 }
1237 
1238 /*
1239  * Send a frame with DCS/DIS.
1240  */
1241 bool
sendFrame(u_char fcf,FaxParams & dcs_caps,bool lastFrame)1242 Class1Modem::sendFrame(u_char fcf, FaxParams& dcs_caps, bool lastFrame)
1243 {
1244     HDLCFrame frame(conf.class1FrameOverhead);
1245     frame.put(0xff);
1246     frame.put(lastFrame ? 0xc8 : 0xc0);
1247     frame.put(fcf);
1248 
1249     int curByte = 0;
1250     //add dcs bytes an any optional bytes
1251     frame.put(dcs_caps.getByte(curByte));
1252     while (dcs_caps.hasNextByte(curByte)) {
1253         curByte += 1;
1254         frame.put(dcs_caps.getByte(curByte));
1255     }
1256 
1257     return (sendRawFrame(frame));
1258 }
1259 
1260 /*
1261  * Send a frame with TSI/CSI/PWD/SUB/SEP/PPR.
1262  */
1263 bool
sendFrame(u_char fcf,const fxStr & tsi,bool lastFrame)1264 Class1Modem::sendFrame(u_char fcf, const fxStr& tsi, bool lastFrame)
1265 {
1266     HDLCFrame frame(conf.class1FrameOverhead);
1267     frame.put(0xff);
1268     frame.put(lastFrame ? 0xc8 : 0xc0);
1269     frame.put(fcf);
1270     frame.put((const u_char*)(const char*)tsi, tsi.length());
1271     return (sendRawFrame(frame));
1272 }
1273 
1274 /*
1275  * Send a frame with NSF.
1276  */
1277 bool
sendFrame(u_char fcf,const u_char * code,const fxStr & nsf,bool lastFrame)1278 Class1Modem::sendFrame(u_char fcf, const u_char* code, const fxStr& nsf, bool lastFrame)
1279 {
1280     HDLCFrame frame(conf.class1FrameOverhead);
1281     frame.put(0xff);
1282     frame.put(lastFrame ? 0xc8 : 0xc0);
1283     frame.put(fcf);
1284     frame.put(code, 3);		// should be in LSBMSB already
1285     frame.put((const u_char*)(const char*)nsf, nsf.length());
1286     return (sendRawFrame(frame));
1287 }
1288 
1289 bool
transmitFrame(fxStr & signal)1290 Class1Modem::transmitFrame(fxStr& signal)
1291 {
1292     HDLCFrame frame(conf.class1FrameOverhead);
1293     for (u_int i = 0; i < signal.length(); i++) frame.put(signal[i]);
1294     startTimeout(7550);
1295     bool frameSent = useV34 ? true : atCmd(thCmd, AT_NOTHING, 0);
1296     if (frameSent) frameSent = useV34 ? true : atResponse(rbuf, 0) == AT_CONNECT;
1297     if (frameSent) frameSent = sendRawFrame(frame);
1298     else if (lastResponse == AT_ERROR) gotEOT = true;	// on hook
1299     stopTimeout("sending HDLC frame");
1300     return (frameSent);
1301 }
1302 
1303 bool
transmitFrame(u_char fcf,bool lastFrame)1304 Class1Modem::transmitFrame(u_char fcf, bool lastFrame)
1305 {
1306     startTimeout(7550);
1307     bool frameSent = useV34 ? true : atCmd(thCmd, AT_NOTHING, 0);
1308     if (frameSent) frameSent = useV34 ? true : atResponse(rbuf, 0) == AT_CONNECT;
1309     if (frameSent) frameSent = sendFrame(fcf, lastFrame);
1310     else if (lastResponse == AT_ERROR) gotEOT = true;	// on hook
1311     stopTimeout("sending HDLC frame");
1312     return (frameSent);
1313 }
1314 
1315 bool
transmitFrame(u_char fcf,FaxParams & dcs_caps,bool lastFrame)1316 Class1Modem::transmitFrame(u_char fcf, FaxParams& dcs_caps, bool lastFrame)
1317 {
1318     /*
1319      * The T.30 spec says no frame can take more than 3 seconds
1320      * (+/- 15%) to transmit.  But the DCE can take as much as 5
1321      * seconds to respond CONNECT or result OK, per T.31.
1322      */
1323     startTimeout(7550);
1324     bool frameSent = useV34 ? true : atCmd(thCmd, AT_NOTHING, 0);
1325     if (frameSent) frameSent = useV34 ? true : atResponse(rbuf, 0) == AT_CONNECT;
1326     if (frameSent) frameSent = sendFrame(fcf, dcs_caps, lastFrame);
1327     else if (lastResponse == AT_ERROR) gotEOT = true;	// on hook
1328     stopTimeout("sending HDLC frame");
1329     return (frameSent);
1330 }
1331 
1332 bool
transmitFrame(u_char fcf,const fxStr & tsi,bool lastFrame)1333 Class1Modem::transmitFrame(u_char fcf, const fxStr& tsi, bool lastFrame)
1334 {
1335     startTimeout(7550);
1336     bool frameSent = useV34 ? true : atCmd(thCmd, AT_NOTHING, 0);
1337     if (frameSent) frameSent = useV34 ? true : atResponse(rbuf, 0) == AT_CONNECT;
1338     if (frameSent) frameSent = sendFrame(fcf, tsi, lastFrame);
1339     else if (lastResponse == AT_ERROR) gotEOT = true;	// on hook
1340     stopTimeout("sending HDLC frame");
1341     return (frameSent);
1342 }
1343 
1344 bool
transmitFrame(u_char fcf,const u_char * code,const fxStr & nsf,bool lastFrame)1345 Class1Modem::transmitFrame(u_char fcf, const u_char* code, const fxStr& nsf, bool lastFrame)
1346 {
1347     startTimeout(7550);
1348     bool frameSent = useV34 ? true : atCmd(thCmd, AT_NOTHING, 0);
1349     if (frameSent) frameSent = useV34 ? true : atResponse(rbuf, 0) == AT_CONNECT;
1350     if (frameSent) frameSent = sendFrame(fcf, code, nsf, lastFrame);
1351     else if (lastResponse == AT_ERROR) gotEOT = true;	// on hook
1352     stopTimeout("sending HDLC frame");
1353     return (frameSent);
1354 }
1355 
1356 /*
1357  * Send data using the specified signalling rate.
1358  */
1359 bool
transmitData(int br,u_char * data,u_int cc,const u_char * bitrev,bool eod)1360 Class1Modem::transmitData(int br, u_char* data, u_int cc,
1361     const u_char* bitrev, bool eod)
1362 {
1363     if (flowControl == FLOW_XONXOFF)
1364 	setXONXOFF(FLOW_XONXOFF, FLOW_NONE, ACT_FLUSH);
1365     fxStr tmCmd(br, tmCmdFmt);
1366     bool ok = atCmd(tmCmd, AT_CONNECT);
1367     if (ok) {
1368 
1369 	// T.31 8.3.3 requires the DCE to report CONNECT at the beginning
1370 	// of transmission of the training pattern rather than at the end.
1371 	// We pause here to allow the remote's +FRM to result in CONNECT.
1372 	// This delay will vary depending on the modem's adherence to T.31.
1373 	pause(conf.class1TMConnectDelay);
1374 
1375 	ok = sendClass1Data(data, cc, bitrev, eod, getDataTimeout());
1376 	if (ok && eod) {
1377 	    ok = false;
1378 	    u_short attempts = 0;
1379 	    lastResponse = AT_NOTHING;
1380 	    while (!ok && lastResponse != AT_NOCARRIER && attempts++ < 3) {
1381 		ok = waitFor(AT_OK, 60*1000);	// wait up to 60 seconds for "OK"
1382 	    }
1383 	}
1384     } else if (lastResponse == AT_ERROR) gotEOT = true;	// on hook
1385     if (flowControl == FLOW_XONXOFF)
1386 	setXONXOFF(FLOW_NONE, FLOW_NONE, ACT_DRAIN);
1387     return (ok);
1388 }
1389 
1390 /*
1391  * Receive an HDLC frame.  The timeout is against
1392  * the receipt of the HDLC flags; the frame itself must
1393  * be received within 3 seconds (per the spec).
1394  * If a carrier is received, but the complete frame
1395  * is not received before the timeout, the receive
1396  * is aborted.
1397  *
1398  * If the frame is received in error, then in instances
1399  * where the other end is likely to be able to receive
1400  * it, we can transmit CRP to get the other end to
1401  * retransmit the frame.
1402  */
1403 bool
recvFrame(HDLCFrame & frame,u_char dir,long ms,bool readPending,bool docrp,bool usehooksensitivity)1404 Class1Modem::recvFrame(HDLCFrame& frame, u_char dir, long ms, bool readPending, bool docrp, bool usehooksensitivity)
1405 {
1406     bool gotframe;
1407     u_short crpcnt = 0, rhcnt = 0;
1408     u_int onhooks = 0;
1409     gotCONNECT = true;
1410     time_t start = Sys::now();
1411     if (useV34) {
1412 	do {
1413 	    if (crpcnt) traceFCF(dir == FCF_SNDR ? "SEND send" : "RECV send", FCF_CRP);
1414 	    frame.reset();
1415 	    gotframe = recvRawFrame(frame);
1416 	} while (!gotframe && !gotRTNC && !gotEOT && docrp && crpcnt++ < 3 && !wasTimeout() && transmitFrame(dir|FCF_CRP));
1417 	return (gotframe);
1418     }
1419     startTimeout(ms);
1420     if (!readPending) {
1421 	/*
1422 	 * Hopefully the modem is smart enough to *not* do +FCERROR after +FRH=3,
1423 	 * as it is only a stumbling-block for us and cannot be beneficial.  But,
1424 	 * in case it adheres blindly to the spec, we'll repeat ourselves here
1425 	 * until we timeout or we do get the V.21 carrier.  We do slow the looping
1426 	 * with a pause to prevent unwanted massive amounts of tracing.  The pause
1427 	 * needs to be short enough, though, that the modem will still pick up
1428 	 * any V.21 signalling if it misses that much of the startup.
1429 	 */
1430 	do {
1431 	    readPending = atCmd(rhCmd, AT_NOTHING, 0) && waitFor(AT_CONNECT, 0);
1432 	    if (lastResponse == AT_FCERROR) pause(200);
1433 	    if (lastResponse == AT_ERROR && !wasTimeout() && ++onhooks <= conf.class1HookSensitivity) {
1434 		if (!usehooksensitivity) {
1435 		    /*
1436 		     * Class1HookSensitivity is used by the calling function, not us.
1437 		     */
1438 		    break;
1439 		} else {
1440 		    stopTimeout("");
1441 		    startTimeout(ms);
1442 		}
1443 	    }
1444 	} while (((u_int) Sys::now()-start < howmany(conf.t1Timer, 1000)) && !wasTimeout() &&
1445 	    (lastResponse == AT_FCERROR || (lastResponse == AT_ERROR && onhooks <= conf.class1HookSensitivity)));
1446     }
1447     if (readPending) {
1448         stopTimeout("waiting for HDLC flags");
1449         if (wasTimeout()){
1450             abortReceive();
1451             return (false);
1452         }
1453 	Status eresult;
1454 	do {
1455 	    if (crpcnt || rhcnt) {
1456 		if (rhcnt) crpcnt = 0;
1457 		if (crpcnt) {
1458 		    rhcnt = 0;
1459 		    traceFCF(dir == FCF_SNDR ? "SEND send" : "RECV send", FCF_CRP);
1460 		}
1461 		do {
1462 		    lastResponse = AT_NOTHING;
1463 		    startTimeout(ms);
1464 		    if (!(atCmd(rhCmd, AT_NOTHING, 0) && waitFor(AT_CONNECT,0))) {
1465 			stopTimeout("waiting for v.21 carrier");
1466 			if (wasTimeout()) {
1467 			    abortReceive();
1468 			    setTimeout(false);
1469 			}
1470 			if (lastResponse != AT_NOCARRIER || rhcnt++ > 30) return (false);
1471 		    }
1472 		    stopTimeout("waiting for v.21 carrier");
1473 		    /*
1474 		     * The meaning of a direct NO CARRIER response/result to the AT+FRH=3
1475 		     * command can be interpreted two ways due to wording in ITU T.31.
1476 		     * The more traditional interpretation is that it is out-of-spec: that
1477 		     * a NO CARRIER response should only come after a CONNECT message.
1478 		     * However, T.31 gives sample sessions that illustrate precisely this
1479 		     * kind of out-of-spec sequence:
1480 		     *
1481 		     * <-- AT+FRH=3
1482 		     * --> NO CARRIER
1483 		     *
1484 		     * And the interpretation is clear to indicate that in this case the
1485 		     * modem detected a carrier, but it apparently was not V.21 HDLC, and
1486 		     * the NO CARRIER response indicates that the indeterminate carrier
1487 		     * has dropped.  This functionality is more cumbersome than it is
1488 		     * helpful (its value is not much different than that of an AT+FRS=1
1489 		     * command), and what it really means is that we just need to re-issue
1490 		     * the AT+FRH=3 command until we get something useful as this scenario
1491 		     * will most likely occur on incidence of Phase C premature carrier loss.
1492 		     */
1493 		} while (lastResponse == AT_NOCARRIER);
1494 	    }
1495 	    frame.reset();
1496             gotframe = recvRawFrame(frame);
1497 	    /*
1498 	     * Some modems aren't very particular about reporting CONNECT after AT+FRH=3.
1499 	     * So, for such modems CONNECT may come with V.17 modulated audio or any noise
1500 	     * whatsoever.  Those modems tend to report NO CARRIER after CONNECT, perhaps
1501 	     * after <DLE><ETX> or some other garbage possibly.  NO CARRIER is an invalid
1502 	     * modem response at that point, anyway.  So it is a good indicator for us.
1503 	     * So we simply repeat AT+FRH=3 in that case.
1504 	     */
1505 	} while ( ((u_int) Sys::now()-start < howmany(conf.t1Timer, 1000) )
1506 		    && !gotframe && !wasTimeout()
1507 		    && ( (conf.class1HasRHConnectBug && !frame.getLength() && lastResponse == AT_NOCARRIER && rhcnt++ < 30)
1508 		         || (docrp && crpcnt++ < 3 && switchingPause(eresult, 3) && transmitFrame(dir|FCF_CRP) )
1509 		    ));	/* triple switchingPause to avoid sending CRP during TCF */
1510 	return (gotframe);
1511     } else {
1512 	gotCONNECT = false;
1513 	if (lastResponse == AT_ERROR) gotEOT = true;		// on hook
1514     }
1515     stopTimeout("waiting for v.21 carrier");
1516     if (wasTimeout()) {
1517 	abortReceive();
1518 	setTimeout(false);
1519     }
1520     return (false);
1521 }
1522 
1523 /*
1524  * Receive TCF data using the specified signalling rate.
1525  */
1526 bool
recvTCF(int br,HDLCFrame & buf,const u_char * bitrev,long ms)1527 Class1Modem::recvTCF(int br, HDLCFrame& buf, const u_char* bitrev, long ms)
1528 {
1529     buf.reset();
1530     if (flowControl == FLOW_XONXOFF)
1531 	setXONXOFF(FLOW_NONE, FLOW_XONXOFF, ACT_DRAIN);
1532     /*
1533      * Loop waiting for carrier or timeout.
1534      */
1535     bool readPending, gotCarrier;
1536     fxStr rmCmd(br, rmCmdFmt);
1537     startTimeout(ms);
1538     u_short attempts = 0;
1539     do {
1540 	readPending = atCmd(rmCmd, AT_NOTHING, 0);
1541 	gotCarrier = readPending && waitFor(AT_CONNECT, 0);
1542     } while (readPending && !gotCarrier && lastResponse == AT_FCERROR && ++attempts < conf.class1RMPersistence);
1543     /*
1544      * If carrier was recognized, collect the data.
1545      */
1546     bool gotData = false;
1547     if (gotCarrier) {
1548 	int c = getModemChar(0);		// NB: timeout is to first byte
1549 	stopTimeout("receiving TCF");
1550 	if (c != EOF) {
1551 	    buf.reset();
1552 	    /*
1553 	     * Use a  timer to receive the 1.5
1554 	     * second TCF--perhaps if it is too long it
1555 	     * won't permit us to send the nak in time?
1556 	     *
1557 	     * The initial timer needs to be longer than 1.5 seconds
1558 	     * to support senders that may not start the zeros
1559 	     * until a second or two after CONNECT.  This is
1560 	     * also why we restart our timeout after the zeros
1561 	     * start.
1562 	     */
1563 	    bool zerosstarted = false;
1564 	    startTimeout(ms);
1565 	    do {
1566 		if (c == 0x00 && !zerosstarted) {
1567 		    zerosstarted = true;
1568 		    startTimeout(ms);
1569 		}
1570 		if (c == DLE) {
1571 		    c = getModemChar(0);
1572 		    if (c == ETX) {
1573 			gotData = true;
1574 			break;
1575 		    }
1576 		    if (c == EOF) {
1577 			break;
1578 		    }
1579 		}
1580 		buf.put(bitrev[c]);
1581 		if (buf.getLength() > 10000) {
1582 		    setTimeout(true);
1583 		    break;
1584 		}
1585 	    } while ((c = getModemChar(0)) != EOF);
1586 	}
1587     }
1588     stopTimeout("receiving TCF");
1589     /*
1590      * If the +FRM is still pending, abort it.
1591      */
1592     if (readPending && wasTimeout())
1593 	abortReceive();
1594     if (flowControl == FLOW_XONXOFF)
1595 	setXONXOFF(FLOW_NONE, FLOW_NONE, ACT_DRAIN);
1596     return (gotData);
1597 }
1598 
1599 /*
1600  * Modem manipulation support.
1601  */
1602 
1603 /*
1604  * Reset a Class 1 modem.
1605  */
1606 bool
reset(long ms)1607 Class1Modem::reset(long ms)
1608 {
1609     return (FaxModem::reset(ms) && setupClass1Parameters());
1610 }
1611 
1612 ATResponse
atResponse(char * buf,long ms)1613 Class1Modem::atResponse(char* buf, long ms)
1614 {
1615     if (FaxModem::atResponse(buf, ms) == AT_OTHER && strneq(buf, "+FCERROR", 8))
1616 	lastResponse = AT_FCERROR;
1617     if (lastResponse == AT_OTHER && strneq(buf, "+FRH:3", 6))
1618 	lastResponse = AT_FRH3;
1619     if (lastResponse == AT_OTHER && strneq(buf, "+F34:", 5)) {
1620 	/*
1621 	 * V.8 handshaking was successful.  The rest of the
1622 	 * session is governed by T.31 Amendment 1 Annex B.
1623 	 * (This should only happen after ATA or ATD.)
1624 	 *
1625 	 * The +F34: response is interpreted according to T.31-A1 B.6.2.
1626 	 */
1627 	buf += 5;					// skip "+F34:" prefix
1628 	primaryV34Rate = 0;
1629 	while (!isdigit(buf[0])) buf++;		// move to digits
1630 	do {
1631 	    primaryV34Rate = primaryV34Rate*10 + (buf[0] - '0');
1632         } while (isdigit((++buf)[0]));
1633 	controlV34Rate = 0;
1634 	while (!isdigit(buf[0])) buf++;		// move to digits
1635 	do {
1636 	    controlV34Rate = controlV34Rate*10 + (buf[0] - '0');
1637         } while (isdigit((++buf)[0]));
1638 	useV34 = true;
1639 	protoTrace("V.8 handshaking succeeded, V.34-Fax (SuperG3) capability enabled.");
1640 	protoTrace("Primary channel rate: %u bit/s, Control channel rate: %u bit/s.", primaryV34Rate*2400, controlV34Rate*1200);
1641 	modemParams.br |= BIT(primaryV34Rate) - 1;
1642     }
1643     return (lastResponse);
1644 }
1645 
1646 /*
1647  * Wait (carefully) for some response from the modem.
1648  */
1649 bool
waitFor(ATResponse wanted,long ms)1650 Class1Modem::waitFor(ATResponse wanted, long ms)
1651 {
1652     for (;;) {
1653 	ATResponse response = atResponse(rbuf, ms);
1654 	if (response == wanted)
1655 	    return (true);
1656 	switch (response) {
1657 	case AT_TIMEOUT:
1658 	case AT_EMPTYLINE:
1659 	case AT_ERROR:
1660 	case AT_NOCARRIER:
1661 	case AT_NODIALTONE:
1662 	case AT_NOANSWER:
1663 	case AT_OFFHOOK:
1664 	case AT_RING:
1665 	    modemTrace("MODEM %s", ATresponses[response]);
1666 	    /* fall thru... */
1667 	case AT_OTHER:
1668 	case AT_FCERROR:
1669 	case AT_FRH3:
1670 	case AT_OK:
1671 	    return (false);
1672 	}
1673     }
1674 }
1675 
1676 /*
1677  * Send queryCmd and get a range response.
1678  */
1679 bool
class1Query(const fxStr & queryCmd,Class1Cap caps[])1680 Class1Modem::class1Query(const fxStr& queryCmd, Class1Cap caps[])
1681 {
1682     char response[1024];
1683     if (queryCmd[0] == '!') {
1684 	return (parseQuery(queryCmd.tail(queryCmd.length()-1), caps));
1685     }
1686     if (atCmd(queryCmd, AT_NOTHING) && atResponse(response) == AT_OTHER) {
1687 	sync(5000);
1688 	return (parseQuery(response, caps));
1689     }
1690     return (false);
1691 }
1692 
1693 /*
1694  * Map the DCS signalling rate to the appropriate
1695  * Class 1 capability entry.
1696  */
1697 const Class1Cap*
findSRCapability(u_short sr,const Class1Cap caps[])1698 Class1Modem::findSRCapability(u_short sr, const Class1Cap caps[])
1699 {
1700     for (u_int i = NCAPS-1; i > 0; i--) {
1701 	const Class1Cap* cap = &caps[i];
1702 	if (cap->sr == sr) {
1703 	    if (cap->mod == V17 && HasShortTraining(cap-1))
1704 		cap--;
1705 	    return (cap);
1706 	}
1707     }
1708     // XXX should not happen...
1709     protoTrace("MODEM: unknown signalling rate %#x, using 9600 v.29", sr);
1710     return findSRCapability(DCSSIGRATE_9600V29, caps);
1711 }
1712 
1713 /*
1714  * Map the Class 2 bit rate to the best
1715  * signalling rate capability of the modem.
1716  */
1717 const Class1Cap*
findBRCapability(u_short br,const Class1Cap caps[])1718 Class1Modem::findBRCapability(u_short br, const Class1Cap caps[])
1719 {
1720     for (u_int i = NCAPS-1; i > 0; i--) {
1721 	const Class1Cap* cap = &caps[i];
1722 	if (cap->br == br && cap->ok) {
1723 	    if (cap->mod == V17 && HasShortTraining(cap-1))
1724 		cap--;
1725 	    return (cap);
1726 	}
1727     }
1728     protoTrace("MODEM: unsupported baud rate %#x", br);
1729     return NULL;
1730 }
1731 
1732 /*
1733  * Build upon the result from Class2Params.
1734  */
1735 FaxParams
modemDIS() const1736 Class1Modem::modemDIS() const
1737 {
1738     FaxParams dis_caps = FaxModem::modemDIS();
1739 
1740     // signalling rates
1741     for (u_short i = 0; i < 4; i++) dis_caps.setBit(11+i, (discap & (0x08>>i)));
1742     if (useV34) dis_caps.setBit(FaxParams::BITNUM_V8_CAPABLE, true);
1743 
1744     // preferred ECM frame size
1745     if (conf.class1ECMFrameSize == 64) dis_caps.setBit(FaxParams::BITNUM_FRAMESIZE_DIS, true);
1746 
1747     // we set both units preferences to allow the sender to choose
1748     dis_caps.setBit(FaxParams::BITNUM_METRIC_RES, true);
1749     dis_caps.setBit(FaxParams::BITNUM_INCH_RES, true);
1750 
1751     // we indicate both letter and legal page size support
1752     dis_caps.setBit(FaxParams::BITNUM_LETTER_SIZE, true);
1753     dis_caps.setBit(FaxParams::BITNUM_LEGAL_SIZE, true);
1754 
1755     // selective polling, subaddressing, password
1756     dis_caps.setBit(FaxParams::BITNUM_SEP, true);
1757     dis_caps.setBit(FaxParams::BITNUM_SUB, true);
1758     dis_caps.setBit(FaxParams::BITNUM_PWD, true);
1759 
1760     if (conf.class1ECMSupport) {
1761 	// JBIG
1762 	if (jbigSupported) {
1763 	    dis_caps.setBit(FaxParams::BITNUM_JBIG_BASIC, true);
1764 	    dis_caps.setBit(FaxParams::BITNUM_JBIG_L0, true);	// JBIG library can handle L0 = 1-Yd
1765 	}
1766 /* - disabled for now
1767 	// JBIG grey/color requires JPEG grey/color
1768 	if (conf.class1GreyJBIGSupport || conf.class1ColorJBIGSupport) {
1769 	    dis_caps.setBit(FaxParams::BITNUM_JPEG, true);
1770 	    dis_caps.setBit(FaxParams::BITNUM_JBIG, true);
1771 	}
1772 	if (conf.class1ColorJBIGSupport)
1773 	    dis_caps.setBit(FaxParams::BITNUM_FULLCOLOR, true);
1774 */
1775 	// JPEG
1776 	if (conf.class1GreyJPEGSupport || conf.class1ColorJPEGSupport)
1777 	    dis_caps.setBit(FaxParams::BITNUM_JPEG, true);
1778 	if (conf.class1ColorJPEGSupport)
1779 	    dis_caps.setBit(FaxParams::BITNUM_FULLCOLOR, true);
1780     }
1781     return dis_caps;
1782 }
1783 
1784 const char COMMA = ',';
1785 const char SPACE = ' ';
1786 
1787 /*
1788  * Parse a Class 1 parameter string.
1789  */
1790 bool
parseQuery(const char * cp,Class1Cap caps[])1791 Class1Modem::parseQuery(const char* cp, Class1Cap caps[])
1792 {
1793     bool bracket = false, first = true;
1794 
1795     while (cp[0]) {
1796 	if (cp[0] == SPACE) {		// ignore white space
1797 	    cp++;
1798 	    continue;
1799 	}
1800 
1801         /* by a.pogoda@web.de, jan 21st 2002
1802          * workaround for modems sending (<item>,<item>,...), i.e.
1803          * enclosed in brackets rather than just <item>,<item>,...
1804          * e.g. elsa microlink 56k internet II and maybo others
1805          */
1806         if (cp[0]=='(' && first && !bracket) {
1807           /* check whether the first non-space char is an
1808            * opening bracket and skip it if true
1809            */
1810           bracket = true;
1811           cp++;
1812           continue;
1813         }
1814         else if (cp[0]==')' && !first && bracket) {
1815           /* if an opening bracket was scanned before and
1816            * the current char is a closing one, skip it
1817            */
1818           bracket = false;
1819           cp++;
1820           continue;
1821         }
1822         else if (!isdigit(cp[0]))
1823 	  return (false);
1824 
1825         /* state that we already scanned past the first char */
1826         first = false;
1827 	int v = 0;
1828 	do {
1829 	    v = v*10 + (cp[0] - '0');
1830 	} while (isdigit((++cp)[0]));
1831 	int r = v;
1832 	if (cp[0] == '-') {				// <low>-<high>
1833 	    cp++;
1834 	    if (!isdigit(cp[0])) {
1835 		return (false);
1836 	    }
1837 	    r = 0;
1838 	    do {
1839 		r = r*10 + (cp[0] - '0');
1840 	    } while (isdigit((++cp)[0]));
1841 	}
1842 	for (u_int i = 0; i < NCAPS; i++)
1843 	    if (caps[i].value >= v && caps[i].value <= r) {
1844 		caps[i].ok = true;
1845 		break;
1846 	    }
1847 	if (cp[0] == COMMA)		// <item>,<item>...
1848 	    cp++;
1849     }
1850     return (true);
1851 }
1852 
1853