00001 /* 00002 * SpanDSP - a series of DSP components for telephony 00003 * 00004 * t30.h - definitions for T.30 fax processing 00005 * 00006 * Written by Steve Underwood <steveu@coppice.org> 00007 * 00008 * Copyright (C) 2003 Steve Underwood 00009 * 00010 * All rights reserved. 00011 * 00012 * This program is free software; you can redistribute it and/or modify 00013 * it under the terms of the GNU General Public License version 2, as 00014 * published by the Free Software Foundation. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License 00022 * along with this program; if not, write to the Free Software 00023 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00024 * 00025 * $Id: t30.h,v 1.93 2008/02/20 13:01:45 steveu Exp $ 00026 */ 00027 00028 /*! \file */ 00029 00030 #if !defined(_SPANDSP_T30_H_) 00031 #define _SPANDSP_T30_H_ 00032 00033 /*! \page t30_page T.30 FAX protocol handling 00034 00035 \section t30_page_sec_1 What does it do? 00036 The T.30 protocol is the core protocol used for FAX transmission. This module 00037 implements most of its key featrues. It does not interface to the outside work. 00038 Seperate modules do that for T.38, analogue line, and other forms of FAX 00039 communication. 00040 00041 Current features of this module include: 00042 00043 - FAXing to and from multi-page TIFF/F files, whose images are one of the standard 00044 FAX sizes. 00045 - T.4 1D (MH), T.4 2D,(MR) and T.6 (MMR) compression. 00046 - Error correction (ECM) 00047 - All standard resolutions and page sizes 00048 00049 \section t30_page_sec_2 How does it work? 00050 00051 Some of the following is paraphrased from some notes found a while ago on the Internet. 00052 I cannot remember exactly where they came from, but they are useful. 00053 00054 The answer (CED) tone 00055 00056 The T.30 standard says an answering fax device must send CED (a 2100Hz tone) for 00057 approximately 3 seconds before sending the first handshake message. Some machines 00058 send an 1100Hz or 1850Hz tone, and some send no tone at all. In fact, this answer 00059 tone is so unpredictable, it cannot really be used. It should, however, always be 00060 generated according to the specification. 00061 00062 Common Timing Deviations 00063 00064 The T.30 spec. specifies a number of time-outs. For example, after dialing a number, 00065 a calling fax system should listen for a response for 35 seconds before giving up. 00066 These time-out periods are as follows: 00067 00068 * T1 - 35+-5s: the maximum time for which two fax system will attempt to identify each other 00069 * T2 - 6+-1s: a time-out used to start the sequence for changing transmit parameters 00070 * T3 - 10+-5s: a time-out used in handling operator interrupts 00071 * T5 - 60+-5s: a time-out used in error correction mode 00072 00073 These time-outs are sometimes misinterpreted. In addition, they are routinely 00074 ignored, sometimes with good reason. For example, after placing a call, the 00075 calling fax system is supposed to wait for 35 seconds before giving up. If the 00076 answering unit does not answer on the first ring or if a voice answering machine 00077 is connected to the line, or if there are many delays through the network, 00078 the delay before answer can be much longer than 35 seconds. 00079 00080 Fax units that support error correction mode (ECM) can respond to a post-image 00081 handshake message with a receiver not ready (RNR) message. The calling unit then 00082 queries the receiving fax unit with a receiver ready (RR) message. If the 00083 answering unit is still busy (printing for example), it will repeat the RNR 00084 message. According to the T.30 standard, this sequence (RR/RNR RR/RNR) can be 00085 repeated for up to the end of T5 (60+-5s). However, many fax systems 00086 ignore the time-out and will continue the sequence indefinitely, unless the user 00087 manually overrides. 00088 00089 All the time-outs are subject to alteration, and sometimes misuse. Good T.30 00090 implementations must do the right thing, and tolerate others doing the wrong thing. 00091 00092 Variations in the inter-carrier gap 00093 00094 T.30 specifies 75+-20ms of silence between signals using different modulation 00095 schemes. Examples are between the end of a DCS signal and the start of a TCF signal, 00096 and between the end of an image and the start of a post-image signal. Many fax systems 00097 violate this requirement, especially for the silent period between DCS and TCF. 00098 This may be stretched to well over 100ms. If this period is too long, it can interfere with 00099 handshake signal error recovery, should a packet be corrupted on the line. Systems 00100 should ensure they stay within the prescribed T.30 limits, and be tolerant of others 00101 being out of spec.. 00102 00103 Other timing variations 00104 00105 Testing is required to determine the ability of a fax system to handle 00106 variations in the duration of pauses between unacknowledged handshake message 00107 repetitions, and also in the pauses between the receipt of a handshake command and 00108 the start of a response to that command. In order to reduce the total 00109 transmission time, many fax systems start sending a response message before the 00110 end of the command has been received. 00111 00112 Other deviations from the T.30 standard 00113 00114 There are many other commonly encountered variations between machines, including: 00115 00116 * frame sequence deviations 00117 * preamble and flag sequence variations 00118 * improper EOM usage 00119 * unusual data rate fallback sequences 00120 * common training pattern detection algorithms 00121 * image transmission deviations 00122 * use of the talker echo protect tone 00123 * image padding and short lines 00124 * RTP/RTN handshake message usage 00125 * long duration lines 00126 * nonstandard disconnect sequences 00127 * DCN usage 00128 */ 00129 00130 #define T30_MAX_DIS_DTC_DCS_LEN 22 00131 #define T30_MAX_IDENT_LEN 20 00132 #define T30_MAX_LOCAL_NSF_LEN 100 00133 #define T30_MAX_PAGE_HEADER_INFO 50 00134 00135 typedef struct t30_state_s t30_state_t; 00136 00137 /*! 00138 T.30 phase B callback handler. 00139 \brief T.30 phase B callback handler. 00140 \param s The T.30 context. 00141 \param user_data An opaque pointer. 00142 \param result The phase B event code. 00143 */ 00144 typedef void (t30_phase_b_handler_t)(t30_state_t *s, void *user_data, int result); 00145 00146 /*! 00147 T.30 phase D callback handler. 00148 \brief T.30 phase D callback handler. 00149 \param s The T.30 context. 00150 \param user_data An opaque pointer. 00151 \param result The phase D event code. 00152 */ 00153 typedef void (t30_phase_d_handler_t)(t30_state_t *s, void *user_data, int result); 00154 00155 /*! 00156 T.30 phase E callback handler. 00157 \brief T.30 phase E callback handler. 00158 \param s The T.30 context. 00159 \param user_data An opaque pointer. 00160 \param completion_code The phase E completion code. 00161 */ 00162 typedef void (t30_phase_e_handler_t)(t30_state_t *s, void *user_data, int completion_code); 00163 00164 /*! 00165 T.30 document handler. 00166 \brief T.30 document handler. 00167 \param s The T.30 context. 00168 \param user_data An opaque pointer. 00169 \param result The document event code. 00170 */ 00171 typedef int (t30_document_handler_t)(t30_state_t *s, void *user_data, int status); 00172 00173 /*! 00174 T.30 set a receive or transmit type handler. 00175 \brief T.30 set a receive or transmit type handler. 00176 \param user_data An opaque pointer. 00177 \param type The modem, tone or silence to be sent or received. 00178 \param short_train TRUE if the short training sequence should be used (where one exists). 00179 \param use_hdlc FALSE for bit stream, TRUE for HDLC framing. 00180 */ 00181 typedef void (t30_set_handler_t)(void *user_data, int type, int short_train, int use_hdlc); 00182 00183 /*! 00184 T.30 send HDLC handler. 00185 \brief T.30 send HDLC handler. 00186 \param user_data An opaque pointer. 00187 \param msg The HDLC message. 00188 \param len The length of the message. 00189 */ 00190 typedef void (t30_send_hdlc_handler_t)(void *user_data, const uint8_t *msg, int len); 00191 00192 /*! 00193 T.30 protocol completion codes, at phase E. 00194 */ 00195 enum 00196 { 00197 T30_ERR_OK = 0, /*! OK */ 00198 00199 /* Link problems */ 00200 T30_ERR_CEDTONE, /*! The CED tone exceeded 5s */ 00201 T30_ERR_T0_EXPIRED, /*! Timed out waiting for initial communication */ 00202 T30_ERR_T1_EXPIRED, /*! Timed out waiting for the first message */ 00203 T30_ERR_T3_EXPIRED, /*! Timed out waiting for procedural interrupt */ 00204 T30_ERR_HDLC_CARRIER, /*! The HDLC carrier did not stop in a timely manner */ 00205 T30_ERR_CANNOT_TRAIN, /*! Failed to train with any of the compatible modems */ 00206 T30_ERR_OPERINTFAIL, /*! Operator intervention failed */ 00207 T30_ERR_INCOMPATIBLE, /*! Far end is not compatible */ 00208 T30_ERR_RX_INCAPABLE, /*! Far end is not able to receive */ 00209 T30_ERR_TX_INCAPABLE, /*! Far end is not able to transmit */ 00210 T30_ERR_NORESSUPPORT, /*! Far end cannot receive at the resolution of the image */ 00211 T30_ERR_NOSIZESUPPORT, /*! Far end cannot receive at the size of image */ 00212 T30_ERR_UNEXPECTED, /*! Unexpected message received */ 00213 00214 /* TIFF file problems */ 00215 T30_ERR_FILEERROR, /*! TIFF/F file cannot be opened */ 00216 T30_ERR_NOPAGE, /*! TIFF/F page not found */ 00217 T30_ERR_BADTIFF, /*! TIFF/F format is not compatible */ 00218 00219 /* Phase E status values returned to a transmitter */ 00220 T30_ERR_BADDCSTX, /*! Received bad response to DCS or training */ 00221 T30_ERR_BADPGTX, /*! Received a DCN from remote after sending a page */ 00222 T30_ERR_ECMPHDTX, /*! Invalid ECM response received from receiver */ 00223 T30_ERR_T5_EXPIRED, /*! Timed out waiting for receiver ready (ECM mode) */ 00224 T30_ERR_GOTDCNTX, /*! Received a DCN while waiting for a DIS */ 00225 T30_ERR_INVALRSPTX, /*! Invalid response after sending a page */ 00226 T30_ERR_NODISTX, /*! Received other than DIS while waiting for DIS */ 00227 T30_ERR_PHBDEADTX, /*! Received no response to DCS, training or TCF */ 00228 T30_ERR_PHDDEADTX, /*! No response after sending a page */ 00229 00230 /* Phase E status values returned to a receiver */ 00231 T30_ERR_ECMPHDRX, /*! Invalid ECM response received from transmitter */ 00232 T30_ERR_GOTDCSRX, /*! DCS received while waiting for DTC */ 00233 T30_ERR_INVALCMDRX, /*! Unexpected command after page received */ 00234 T30_ERR_NOCARRIERRX, /*! Carrier lost during fax receive */ 00235 T30_ERR_NOEOLRX, /*! Timed out while waiting for EOL (end Of line) */ 00236 T30_ERR_NOFAXRX, /*! Timed out while waiting for first line */ 00237 T30_ERR_T2EXPDCNRX, /*! Timer T2 expired while waiting for DCN */ 00238 T30_ERR_T2EXPDRX, /*! Timer T2 expired while waiting for phase D */ 00239 T30_ERR_T2EXPFAXRX, /*! Timer T2 expired while waiting for fax page */ 00240 T30_ERR_T2EXPMPSRX, /*! Timer T2 expired while waiting for next fax page */ 00241 T30_ERR_T2EXPRRRX, /*! Timer T2 expired while waiting for RR command */ 00242 T30_ERR_T2EXPRX, /*! Timer T2 expired while waiting for NSS, DCS or MCF */ 00243 T30_ERR_DCNWHYRX, /*! Unexpected DCN while waiting for DCS or DIS */ 00244 T30_ERR_DCNDATARX, /*! Unexpected DCN while waiting for image data */ 00245 T30_ERR_DCNFAXRX, /*! Unexpected DCN while waiting for EOM, EOP or MPS */ 00246 T30_ERR_DCNPHDRX, /*! Unexpected DCN after EOM or MPS sequence */ 00247 T30_ERR_DCNRRDRX, /*! Unexpected DCN after RR/RNR sequence */ 00248 T30_ERR_DCNNORTNRX, /*! Unexpected DCN after requested retransmission */ 00249 00250 T30_ERR_BADPAGE, /*! TIFF/F page number tag missing */ 00251 T30_ERR_BADTAG, /*! Incorrect values for TIFF/F tags */ 00252 T30_ERR_BADTIFFHDR, /*! Bad TIFF/F header - incorrect values in fields */ 00253 T30_ERR_NODATA, /*! Data requested is not available (NSF, DIS, DCS) */ 00254 T30_ERR_NOMEM, /*! Cannot allocate memory for more pages */ 00255 T30_ERR_NOPOLL, /*! Poll not accepted */ 00256 T30_ERR_RETRYDCN, /*! Disconnected after permitted retries */ 00257 T30_ERR_CALLDROPPED /*! The call dropped prematurely */ 00258 }; 00259 00260 /*! 00261 I/O modes for the T.30 protocol. 00262 */ 00263 enum 00264 { 00265 T30_MODEM_NONE = 0, 00266 T30_MODEM_PAUSE, 00267 T30_MODEM_CED, 00268 T30_MODEM_CNG, 00269 T30_MODEM_V21, 00270 T30_MODEM_V27TER_2400, 00271 T30_MODEM_V27TER_4800, 00272 T30_MODEM_V29_7200, 00273 T30_MODEM_V29_9600, 00274 T30_MODEM_V17_7200, 00275 T30_MODEM_V17_9600, 00276 T30_MODEM_V17_12000, 00277 T30_MODEM_V17_14400, 00278 T30_MODEM_DONE 00279 }; 00280 00281 enum 00282 { 00283 T30_FRONT_END_SEND_STEP_COMPLETE = 0, 00284 /*! The current receive has completed. This is only needed to report an 00285 unexpected end of the receive operation, as might happen with T.38 00286 dying. */ 00287 T30_FRONT_END_RECEIVE_COMPLETE, 00288 T30_FRONT_END_SIGNAL_PRESENT, 00289 T30_FRONT_END_SIGNAL_ABSENT 00290 }; 00291 00292 enum 00293 { 00294 T30_SUPPORT_V27TER = 0x01, 00295 T30_SUPPORT_V29 = 0x02, 00296 T30_SUPPORT_V17 = 0x04, 00297 T30_SUPPORT_V34 = 0x08, 00298 T30_SUPPORT_IAF = 0x10, 00299 }; 00300 00301 enum 00302 { 00303 T30_SUPPORT_NO_COMPRESSION = 0x01, 00304 T30_SUPPORT_T4_1D_COMPRESSION = 0x02, 00305 T30_SUPPORT_T4_2D_COMPRESSION = 0x04, 00306 T30_SUPPORT_T6_COMPRESSION = 0x08, 00307 T30_SUPPORT_T85_COMPRESSION = 0x10, /* Monochrome JBIG */ 00308 T30_SUPPORT_T43_COMPRESSION = 0x20, /* Colour JBIG */ 00309 T30_SUPPORT_T45_COMPRESSION = 0x40 /* Run length colour compression */ 00310 }; 00311 00312 enum 00313 { 00314 T30_SUPPORT_STANDARD_RESOLUTION = 0x01, 00315 T30_SUPPORT_FINE_RESOLUTION = 0x02, 00316 T30_SUPPORT_SUPERFINE_RESOLUTION = 0x04, 00317 00318 T30_SUPPORT_R4_RESOLUTION = 0x10000, 00319 T30_SUPPORT_R8_RESOLUTION = 0x20000, 00320 T30_SUPPORT_R16_RESOLUTION = 0x40000, 00321 00322 T30_SUPPORT_300_300_RESOLUTION = 0x100000, 00323 T30_SUPPORT_400_400_RESOLUTION = 0x200000, 00324 T30_SUPPORT_600_600_RESOLUTION = 0x400000, 00325 T30_SUPPORT_1200_1200_RESOLUTION = 0x800000, 00326 T30_SUPPORT_300_600_RESOLUTION = 0x1000000, 00327 T30_SUPPORT_400_800_RESOLUTION = 0x2000000, 00328 T30_SUPPORT_600_1200_RESOLUTION = 0x4000000 00329 }; 00330 00331 enum 00332 { 00333 T30_SUPPORT_215MM_WIDTH = 0x01, 00334 T30_SUPPORT_255MM_WIDTH = 0x02, 00335 T30_SUPPORT_303MM_WIDTH = 0x04, 00336 00337 T30_SUPPORT_UNLIMITED_LENGTH = 0x10000, 00338 T30_SUPPORT_A4_LENGTH = 0x20000, 00339 T30_SUPPORT_B4_LENGTH = 0x40000, 00340 T30_SUPPORT_US_LETTER_LENGTH = 0x80000, 00341 T30_SUPPORT_US_LEGAL_LENGTH = 0x100000 00342 }; 00343 00344 enum 00345 { 00346 T30_SUPPORT_SEP = 0x01, 00347 T30_SUPPORT_PSA = 0x02 00348 }; 00349 00350 enum 00351 { 00352 T30_IAF_MODE_T37 = 0x01, 00353 T30_IAF_MODE_T38 = 0x02, 00354 T30_IAF_MODE_FLOW_CONTROL = 0x04, 00355 /*! Continuous flow mode means data is sent as fast as possible, usually across 00356 the Internet, where speed is not constrained by a PSTN modem. */ 00357 T30_IAF_MODE_CONTINUOUS_FLOW = 0x08, 00358 /*! No TCF means TCF is not exchanged. The end points must sort out usable speed 00359 issues locally. */ 00360 T30_IAF_MODE_NO_TCF = 0x10, 00361 /*! No fill bits means do not insert fill bits, even if the T.30 messages request 00362 them. */ 00363 T30_IAF_MODE_NO_FILL_BITS = 0x20, 00364 /*! No indicators means do not send indicator messages when using T.38. */ 00365 T30_IAF_MODE_NO_INDICATORS = 0x40 00366 }; 00367 00368 /*! 00369 T.30 FAX channel descriptor. This defines the state of a single working 00370 instance of a T.30 FAX channel. 00371 */ 00372 struct t30_state_s 00373 { 00374 /* This must be kept the first thing in the structure, so it can be pointed 00375 to reliably as the structures change over time. */ 00376 /*! \brief T.4 context for reading or writing image data. */ 00377 t4_state_t t4; 00378 00379 /*! \brief TRUE if behaving as the calling party */ 00380 int calling_party; 00381 00382 /*! \brief The received DCS, formatted as an ASCII string, for inclusion 00383 in the TIFF file. */ 00384 char rx_dcs_string[T30_MAX_DIS_DTC_DCS_LEN*3 + 1]; 00385 /*! \brief The local identifier string. */ 00386 char local_ident[T30_MAX_IDENT_LEN + 1]; 00387 /*! \brief The identifier string supplied by the remote FAX machine. */ 00388 char far_ident[T30_MAX_IDENT_LEN + 1]; 00389 /*! \brief The sub-address string to be sent to the remote FAX machine. */ 00390 char local_sub_address[T30_MAX_IDENT_LEN + 1]; 00391 /*! \brief The sub-address string supplied by the remote FAX machine. */ 00392 char far_sub_address[T30_MAX_IDENT_LEN + 1]; 00393 /*! \brief The selective polling sub-address supplied by the remote FAX machine. */ 00394 char sep_address[T30_MAX_IDENT_LEN + 1]; 00395 /*! \brief The polled sub-address supplied by the remote FAX machine. */ 00396 char psa_address[T30_MAX_IDENT_LEN + 1]; 00397 /*! \brief A password to be associated with the T.30 context. */ 00398 char local_password[T30_MAX_IDENT_LEN + 1]; 00399 /*! \brief A password expected from the far end. */ 00400 char far_password[T30_MAX_IDENT_LEN + 1]; 00401 /*! \brief The text which will be used in FAX page header. No text results 00402 in no header line. */ 00403 char header_info[T30_MAX_PAGE_HEADER_INFO + 1]; 00404 /*! \brief The country of origin of the remote machine, if known, else NULL. */ 00405 const char *country; 00406 /*! \brief The vendor of the remote machine, if known, else NULL. */ 00407 const char *vendor; 00408 /*! \brief The model of the remote machine, if known, else NULL. */ 00409 const char *model; 00410 /*! \brief An NSF frame to be sent to the far end. */ 00411 uint8_t local_nsf[T30_MAX_LOCAL_NSF_LEN]; 00412 /*! \brief The length of the NSF frame to be sent to the far end. */ 00413 int local_nsf_len; 00414 00415 /*! \brief A pointer to a callback routine to be called when phase B events 00416 occur. */ 00417 t30_phase_b_handler_t *phase_b_handler; 00418 /*! \brief An opaque pointer supplied in event B callbacks. */ 00419 void *phase_b_user_data; 00420 /*! \brief A pointer to a callback routine to be called when phase D events 00421 occur. */ 00422 t30_phase_d_handler_t *phase_d_handler; 00423 /*! \brief An opaque pointer supplied in event D callbacks. */ 00424 void *phase_d_user_data; 00425 /*! \brief A pointer to a callback routine to be called when phase E events 00426 occur. */ 00427 t30_phase_e_handler_t *phase_e_handler; 00428 /*! \brief An opaque pointer supplied in event E callbacks. */ 00429 void *phase_e_user_data; 00430 00431 /*! \brief A pointer to a callback routine to be called when document events 00432 (e.g. end of transmitted document) occur. */ 00433 t30_document_handler_t *document_handler; 00434 /*! \brief An opaque pointer supplied in document callbacks. */ 00435 void *document_user_data; 00436 00437 /*! \brief The handler for changes to the receive mode */ 00438 t30_set_handler_t *set_rx_type_handler; 00439 /*! \brief An opaque pointer passed to the handler for changes to the receive mode */ 00440 void *set_rx_type_user_data; 00441 /*! \brief The handler for changes to the transmit mode */ 00442 t30_set_handler_t *set_tx_type_handler; 00443 /*! \brief An opaque pointer passed to the handler for changes to the transmit mode */ 00444 void *set_tx_type_user_data; 00445 00446 /*! \brief The transmitted HDLC frame handler. */ 00447 t30_send_hdlc_handler_t *send_hdlc_handler; 00448 /*! \brief An opaque pointer passed to the transmitted HDLC frame handler. */ 00449 void *send_hdlc_user_data; 00450 00451 /*! \brief The DIS code for the minimum scan row time we require. This is usually 0ms, 00452 but if we are trying to simulate another type of FAX machine, we may need a non-zero 00453 value here. */ 00454 uint8_t local_min_scan_time_code; 00455 00456 /*! \brief The current T.30 phase. */ 00457 int phase; 00458 /*! \brief The T.30 phase to change to when the current phase ends. */ 00459 int next_phase; 00460 /*! \brief The current state of the T.30 state machine. */ 00461 int state; 00462 /*! \brief The step in sending a sequence of HDLC frames. */ 00463 int step; 00464 00465 /*! \brief The preparation buffer for the DCS message to be transmitted. */ 00466 uint8_t dcs_frame[T30_MAX_DIS_DTC_DCS_LEN]; 00467 /*! \brief The length of the DCS message to be transmitted. */ 00468 int dcs_len; 00469 /*! \brief The preparation buffer for DIS or DTC message to be transmitted. */ 00470 uint8_t local_dis_dtc_frame[T30_MAX_DIS_DTC_DCS_LEN]; 00471 /*! \brief The length of the DIS or DTC message to be transmitted. */ 00472 int local_dis_dtc_len; 00473 /*! \brief The last DIS or DTC message received form the far end. */ 00474 uint8_t far_dis_dtc_frame[T30_MAX_DIS_DTC_DCS_LEN]; 00475 /*! \brief The length of the last DIS or DTC message received form the far end. */ 00476 int far_dis_dtc_len; 00477 /*! \brief TRUE if a valid DIS has been received from the far end. */ 00478 int dis_received; 00479 00480 /*! \brief A flag to indicate a message is in progress. */ 00481 int in_message; 00482 00483 /*! \brief TRUE if the short training sequence should be used. */ 00484 int short_train; 00485 00486 /*! \brief A count of the number of bits in the trainability test. */ 00487 int training_test_bits; 00488 /*! \brief The current count of consecutive zero bits, during the trainability test. */ 00489 int training_current_zeros; 00490 /*! \brief The maximum consecutive zero bits seen to date, during the trainability test. */ 00491 int training_most_zeros; 00492 00493 /*! \brief The current fallback step for the fast message transfer modem. */ 00494 int current_fallback; 00495 /*! \brief The subset of supported modems allowed at the current time, allowing for negotiation. */ 00496 int current_permitted_modems; 00497 /*! \brief TRUE if a carrier is present. Otherwise FALSE. */ 00498 int rx_signal_present; 00499 /*! \brief TRUE if a modem has trained correctly. */ 00500 int rx_trained; 00501 int current_rx_type; 00502 int current_tx_type; 00503 00504 /*! \brief T0 is the answer timeout when calling another FAX machine. 00505 Placing calls is handled outside the FAX processing, but this timeout keeps 00506 running until V.21 modulation is sent or received. 00507 T1 is the remote terminal identification timeout (in audio samples). */ 00508 int timer_t0_t1; 00509 /*! \brief T2 is the HDLC command timeout. 00510 T4 is the HDLC response timeout (in audio samples). */ 00511 int timer_t2_t4; 00512 /*! \brief TRUE if the T2/T4 timer is actually timing T4 */ 00513 int timer_is_t4; 00514 /*! \brief Procedural interrupt timeout (in audio samples). */ 00515 int timer_t3; 00516 /*! \brief This is only used in error correcting mode. */ 00517 int timer_t5; 00518 /*! \brief This is only used in full duplex (e.g. ISDN) modes. */ 00519 int timer_t6; 00520 /*! \brief This is only used in full duplex (e.g. ISDN) modes. */ 00521 int timer_t7; 00522 /*! \brief This is only used in full duplex (e.g. ISDN) modes. */ 00523 int timer_t8; 00524 00525 /*! \brief TRUE once the far end FAX entity has been detected. */ 00526 int far_end_detected; 00527 00528 /*! \brief TRUE if a local T.30 interrupt is pending. */ 00529 int local_interrupt_pending; 00530 /*! \brief The image coding being used on the line. */ 00531 int line_encoding; 00532 /*! \brief The image coding being used for output files. */ 00533 int output_encoding; 00534 /*! \brief The current DCS message minimum scan time code. */ 00535 uint8_t min_scan_time_code; 00536 /*! \brief The X direction resolution of the current image, in pixels per metre. */ 00537 int x_resolution; 00538 /*! \brief The Y direction resolution of the current image, in pixels per metre. */ 00539 int y_resolution; 00540 /*! \brief The width of the current image, in pixels. */ 00541 t4_image_width_t image_width; 00542 /*! \brief Current number of retries of the action in progress. */ 00543 int retries; 00544 /*! \brief TRUE if error correcting mode is used. */ 00545 int error_correcting_mode; 00546 /*! \brief The current count of consecutive T30_PPR messages. */ 00547 int ppr_count; 00548 /*! \brief The current count of consecutive T30_RNR messages. */ 00549 int receiver_not_ready_count; 00550 /*! \brief The number of octets to be used per ECM frame. */ 00551 int octets_per_ecm_frame; 00552 /*! \brief The ECM partial page buffer. */ 00553 uint8_t ecm_data[256][260]; 00554 /*! \brief The lengths of the frames in the ECM partial page buffer. */ 00555 int16_t ecm_len[256]; 00556 /*! \brief A bit map of the OK ECM frames, constructed as a PPR frame. */ 00557 uint8_t ecm_frame_map[3 + 32]; 00558 00559 /*! \brief The current page number, in ECM mode */ 00560 int ecm_page; 00561 /*! \brief The current block number, in ECM mode */ 00562 int ecm_block; 00563 /*! \brief The number of frames in the current block number, in ECM mode */ 00564 int ecm_frames; 00565 /*! \brief The number of frames sent in the current burst of image transmission, in ECM mode */ 00566 int ecm_frames_this_tx_burst; 00567 /*! \brief The current ECM frame, during ECM transmission. */ 00568 int ecm_current_tx_frame; 00569 /*! \brief TRUE if we are at the end of an ECM page to se sent - i.e. there are no more 00570 partial pages still to come. */ 00571 int ecm_at_page_end; 00572 int next_tx_step; 00573 int next_rx_step; 00574 /*! \brief Image file name for image reception. */ 00575 char rx_file[256]; 00576 /*! \brief The last page we are prepared accept for a received image file. -1 means no restriction. */ 00577 int rx_stop_page; 00578 /*! \brief Image file name to be sent. */ 00579 char tx_file[256]; 00580 /*! \brief The first page to be sent from the image file. -1 means no restriction. */ 00581 int tx_start_page; 00582 /*! \brief The last page to be sent from the image file. -1 means no restriction. */ 00583 int tx_stop_page; 00584 int current_status; 00585 /*! \brief Internet Aware FAX mode bit mask. */ 00586 int iaf; 00587 /*! \brief A bit mask of the currently supported modem types. */ 00588 int supported_modems; 00589 /*! \brief A bit mask of the currently supported image compression modes. */ 00590 int supported_compressions; 00591 /*! \brief A bit mask of the currently supported image resolutions. */ 00592 int supported_resolutions; 00593 /*! \brief A bit mask of the currently supported image sizes. */ 00594 int supported_image_sizes; 00595 /*! \brief A bit mask of the currently supported polling features. */ 00596 int supported_polling_features; 00597 /*! \brief TRUE is T30_FNV message handling is enabled. */ 00598 int support_fnv; 00599 /*! \brief TRUE is T30_CRP message handling is enabled. */ 00600 int crp_enabled; 00601 /*! \brief TRUE is ECM mode handling is enabled. */ 00602 int ecm_allowed; 00603 00604 /*! \brief the FCF2 field of the last PPS message we received. */ 00605 int last_pps_fcf2; 00606 /*! \brief The number of the first ECM frame which we do not currently received correctly. For 00607 a partial page received correctly, this will be one greater than the number of frames it 00608 contains. */ 00609 int ecm_first_bad_frame; 00610 /*! \brief A count of successfully received ECM frames, to assess progress as a basis for 00611 deciding whether to continue error correction when PPRs keep repeating. */ 00612 int ecm_progress; 00613 00614 /*! \brief A password received from the far end. */ 00615 char received_password[T30_MAX_IDENT_LEN + 1]; 00616 /*! \brief TRUE if the far end requires that we send a password. */ 00617 int password_required; 00618 00619 /*! \brief Error and flow logging control */ 00620 logging_state_t logging; 00621 }; 00622 00623 typedef struct 00624 { 00625 /*! \brief The current bit rate for image transfer. */ 00626 int bit_rate; 00627 /*! \brief TRUE if error correcting mode is used. */ 00628 int error_correcting_mode; 00629 /*! \brief The number of pages transferred so far. */ 00630 int pages_transferred; 00631 /*! \brief The number of pages in the file (<0 if not known). */ 00632 int pages_in_file; 00633 /*! \brief The number of horizontal pixels in the most recent page. */ 00634 int width; 00635 /*! \brief The number of vertical pixels in the most recent page. */ 00636 int length; 00637 /*! \brief The number of bad pixel rows in the most recent page. */ 00638 int bad_rows; 00639 /*! \brief The largest number of bad pixel rows in a block in the most recent page. */ 00640 int longest_bad_row_run; 00641 /*! \brief The horizontal column-to-column resolution of the page in pixels per metre */ 00642 int x_resolution; 00643 /*! \brief The vertical row-to-row resolution of the page in pixels per metre */ 00644 int y_resolution; 00645 /*! \brief The type of compression used between the FAX machines */ 00646 int encoding; 00647 /*! \brief The size of the image, in bytes */ 00648 int image_size; 00649 /*! \brief Current status */ 00650 int current_status; 00651 } t30_stats_t; 00652 00653 #if defined(__cplusplus) 00654 extern "C" 00655 { 00656 #endif 00657 00658 /*! Initialise a T.30 context. 00659 \brief Initialise a T.30 context. 00660 \param s The T.30 context. 00661 \param calling_party TRUE if the context is for a calling party. FALSE if the 00662 context is for an answering party. 00663 \param set_rx_type_handler 00664 \param set_rx_type_user_data 00665 \param set_tx_type_handler 00666 \param set_tx_type_user_data 00667 \param send_hdlc_handler 00668 \param send_hdlc_user_data 00669 \return A pointer to the context, or NULL if there was a problem. */ 00670 t30_state_t *t30_init(t30_state_t *s, 00671 int calling_party, 00672 t30_set_handler_t *set_rx_type_handler, 00673 void *set_rx_type_user_data, 00674 t30_set_handler_t *set_tx_type_handler, 00675 void *set_tx_type_user_data, 00676 t30_send_hdlc_handler_t *send_hdlc_handler, 00677 void *send_hdlc_user_data); 00678 00679 /*! Release a T.30 context. 00680 \brief Release a T.30 context. 00681 \param s The T.30 context. 00682 \return 0 for OK, else -1. */ 00683 int t30_release(t30_state_t *s); 00684 00685 /*! Free a T.30 context. 00686 \brief Free a T.30 context. 00687 \param s The T.30 context. 00688 \return 0 for OK, else -1. */ 00689 int t30_free(t30_state_t *s); 00690 00691 /*! Restart a T.30 context. 00692 \brief Restart a T.30 context. 00693 \param s The T.30 context. 00694 \return 0 for OK, else -1. */ 00695 int t30_restart(t30_state_t *s); 00696 00697 /*! Cleanup a T.30 context if the call terminates. 00698 \brief Cleanup a T.30 context if the call terminates. 00699 \param s The T.30 context. */ 00700 void t30_terminate(t30_state_t *s); 00701 00702 /*! Return a text name for a T.30 frame type. 00703 \brief Return a text name for a T.30 frame type. 00704 \param x The frametype octet. 00705 \return A pointer to the text name for the frame type. If the frame type is 00706 not value, the string "???" is returned. */ 00707 const char *t30_frametype(uint8_t x); 00708 00709 /*! Decode a DIS, DTC or DCS frame, and log the contents. 00710 \brief Decode a DIS, DTC or DCS frame, and log the contents. 00711 \param s The T.30 context. 00712 \param dis A pointer to the frame to be decoded. 00713 \param len The length of the frame. */ 00714 void t30_decode_dis_dtc_dcs(t30_state_t *s, const uint8_t *dis, int len); 00715 00716 /*! Convert a phase E completion code to a short text description. 00717 \brief Convert a phase E completion code to a short text description. 00718 \param result The result code. 00719 \return A pointer to the description. */ 00720 const char *t30_completion_code_to_str(int result); 00721 00722 /*! Set Internet aware FAX (IAF) mode. 00723 \brief Set Internet aware FAX (IAF) mode. 00724 \param s The T.30 context. 00725 \param iaf TRUE for IAF, or FALSE for non-IAF. */ 00726 void t30_set_iaf_mode(t30_state_t *s, int iaf); 00727 00728 /*! Set the header information associated with a T.30 context. 00729 \brief Set the header information associated with a T.30 context. 00730 \param s The T.30 context. 00731 \param info A pointer to the information string. 00732 \return 0 for OK, else -1. */ 00733 int t30_set_header_info(t30_state_t *s, const char *info); 00734 00735 /*! Set the sub-address associated with a T.30 context. 00736 \brief Set the sub-address associated with a T.30 context. 00737 \param s The T.30 context. 00738 \param sub_address A pointer to the sub-address. 00739 \return 0 for OK, else -1. */ 00740 int t30_set_local_sub_address(t30_state_t *s, const char *sub_address); 00741 00742 /*! Set the local password (i.e. the one we expect to be given by the far 00743 end) associated with a T.30 context. 00744 \brief Set the local password associated with a T.30 context. 00745 \param s The T.30 context. 00746 \param password A pointer to the password. 00747 \return 0 for OK, else -1. */ 00748 int t30_set_local_password(t30_state_t *s, const char *password); 00749 00750 /*! Set the far password (i.e. the one we will send to the far 00751 end) associated with a T.30 context. 00752 \brief Set the far password associated with a T.30 context. 00753 \param s The T.30 context. 00754 \param password A pointer to the password. 00755 \return 0 for OK, else -1. */ 00756 int t30_set_far_password(t30_state_t *s, const char *password); 00757 00758 /*! Set the local identifier associated with a T.30 context. 00759 \brief Set the local identifier associated with a T.30 context. 00760 \param s The T.30 context. 00761 \param id A pointer to the identifier. 00762 \return 0 for OK, else -1. */ 00763 int t30_set_local_ident(t30_state_t *s, const char *id); 00764 00765 /*! Set an NSF frame to be associated with a T.30 context. 00766 \brief Set an NSF frame to be associated with a T.30 context. 00767 \param s The T.30 context. 00768 \param nsf A pointer to the frame. 00769 \param len The length of the frame. 00770 \return 0 for OK, else -1. */ 00771 int t30_set_local_nsf(t30_state_t *s, const uint8_t *nsf, int len); 00772 00773 /*! Get the header information associated with a T.30 context. 00774 \brief Get the header information associated with a T.30 context. 00775 \param s The T.30 context. 00776 \param info A pointer to a buffer for the header information. The buffer 00777 should be at least 51 bytes long. 00778 \return the length of the string. */ 00779 size_t t30_get_header_info(t30_state_t *s, char *info); 00780 00781 /*! Get the local sub-address associated with a T.30 context. 00782 \brief Get the local sub-address associated with a T.30 context. 00783 \param s The T.30 context. 00784 \param sub_address A pointer to a buffer for the sub-address. The buffer 00785 should be at least 21 bytes long. 00786 \return the length of the string. */ 00787 size_t t30_get_local_sub_address(t30_state_t *s, char *sub_address); 00788 00789 /*! Get the far sub-address associated with a T.30 context. 00790 \brief Get the far sub-address associated with a T.30 context. 00791 \param s The T.30 context. 00792 \param sub_address A pointer to a buffer for the sub-address. The buffer 00793 should be at least 21 bytes long. 00794 \return the length of the string. */ 00795 size_t t30_get_far_sub_address(t30_state_t *s, char *sub_address); 00796 00797 /*! Get the local password associated with a T.30 context. 00798 \brief Get the local password associated with a T.30 context. 00799 \param s The T.30 context. 00800 \param password A pointer to a buffer for the password. The buffer 00801 should be at least 21 bytes long. 00802 \return the length of the string. */ 00803 size_t t30_get_local_password(t30_state_t *s, char *password); 00804 00805 /*! Get the far password associated with a T.30 context. 00806 \brief Get the far password associated with a T.30 context. 00807 \param s The T.30 context. 00808 \param password A pointer to a buffer for the password. The buffer 00809 should be at least 21 bytes long. 00810 \return the length of the string. */ 00811 size_t t30_get_far_password(t30_state_t *s, char *password); 00812 00813 /*! Get the received password associated with a T.30 context. 00814 \brief Get the received password associated with a T.30 context. 00815 \param s The T.30 context. 00816 \param password A pointer to a buffer for the password. The buffer 00817 should be at least 21 bytes long. 00818 \return the length of the string. */ 00819 size_t t30_get_received_password(t30_state_t *s, char *password); 00820 00821 /*! Get the local FAX machine identifier associated with a T.30 context. 00822 \brief Get the local identifier associated with a T.30 context. 00823 \param s The T.30 context. 00824 \param id A pointer to a buffer for the identifier. The buffer should 00825 be at least 21 bytes long. 00826 \return the length of the string. */ 00827 size_t t30_get_local_ident(t30_state_t *s, char *id); 00828 00829 /*! Get the remote FAX machine identifier associated with a T.30 context. 00830 \brief Get the remote identifier associated with a T.30 context. 00831 \param s The T.30 context. 00832 \param id A pointer to a buffer for the identifier. The buffer should 00833 be at least 21 bytes long. 00834 \return the length of the string. */ 00835 size_t t30_get_far_ident(t30_state_t *s, char *id); 00836 00837 /*! Get the country of origin of the remote FAX machine associated with a T.30 context. 00838 \brief Get the country of origin of the remote FAX machine associated with a T.30 context. 00839 \param s The T.30 context. 00840 \return a pointer to the country name, or NULL if the country is not known. */ 00841 const char *t30_get_far_country(t30_state_t *s); 00842 00843 /*! Get the name of the vendor of the remote FAX machine associated with a T.30 context. 00844 \brief Get the name of the vendor of the remote FAX machine associated with a T.30 context. 00845 \param s The T.30 context. 00846 \return a pointer to the vendor name, or NULL if the vendor is not known. */ 00847 const char *t30_get_far_vendor(t30_state_t *s); 00848 00849 /*! Get the name of the model of the remote FAX machine associated with a T.30 context. 00850 \brief Get the name of the model of the remote FAX machine associated with a T.30 context. 00851 \param s The T.30 context. 00852 \return a pointer to the model name, or NULL if the model is not known. */ 00853 const char *t30_get_far_model(t30_state_t *s); 00854 00855 /*! Get the current transfer statistics for the file being sent or received. 00856 \brief Get the current transfer statistics. 00857 \param s The T.30 context. 00858 \param t A pointer to a buffer for the statistics. */ 00859 void t30_get_transfer_statistics(t30_state_t *s, t30_stats_t *t); 00860 00861 /*! Set a callback function for T.30 phase B handling. 00862 \brief Set a callback function for T.30 phase B handling. 00863 \param s The T.30 context. 00864 \param handler The callback function 00865 \param user_data An opaque pointer passed to the callback function. */ 00866 void t30_set_phase_b_handler(t30_state_t *s, t30_phase_b_handler_t *handler, void *user_data); 00867 00868 /*! Set a callback function for T.30 phase D handling. 00869 \brief Set a callback function for T.30 phase D handling. 00870 \param s The T.30 context. 00871 \param handler The callback function 00872 \param user_data An opaque pointer passed to the callback function. */ 00873 void t30_set_phase_d_handler(t30_state_t *s, t30_phase_d_handler_t *handler, void *user_data); 00874 00875 /*! Set a callback function for T.30 phase E handling. 00876 \brief Set a callback function for T.30 phase E handling. 00877 \param s The T.30 context. 00878 \param handler The callback function 00879 \param user_data An opaque pointer passed to the callback function. */ 00880 void t30_set_phase_e_handler(t30_state_t *s, t30_phase_e_handler_t *handler, void *user_data); 00881 00882 /*! Set a callback function for T.30 end of document handling. 00883 \brief Set a callback function for T.30 end of document handling. 00884 \param s The T.30 context. 00885 \param handler The callback function 00886 \param user_data An opaque pointer passed to the callback function. */ 00887 void t30_set_document_handler(t30_state_t *s, t30_document_handler_t *handler, void *user_data); 00888 00889 /*! Specify the file name of the next TIFF file to be received by a T.30 00890 context. 00891 \brief Set next receive file name. 00892 \param s The T.30 context. 00893 \param file The file name 00894 \param stop_page The maximum page to receive. -1 for no restriction. */ 00895 void t30_set_rx_file(t30_state_t *s, const char *file, int stop_page); 00896 00897 /*! Specify the file name of the next TIFF file to be transmitted by a T.30 00898 context. 00899 \brief Set next transmit file name. 00900 \param s The T.30 context. 00901 \param file The file name 00902 \param start_page The first page to send. -1 for no restriction. 00903 \param stop_page The last page to send. -1 for no restriction. */ 00904 void t30_set_tx_file(t30_state_t *s, const char *file, int start_page, int stop_page); 00905 00906 /*! Specify which modem types are supported by a T.30 context. 00907 \brief Specify supported modems. 00908 \param s The T.30 context. 00909 \param supported_modems Bit field list of the supported modems. 00910 \return 0 if OK, else -1. */ 00911 int t30_set_supported_modems(t30_state_t *s, int supported_modems); 00912 00913 /*! Specify a period of responding with receiver not ready. 00914 \brief Specify a period of responding with receiver not ready. 00915 \param s The T.30 context. 00916 \param count The number of times to report receiver not ready. 00917 \return 0 if OK, else -1. */ 00918 int t30_set_receiver_not_ready(t30_state_t *s, int count); 00919 00920 /*! Specify which compression types are supported by a T.30 context. 00921 \brief Specify supported compression types. 00922 \param s The T.30 context. 00923 \param supported_compressions Bit field list of the supported compression types. 00924 \return 0 if OK, else -1. */ 00925 int t30_set_supported_compressions(t30_state_t *s, int supported_compressions); 00926 00927 /*! Specify which resolutions are supported by a T.30 context. 00928 \brief Specify supported resolutions. 00929 \param s The T.30 context. 00930 \param supported_resolutions Bit field list of the supported resolutions. 00931 \return 0 if OK, else -1. */ 00932 int t30_set_supported_resolutions(t30_state_t *s, int supported_resolutions); 00933 00934 /*! Specify which images sizes are supported by a T.30 context. 00935 \brief Specify supported image sizes. 00936 \param s The T.30 context. 00937 \param supported_image_sizes Bit field list of the supported widths and lengths. 00938 \return 0 if OK, else -1. */ 00939 int t30_set_supported_image_sizes(t30_state_t *s, int supported_image_sizes); 00940 00941 /*! Specify if error correction mode (ECM) is allowed by a T.30 context. 00942 \brief Select ECM capability. 00943 \param s The T.30 context. 00944 \param enabled TRUE for ECM capable, FALSE for not ECM capable. 00945 \return 0 if OK, else -1. */ 00946 int t30_set_ecm_capability(t30_state_t *s, int enabled); 00947 00948 /*! Specify the output encoding for TIFF files created during FAX reception. 00949 \brief Specify the output encoding for TIFF files created during FAX reception. 00950 \param s The T.30 context. 00951 \param encoding The coding required. The options are T4_COMPRESSION_ITU_T4_1D, 00952 T4_COMPRESSION_ITU_T4_2D, T4_COMPRESSION_ITU_T6. T6 is usually the 00953 densest option, but support for it is broken in a number of software 00954 packages. 00955 \return 0 if OK, else -1. */ 00956 int t30_set_rx_encoding(t30_state_t *s, int encoding); 00957 00958 /*! Request a local interrupt of FAX exchange. 00959 \brief Request a local interrupt of FAX exchange. 00960 \param s The T.30 context. 00961 \param state TRUE to enable interrupt request, else FALSE. */ 00962 void t30_local_interrupt_request(t30_state_t *s, int state); 00963 00964 /*! Inform the T.30 engine of a status change in the front end (end of tx, rx signal change, etc.). 00965 \brief Inform the T.30 engine of a status change in the front end (end of tx, rx signal change, etc.). 00966 \param user_data The T.30 context. 00967 \param status The type of status change which occured. */ 00968 void t30_front_end_status(void *user_data, int status); 00969 00970 /*! Get a bit of received non-ECM image data. 00971 \brief Get a bit of received non-ECM image data. 00972 \param user_data An opaque pointer, which must point to the T.30 context. 00973 \return The next bit to transmit. */ 00974 int t30_non_ecm_get_bit(void *user_data); 00975 00976 /*! Get a byte of received non-ECM image data. 00977 \brief Get a byte of received non-ECM image data. 00978 \param user_data An opaque pointer, which must point to the T.30 context. 00979 \return The next byte to transmit. */ 00980 int t30_non_ecm_get_byte(void *user_data); 00981 00982 /*! Get a chunk of received non-ECM image data. 00983 \brief Get a bit of received non-ECM image data. 00984 \param user_data An opaque pointer, which must point to the T.30 context. 00985 \param buf The buffer to contain the data. 00986 \param max_len The maximum length of the chunk. 00987 \return The actual length of the chunk. */ 00988 int t30_non_ecm_get_chunk(void *user_data, uint8_t buf[], int max_len); 00989 00990 /*! Process a bit of received non-ECM image data. 00991 \brief Process a bit of received non-ECM image data 00992 \param user_data An opaque pointer, which must point to the T.30 context. 00993 \param bit The received bit. */ 00994 void t30_non_ecm_put_bit(void *user_data, int bit); 00995 00996 /*! Process a byte of received non-ECM image data. 00997 \brief Process a byte of received non-ECM image data 00998 \param user_data An opaque pointer, which must point to the T.30 context. 00999 \param byte The received byte. */ 01000 void t30_non_ecm_put_byte(void *user_data, int byte); 01001 01002 /*! Process a chunk of received non-ECM image data. 01003 \brief Process a chunk of received non-ECM image data 01004 \param user_data An opaque pointer, which must point to the T.30 context. 01005 \param buf The buffer containing the received data. 01006 \param len The length of the data in buf. */ 01007 void t30_non_ecm_put_chunk(void *user_data, const uint8_t buf[], int len); 01008 01009 /*! Process a received HDLC frame. 01010 \brief Process a received HDLC frame. 01011 \param user_data The T.30 context. 01012 \param msg The HDLC message. 01013 \param len The length of the message, in octets. 01014 \param ok TRUE if the frame was received without error. */ 01015 void t30_hdlc_accept(void *user_data, const uint8_t *msg, int len, int ok); 01016 01017 /*! Report the passage of time to the T.30 engine. 01018 \brief Report the passage of time to the T.30 engine. 01019 \param s The T.30 context. 01020 \param samples The time change in 1/8000th second steps. */ 01021 void t30_timer_update(t30_state_t *s, int samples); 01022 01023 #if defined(__cplusplus) 01024 } 01025 #endif 01026 01027 #endif 01028 /*- End of file ------------------------------------------------------------*/