Restore behavior of 'receivefax' to one provided by version 628 of chan_capi.c: Use fax T.30 extended for Diva hardware or if required by 'receivefax' option only. By default allow fine resolution for fax T.30 extended.

This commit is contained in:
MelwareDE 2009-08-05 22:25:53 +00:00
parent 73edae5356
commit c65f9424b7
4 changed files with 240 additions and 18 deletions

5
README
View File

@ -153,7 +153,7 @@ Call Deflection:
Fax receive:
Receives a fax using CAPI.
Example:
exten => s,1,capicommand(receivefax|/tmp/${UNIQUEID}|+49 6137 555123|Asterisk|k)
exten => s,1,capicommand(receivefax|/tmp/${UNIQUEID}|+49 6137 555123|Asterisk|kX)
(more see below)
Fax send:
@ -383,6 +383,9 @@ The parameter <filename> is mandatory and the parameters <stationid>,
By default, if fax reception was not successful, the file is deleted. If you want even
partly received or broken fax files, use 'k' for "keep bad fax" in the <options>:
capicommand(receivefax|/tmp/${UNIQUEID}|+123456789||k)
You can activate extended fax support by 'X' in the <options>:
capicommand(receivefax|/tmp/${UNIQUEID}|+123456789||X)
Please read details on extended fax options in README.Diva.fax.
To enable fax tone detection and redirect to extension 'fax', use config variable
'faxdetect' in capi.conf. This can be limited to the first 'n' seconds of a connection

View File

@ -219,6 +219,8 @@ The reception of the fax message is started using 'receivefax' capi command:
'stationid' - station ID, optional
'headline' - head line, optional
'options' - fax options, optional
'X' - use fax T.30 extended (default)
'x' - do not use fax T.30 extended
'k' - keep fax document in case of errors (by default document is removed
if fax transmission was not completed with success).
'f' - allow Fine resolution (default)

View File

@ -238,6 +238,11 @@ static struct {
NULL,
NULL,
NULL
},
{ 0x04, 0x04, 0x04, /* 4 */
NULL,
NULL,
NULL
}
};
@ -2394,7 +2399,7 @@ pbx_capi_request(const char *type, int format, void *data, int *cause)
}
/*
* fill out fax conf struct
* fill out extended fax conf struct
*
* b3_protocol_options:
* [Bit 0] : Enable high resolution
@ -2426,6 +2431,28 @@ static void setup_b3_fax_config(B3_PROTO_FAXG3 *b3conf, int fax_format, char *st
return;
}
/*
* fill out basic fax conf struct
*/
static void setup_b3_basic_fax_config(B3_PROTO_FAXG3 *b3conf, int fax_format, char *stationid, char *headline)
{
int len1;
int len2;
cc_verbose(3, 1, VERBOSE_PREFIX_3 "Setup fax b3conf fmt=%d, stationid='%s' headline='%s'\n",
fax_format, stationid, headline);
b3conf->resolution = 0;
b3conf->format = (unsigned short)fax_format;
len1 = strlen(stationid);
b3conf->Infos[0] = (unsigned char)len1;
strcpy((char *)&b3conf->Infos[1], stationid);
len2 = strlen(headline);
b3conf->Infos[len1 + 1] = (unsigned char)len2;
strcpy((char *)&b3conf->Infos[len1 + 2], headline);
b3conf->len = (unsigned char)(2 * sizeof(unsigned short) + len1 + len2 + 2);
return;
}
/*
* change b protocol to fax
*/
@ -2438,11 +2465,10 @@ static void capi_change_bchan_fax(struct capi_pvt *i, B3_PROTO_FAXG3 *b3conf)
}
/*
* capicommand 'receivefax'
* capicommand 'receivefax' using B3 fax T.30 extended
*/
static int pbx_capi_receive_fax(struct ast_channel *c, char *data)
static int pbx_capi_receive_extended_fax(struct ast_channel *c, struct capi_pvt *i, char *data)
{
struct capi_pvt *i = get_active_plci(c);
int res = 0;
int keepbadfax = 0;
char *filename, *stationid, *headline, *options;
@ -2451,17 +2477,6 @@ static int pbx_capi_receive_fax(struct ast_channel *c, char *data)
unsigned short b3_protocol_options = 0x0001;
int extended_resolution = 0;
if ((i == NULL) || ((i->channeltype == CAPI_CHANNELTYPE_NULL) && (i->line_plci == NULL))) {
cc_log(LOG_WARNING, CC_MESSAGE_NAME " receivefax requires resource PLCI\n");
return -1;
}
if (!data) { /* no data implies no filename or anything is present */
cc_log(LOG_WARNING, CC_MESSAGE_NAME " receivefax requires a filename\n");
capi_remove_nullif(i);
return -1;
}
filename = strsep(&data, "|");
stationid = strsep(&data, "|");
headline = strsep(&data, "|");
@ -2534,6 +2549,10 @@ static int pbx_capi_receive_fax(struct ast_channel *c, char *data)
b3_protocol_options |= 0x2000;
break;
case 'X':
case 'x':
break;
default:
cc_log(LOG_WARNING, "Unknown option '%c' for receivefax.\n",
*options);
@ -2635,6 +2654,201 @@ static int pbx_capi_receive_fax(struct ast_channel *c, char *data)
return 0;
}
/*
* capicommand 'receivefax' using B3 fax T.30
*/
static int pbx_capi_receive_basic_fax(struct ast_channel *c, struct capi_pvt *i, char *data)
{
int res = 0;
int keepbadfax = 0;
char *filename, *stationid, *headline, *options;
B3_PROTO_FAXG3 b3conf;
char buffer[CAPI_MAX_STRING];
filename = strsep(&data, "|");
stationid = strsep(&data, "|");
headline = strsep(&data, "|");
options = data;
if (!stationid)
stationid = emptyid;
if (!headline)
headline = emptyid;
if (!options)
options = emptyid;
cc_verbose(3, 1, VERBOSE_PREFIX_3 CC_MESSAGE_NAME " receivefax: '%s' '%s' '%s' '%s'\n",
filename, stationid, headline, options);
/* parse the options */
while ((options) && (*options)) {
switch (*options) {
case 'k': /* keepbadfax */
cc_verbose(3, 1,
VERBOSE_PREFIX_3 CC_MESSAGE_NAME " receivefax: if fax is bad, "
"file won't be deleted.\n");
keepbadfax = 1;
break;
case 'f': /* use Fine resolution */
case 'F': /* do not use Fine resolution */
case 'u': /* use Fine resolution */
case 'j': /* enable JPEG encoding */
case 'b': /* enable T.43 encoding */
case 't': /* diasble T.85 encoding */
case 'e': /* disable ECM encoding */
case 'm': /* disable MMR encoding */
case 'd': /* disable MR encoding */
cc_log(LOG_WARNING, "Option '%c' requires B3 fax T.30 extended.\n",
*options);
break;
case 'X':
case 'x':
break;
default:
cc_log(LOG_WARNING, "Unknown option '%c' for receivefax.\n",
*options);
}
options++;
}
capi_wait_for_answered(i);
i->FaxState &= ~CAPI_FAX_STATE_CONN;
if ((i->fFax = fopen(filename, "wb")) == NULL) {
cc_log(LOG_WARNING, "can't create fax output file (%s)\n", strerror(errno));
return -1;
}
i->FaxState |= CAPI_FAX_STATE_ACTIVE;
setup_b3_basic_fax_config(&b3conf, FAX_SFF_FORMAT, stationid, headline);
i->bproto = CC_BPROTO_FAX3_BASIC;
switch (i->state) {
case CAPI_STATE_ALERTING:
case CAPI_STATE_DID:
case CAPI_STATE_INCALL:
capi_send_answer(c, (_cstruct)&b3conf);
break;
case CAPI_STATE_CONNECTED:
capi_change_bchan_fax(i, &b3conf);
break;
default:
i->FaxState &= ~CAPI_FAX_STATE_ACTIVE;
cc_log(LOG_WARNING, CC_MESSAGE_NAME " receive fax in wrong state (%d)\n",
i->state);
return -1;
}
while (capi_tell_fax_finish(i)) {
if (ast_safe_sleep_conditional(c, 1000, capi_tell_fax_finish, i) != 0) {
/* we got a hangup */
cc_verbose(3, 1,
VERBOSE_PREFIX_3 CC_MESSAGE_NAME " receivefax: hangup.\n");
break;
}
}
cc_mutex_lock(&i->lock);
res = (i->FaxState & CAPI_FAX_STATE_ERROR) ? 1 : 0;
i->FaxState &= ~(CAPI_FAX_STATE_ACTIVE | CAPI_FAX_STATE_ERROR);
/* if the file has zero length */
if (ftell(i->fFax) == 0L) {
res = 1;
}
cc_verbose(2, 1, VERBOSE_PREFIX_3 "Closing fax file...\n");
fclose(i->fFax);
i->fFax = NULL;
cc_mutex_unlock(&i->lock);
if (res != 0) {
cc_verbose(2, 0,
VERBOSE_PREFIX_1 CC_MESSAGE_NAME
" receivefax: fax receive failed reason=0x%04x reasonB3=0x%04x\n",
i->reason, i->reasonb3);
if (!keepbadfax) {
cc_verbose(3, 1,
VERBOSE_PREFIX_3 CC_MESSAGE_NAME " receivefax: removing fax file.\n");
unlink(filename);
}
} else {
cc_verbose(2, 0,
VERBOSE_PREFIX_1 CC_MESSAGE_NAME " receivefax: fax receive successful.\n");
}
snprintf(buffer, CAPI_MAX_STRING-1, "%d", res);
pbx_builtin_setvar_helper(c, "FAXSTATUS", buffer);
return 0;
}
/*
* capicommand 'receivefax'
*/
static int pbx_capi_receive_fax(struct ast_channel *c, char *data)
{
struct capi_pvt *i = get_active_plci(c);
int force_extended = 0, force_no_extended = 0;
char *ldata_mem, *ldata;
if ((i == NULL) || ((i->channeltype == CAPI_CHANNELTYPE_NULL) && (i->line_plci == NULL))) {
cc_log(LOG_WARNING, CC_MESSAGE_NAME " receivefax requires resource PLCI\n");
return -1;
}
if (!data || !*data) { /* no data implies no filename or anything is present */
cc_log(LOG_WARNING, CC_MESSAGE_NAME " receivefax requires a filename\n");
capi_remove_nullif(i);
return -1;
}
ldata_mem = ldata = strdup(data);
if (!ldata_mem) {
cc_log(LOG_WARNING, CC_MESSAGE_NAME " out of memory\n");
capi_remove_nullif(i);
return -1;
}
(void)strsep(&ldata, "|");
(void)strsep(&ldata, "|");
(void)strsep(&ldata, "|");
while ((ldata) && (*ldata)) {
switch (*ldata) {
case 'X':
force_extended = 1;
force_no_extended = 0;
break;
case 'x':
force_extended = 0;
force_no_extended = 1;
break;
}
ldata++;
}
free(ldata_mem);
if ((force_extended != 0) && (capi_controllers[i->controller]->fax_t30_extended == 0)) {
force_extended = 0;
cc_log(LOG_WARNING, CC_MESSAGE_NAME " fax T.30 extended not available\n");
}
force_extended |= ((capi_controllers[i->controller]->divaExtendedFeaturesAvailable != 0) && (force_no_extended == 0)); /* Always use fax T.30 extended for Diva */
force_extended |= (i->channeltype == CAPI_CHANNELTYPE_NULL); /* always use fax T.30 extended for clear channel fax */
if (force_extended != 0) {
return (pbx_capi_receive_extended_fax(c, i, data));
} else {
return (pbx_capi_receive_basic_fax(c, i, data));
}
}
static void clear_channel_fax_loop(struct ast_channel *c, struct capi_pvt *i)
{
struct ast_frame *f;
@ -6974,6 +7188,7 @@ static char *show_bproto(int bproto)
case CC_BPROTO_TRANSPARENT:
return "trans";
case CC_BPROTO_FAXG3:
case CC_BPROTO_FAX3_BASIC:
return " fax ";
case CC_BPROTO_RTP:
return " rtp ";
@ -7487,14 +7702,14 @@ static int cc_init_capi(void)
#else
cp->nbchannels = read_capi_word(&profile.nbchannels);
cp->nfreebchannels = read_capi_word(&profile.nbchannels);
cp->fax_t30_extended = ((profile.b3protocols & (1U << 5)) != 0);
if (profile.globaloptions & 0x08) {
#endif
cc_verbose(3, 0, VERBOSE_PREFIX_3 "Contr%d supports DTMF\n",
controller);
cp->dtmf = 1;
}
#if (CAPI_OS_HINT == 1)
if (profile.dwGlobalOptions & 0x01) {
#else

View File

@ -148,6 +148,7 @@ static inline unsigned int read_capi_dword(void *m)
#define CC_BPROTO_FAXG3 1
#define CC_BPROTO_RTP 2
#define CC_BPROTO_VOCODER 3
#define CC_BPROTO_FAX3_BASIC 4
/* FAX Resolutions */
#define FAX_STANDARD_RESOLUTION 0
@ -609,6 +610,7 @@ struct cc_capi_controller {
int divaExtendedFeaturesAvailable;
int ecPath;
int fax_t30_extended;
};