Merge pcadach's new progress code (bug #2822)
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@179 2fbb986a-6c06-0410-b554-c9c1f0a7f128
This commit is contained in:
parent
1630193827
commit
c05e4b45c0
48
libpri.h
48
libpri.h
@ -49,35 +49,48 @@
|
||||
#define PRI_SWITCH_EUROISDN_E1 5 /* Standard EuroISDN (CTR4, ETSI 300-102) */
|
||||
#define PRI_SWITCH_EUROISDN_T1 6 /* T1 EuroISDN variant (ETSI 300-102) */
|
||||
#define PRI_SWITCH_NI1 7 /* National ISDN 1 */
|
||||
#define PRI_SWITCH_GR303_EOC 8 /* GR-303 Embedded Operations Channel */
|
||||
#define PRI_SWITCH_GR303_TMC 9 /* GR-303 Timeslot Management Channel */
|
||||
#define PRI_SWITCH_GR303_EOC 8 /* GR-303 Embedded Operations Channel */
|
||||
#define PRI_SWITCH_GR303_TMC 9 /* GR-303 Timeslot Management Channel */
|
||||
#define PRI_SWITCH_QSIG 10 /* QSIG Switch */
|
||||
/* Switchtypes 10 - 20 are reserved for internal use */
|
||||
|
||||
|
||||
/* PRI D-Channel Events */
|
||||
#define PRI_EVENT_DCHAN_UP 1 /* D-channel is up */
|
||||
#define PRI_EVENT_DCHAN_DOWN 2 /* D-channel is down */
|
||||
#define PRI_EVENT_RESTART 3 /* B-channel is restarted */
|
||||
#define PRI_EVENT_CONFIG_ERR 4 /* Configuration Error Detected */
|
||||
#define PRI_EVENT_RING 5 /* Incoming call */
|
||||
#define PRI_EVENT_HANGUP 6 /* Call got hung up */
|
||||
#define PRI_EVENT_RINGING 7 /* Call is ringing (alerting) */
|
||||
#define PRI_EVENT_ANSWER 8 /* Call has been answered */
|
||||
#define PRI_EVENT_HANGUP_ACK 9 /* Call hangup has been acknowledged */
|
||||
#define PRI_EVENT_DCHAN_UP 1 /* D-channel is up */
|
||||
#define PRI_EVENT_DCHAN_DOWN 2 /* D-channel is down */
|
||||
#define PRI_EVENT_RESTART 3 /* B-channel is restarted */
|
||||
#define PRI_EVENT_CONFIG_ERR 4 /* Configuration Error Detected */
|
||||
#define PRI_EVENT_RING 5 /* Incoming call */
|
||||
#define PRI_EVENT_HANGUP 6 /* Call got hung up */
|
||||
#define PRI_EVENT_RINGING 7 /* Call is ringing (alerting) */
|
||||
#define PRI_EVENT_ANSWER 8 /* Call has been answered */
|
||||
#define PRI_EVENT_HANGUP_ACK 9 /* Call hangup has been acknowledged */
|
||||
#define PRI_EVENT_RESTART_ACK 10 /* Restart complete on a given channel */
|
||||
#define PRI_EVENT_FACNAME 11 /* Caller*ID Name received on Facility */
|
||||
#define PRI_EVENT_FACNAME 11 /* Caller*ID Name received on Facility */
|
||||
#define PRI_EVENT_INFO_RECEIVED 12 /* Additional info (keypad) received */
|
||||
#define PRI_EVENT_PROCEEDING 13 /* When we get CALL_PROCEEDING or PROGRESS */
|
||||
#define PRI_EVENT_SETUP_ACK 14 /* When we get SETUP_ACKNOWLEDGE */
|
||||
#define PRI_EVENT_SETUP_ACK 14 /* When we get SETUP_ACKNOWLEDGE */
|
||||
#define PRI_EVENT_HANGUP_REQ 15 /* Requesting the higher layer to hangup */
|
||||
#define PRI_EVENT_NOTIFY 16 /* Notification received */
|
||||
#define PRI_EVENT_PROGRESS 17 /* When we get CALL_PROCEEDING or PROGRESS */
|
||||
#define PRI_EVENT_NOTIFY 16 /* Notification received */
|
||||
#define PRI_EVENT_PROGRESS 17 /* When we get CALL_PROCEEDING or PROGRESS */
|
||||
|
||||
/* Simple states */
|
||||
#define PRI_STATE_DOWN 0
|
||||
#define PRI_STATE_UP 1
|
||||
|
||||
#define PRI_PROGRESS_MASK
|
||||
|
||||
/* Progress indicator values */
|
||||
#define PRI_PROG_CALL_NOT_E2E_ISDN (1 << 0)
|
||||
#define PRI_PROG_CALLED_NOT_ISDN (1 << 1)
|
||||
#define PRI_PROG_CALLER_NOT_ISDN (1 << 2)
|
||||
#define PRI_PROG_INBAND_AVAILABLE (1 << 3)
|
||||
#define PRI_PROG_DELAY_AT_INTERF (1 << 4)
|
||||
#define PRI_PROG_INTERWORKING_WITH_PUBLIC (1 << 5)
|
||||
#define PRI_PROG_INTERWORKING_NO_RELEASE (1 << 6)
|
||||
#define PRI_PROG_INTERWORKING_NO_RELEASE_PRE_ANSWER (1 << 7)
|
||||
#define PRI_PROG_INTERWORKING_NO_RELEASE_POST_ANSWER (1 << 8)
|
||||
|
||||
/* Numbering plan identifier */
|
||||
#define PRI_NPI_UNKNOWN 0x0
|
||||
#define PRI_NPI_E163_E164 0x1
|
||||
@ -254,6 +267,7 @@ typedef struct pri_event_ringing {
|
||||
int channel;
|
||||
int cref;
|
||||
int progress;
|
||||
int progressmask;
|
||||
q931_call *call;
|
||||
} pri_event_ringing;
|
||||
|
||||
@ -262,6 +276,7 @@ typedef struct pri_event_answer {
|
||||
int channel;
|
||||
int cref;
|
||||
int progress;
|
||||
int progressmask;
|
||||
q931_call *call;
|
||||
} pri_event_answer;
|
||||
|
||||
@ -294,6 +309,8 @@ typedef struct pri_event_ring {
|
||||
int complete; /* Have we seen "Complete" i.e. no more number? */
|
||||
q931_call *call; /* Opaque call pointer */
|
||||
char callingsubaddr[256]; /* Calling parties subaddress */
|
||||
int progress;
|
||||
int progressmask;
|
||||
} pri_event_ring;
|
||||
|
||||
typedef struct pri_event_hangup {
|
||||
@ -314,6 +331,7 @@ typedef struct pri_event_proceeding {
|
||||
int channel;
|
||||
int cref;
|
||||
int progress;
|
||||
int progressmask;
|
||||
q931_call *call;
|
||||
} pri_event_proceeding;
|
||||
|
||||
|
@ -132,7 +132,7 @@ struct pri_sr {
|
||||
|
||||
struct q931_call {
|
||||
struct pri *pri; /* PRI */
|
||||
int cr; /* Call Reference */
|
||||
int cr; /* Call Reference */
|
||||
int forceinvert; /* Force inversion of call number even if 0 */
|
||||
q931_call *next;
|
||||
/* Slotmap specified (bitmap of channels 31/24-1) (Channel Identifier IE) (-1 means not specified) */
|
||||
@ -146,10 +146,10 @@ struct q931_call {
|
||||
|
||||
int alive; /* Whether or not the call is alive */
|
||||
int acked; /* Whether setup has been acked or not */
|
||||
int sendhangupack; /* Whether or not to send a hangup ack */
|
||||
int sendhangupack; /* Whether or not to send a hangup ack */
|
||||
int proc; /* Whether we've sent a call proceeding / alerting */
|
||||
|
||||
int ri; /* Restart Indicator (Restart Indicator IE) */
|
||||
int ri; /* Restart Indicator (Restart Indicator IE) */
|
||||
|
||||
/* Bearer Capability */
|
||||
int transcapability;
|
||||
@ -165,14 +165,15 @@ struct q931_call {
|
||||
int progcode; /* Progress coding */
|
||||
int progloc; /* Progress Location */
|
||||
int progress; /* Progress indicator */
|
||||
int progressmask; /* Progress Indicator bitmask */
|
||||
|
||||
int notify; /* Notification */
|
||||
int notify; /* Notification */
|
||||
|
||||
int causecode; /* Cause Coding */
|
||||
int causeloc; /* Cause Location */
|
||||
int cause; /* Cause of clearing */
|
||||
|
||||
int peercallstate; /* Call state of peer as reported */
|
||||
int peercallstate; /* Call state of peer as reported */
|
||||
int ourcallstate; /* Our call state */
|
||||
int sugcallstate; /* Status call state */
|
||||
|
||||
@ -187,7 +188,7 @@ struct q931_call {
|
||||
int nonisdn;
|
||||
char callednum[256]; /* Called Number */
|
||||
int complete; /* no more digits coming */
|
||||
int newcall; /* if the received message has a new call reference value */
|
||||
int newcall; /* if the received message has a new call reference value */
|
||||
|
||||
int retranstimer; /* Timer for retransmitting DISC */
|
||||
int t308_timedout; /* Whether t308 timed out once */
|
||||
|
375
q931.c
375
q931.c
@ -33,6 +33,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
|
||||
#define MAX_MAND_IES 10
|
||||
|
||||
@ -178,7 +179,7 @@ struct msgtype facilities[] = {
|
||||
/* The 4ESS uses a different audio field */
|
||||
#define PRI_TRANS_CAP_AUDIO_4ESS 0x08
|
||||
|
||||
|
||||
/* Don't forget to update PRI_PROG_xxx at libpri.h */
|
||||
#define Q931_PROG_CALL_NOT_E2E_ISDN 0x01
|
||||
#define Q931_PROG_CALLED_NOT_ISDN 0x02
|
||||
#define Q931_PROG_CALLER_NOT_ISDN 0x03
|
||||
@ -206,11 +207,15 @@ struct msgtype facilities[] = {
|
||||
|
||||
#define FUNC_DUMP(name) void ((name))(int full_ie, q931_ie *ie, int len, char prefix)
|
||||
#define FUNC_RECV(name) int ((name))(int full_ie, struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
|
||||
#define FUNC_SEND(name) int ((name))(int full_ie, struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
|
||||
#define FUNC_SEND(name) int ((name))(int full_ie, struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
|
||||
|
||||
|
||||
struct ie {
|
||||
/* Maximal count of same IEs at the message (0 - any, 1..n - limited) */
|
||||
int max_count;
|
||||
/* IE code */
|
||||
int ie;
|
||||
/* IE friendly name */
|
||||
char *name;
|
||||
/* Dump an IE for debugging (preceed all lines by prefix) */
|
||||
FUNC_DUMP(*dump);
|
||||
@ -317,6 +322,11 @@ static FUNC_RECV(receive_channel_id)
|
||||
static FUNC_SEND(transmit_channel_id)
|
||||
{
|
||||
int pos=0;
|
||||
|
||||
/* We are ready to transmit single IE only */
|
||||
if (order > 1)
|
||||
return 0;
|
||||
|
||||
/* Start with standard stuff */
|
||||
if (pri->switchtype == PRI_SWITCH_GR303_TMC)
|
||||
ie->data[pos] = 0x69;
|
||||
@ -590,6 +600,11 @@ static FUNC_RECV(receive_bearer_capability)
|
||||
static FUNC_SEND(transmit_bearer_capability)
|
||||
{
|
||||
int tc;
|
||||
|
||||
/* We are ready to transmit single IE only */
|
||||
if(order > 1)
|
||||
return 0;
|
||||
|
||||
tc = call->transcapability;
|
||||
if (pri->subchannel) {
|
||||
/* Bearer capability is *hard coded* in GR-303 */
|
||||
@ -821,6 +836,8 @@ static FUNC_RECV(receive_redirecting_number)
|
||||
|
||||
static FUNC_SEND(transmit_redirecting_number)
|
||||
{
|
||||
if (order > 1)
|
||||
return 0;
|
||||
if (call->redirectingnum && strlen(call->redirectingnum)) {
|
||||
ie->data[0] = call->redirectingplan;
|
||||
ie->data[1] = call->redirectingpres;
|
||||
@ -992,7 +1009,38 @@ static FUNC_RECV(receive_progress_indicator)
|
||||
{
|
||||
call->progloc = ie->data[0] & 0xf;
|
||||
call->progcode = (ie->data[0] & 0x60) >> 5;
|
||||
call->progress = (ie->data[1] & 0x7f);
|
||||
switch (call->progress = (ie->data[1] & 0x7f)) {
|
||||
case Q931_PROG_CALL_NOT_E2E_ISDN:
|
||||
call->progressmask |= PRI_PROG_CALL_NOT_E2E_ISDN;
|
||||
break;
|
||||
case Q931_PROG_CALLED_NOT_ISDN:
|
||||
call->progressmask |= PRI_PROG_CALLED_NOT_ISDN;
|
||||
break;
|
||||
case Q931_PROG_CALLER_NOT_ISDN:
|
||||
call->progressmask |= PRI_PROG_CALLER_NOT_ISDN;
|
||||
break;
|
||||
case Q931_PROG_INBAND_AVAILABLE:
|
||||
call->progressmask |= PRI_PROG_INBAND_AVAILABLE;
|
||||
break;
|
||||
case Q931_PROG_DELAY_AT_INTERF:
|
||||
call->progressmask |= PRI_PROG_DELAY_AT_INTERF;
|
||||
break;
|
||||
case Q931_PROG_INTERWORKING_WITH_PUBLIC:
|
||||
call->progressmask |= PRI_PROG_INTERWORKING_WITH_PUBLIC;
|
||||
break;
|
||||
case Q931_PROG_INTERWORKING_NO_RELEASE:
|
||||
call->progressmask |= PRI_PROG_INTERWORKING_NO_RELEASE;
|
||||
break;
|
||||
case Q931_PROG_INTERWORKING_NO_RELEASE_PRE_ANSWER:
|
||||
call->progressmask |= PRI_PROG_INTERWORKING_NO_RELEASE_PRE_ANSWER;
|
||||
break;
|
||||
case Q931_PROG_INTERWORKING_NO_RELEASE_POST_ANSWER:
|
||||
call->progressmask |= PRI_PROG_INTERWORKING_NO_RELEASE_POST_ANSWER;
|
||||
break;
|
||||
default:
|
||||
pri_error("XXX Invalid Progress indicator value received: %02x\n",(ie->data[1] & 0x7f));
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1090,15 +1138,42 @@ static FUNC_RECV(receive_facility)
|
||||
|
||||
static FUNC_SEND(transmit_progress_indicator)
|
||||
{
|
||||
int code, mask;
|
||||
/* Can't send progress indicator on GR-303 -- EVER! */
|
||||
if (!pri->subchannel && (call->progress > 0)) {
|
||||
ie->data[0] = 0x80 | (call->progcode << 5) | (call->progloc);
|
||||
ie->data[1] = 0x80 | (call->progress);
|
||||
return 4;
|
||||
} else {
|
||||
/* Leave off */
|
||||
if (pri->subchannel)
|
||||
return 0;
|
||||
if (call->progressmask > 0) {
|
||||
if (call->progressmask & (mask = PRI_PROG_CALL_NOT_E2E_ISDN))
|
||||
code = Q931_PROG_CALL_NOT_E2E_ISDN;
|
||||
else if (call->progressmask & (mask = PRI_PROG_CALLED_NOT_ISDN))
|
||||
code = Q931_PROG_CALLED_NOT_ISDN;
|
||||
else if (call->progressmask & (mask = PRI_PROG_CALLER_NOT_ISDN))
|
||||
code = Q931_PROG_CALLER_NOT_ISDN;
|
||||
else if (call->progressmask & (mask = PRI_PROG_INBAND_AVAILABLE))
|
||||
code = Q931_PROG_INBAND_AVAILABLE;
|
||||
else if (call->progressmask & (mask = PRI_PROG_DELAY_AT_INTERF))
|
||||
code = Q931_PROG_DELAY_AT_INTERF;
|
||||
else if (call->progressmask & (mask = PRI_PROG_INTERWORKING_WITH_PUBLIC))
|
||||
code = Q931_PROG_INTERWORKING_WITH_PUBLIC;
|
||||
else if (call->progressmask & (mask = PRI_PROG_INTERWORKING_NO_RELEASE))
|
||||
code = Q931_PROG_INTERWORKING_NO_RELEASE;
|
||||
else if (call->progressmask & (mask = PRI_PROG_INTERWORKING_NO_RELEASE_PRE_ANSWER))
|
||||
code = Q931_PROG_INTERWORKING_NO_RELEASE_PRE_ANSWER;
|
||||
else if (call->progressmask & (mask = PRI_PROG_INTERWORKING_NO_RELEASE_POST_ANSWER))
|
||||
code = Q931_PROG_INTERWORKING_NO_RELEASE_POST_ANSWER;
|
||||
else {
|
||||
code = 0;
|
||||
pri_error("XXX Undefined progress bit: %x\n", call->progressmask);
|
||||
}
|
||||
if (code) {
|
||||
ie->data[0] = 0x80 | (call->progcode << 5) | (call->progloc);
|
||||
ie->data[1] = 0x80 | code;
|
||||
call->progressmask &= ~mask;
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
/* Leave off */
|
||||
return 0;
|
||||
}
|
||||
static FUNC_SEND(transmit_call_state)
|
||||
{
|
||||
@ -1241,30 +1316,33 @@ static FUNC_DUMP(dump_facility)
|
||||
|
||||
static FUNC_DUMP(dump_network_spec_fac)
|
||||
{
|
||||
pri_message("%c Network-Specific Facilities (len=%2d) [ ", prefix, ie->len);
|
||||
if (ie->data[0] == 0x00) {
|
||||
pri_message (code2str(ie->data[1], facilities, sizeof(facilities) / sizeof(facilities[0])));
|
||||
}
|
||||
else
|
||||
dump_ie_data(ie->data, ie->len);
|
||||
pri_message(" ]\n");
|
||||
pri_message("%c Network-Specific Facilities (len=%2d) [ ", prefix, ie->len);
|
||||
if (ie->data[0] == 0x00) {
|
||||
pri_message (code2str(ie->data[1], facilities, sizeof(facilities) / sizeof(facilities[0])));
|
||||
}
|
||||
else
|
||||
dump_ie_data(ie->data, ie->len);
|
||||
pri_message(" ]\n");
|
||||
}
|
||||
|
||||
static FUNC_RECV(receive_network_spec_fac)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FUNC_SEND(transmit_network_spec_fac)
|
||||
{
|
||||
if (pri->nsf != PRI_NSF_NONE) {
|
||||
ie->data[0] = 0x00;
|
||||
ie->data[1] = pri->nsf;
|
||||
return 4;
|
||||
} else {
|
||||
/* Leave off */
|
||||
return 0;
|
||||
}
|
||||
/* We are ready to transmit single IE only */
|
||||
if (order > 1)
|
||||
return 0;
|
||||
|
||||
if (pri->nsf != PRI_NSF_NONE) {
|
||||
ie->data[0] = 0x00;
|
||||
ie->data[1] = pri->nsf;
|
||||
return 4;
|
||||
}
|
||||
/* Leave off */
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *pri_cause2str(int cause)
|
||||
@ -1310,6 +1388,10 @@ static FUNC_RECV(receive_cause)
|
||||
|
||||
static FUNC_SEND(transmit_cause)
|
||||
{
|
||||
/* We are ready to transmit single IE only */
|
||||
if (order > 1)
|
||||
return 0;
|
||||
|
||||
if (call->cause > 0) {
|
||||
ie->data[0] = 0x80 | (call->causecode << 5) | (call->causeloc);
|
||||
ie->data[1] = 0x80 | (call->cause);
|
||||
@ -1443,7 +1525,7 @@ static FUNC_RECV(receive_line_information)
|
||||
|
||||
static FUNC_SEND(transmit_line_information)
|
||||
{
|
||||
#if 0 /* XXX Is this IE possible for 4ESS? XXX */
|
||||
#if 0 /* XXX Is this IE possible for 4ESS only? XXX */
|
||||
if(pri->switchtype == PRI_SWITCH_ATT4ESS) {
|
||||
ie->data[0] = 0;
|
||||
return 3;
|
||||
@ -1604,6 +1686,9 @@ static FUNC_RECV(receive_generic_digits)
|
||||
static FUNC_SEND(transmit_generic_digits)
|
||||
{
|
||||
#if 0 /* XXX Is this IE possible for other switches? XXX */
|
||||
if (order > 1)
|
||||
return 0;
|
||||
|
||||
if(pri->switchtype == PRI_SWITCH_NI1) {
|
||||
ie->data[0] = 0x04; /* BCD even, Info Digits */
|
||||
ie->data[1] = 0x00; /* POTS */
|
||||
@ -1614,64 +1699,104 @@ static FUNC_SEND(transmit_generic_digits)
|
||||
}
|
||||
|
||||
|
||||
static char *signal2str(int signal)
|
||||
{
|
||||
/* From Q.931 4.5.8 Table 4-24 */
|
||||
static struct msgtype mtsignal[] = {
|
||||
{ 0, "Dial tone" },
|
||||
{ 1, "Ring back tone" },
|
||||
{ 2, "Intercept tone" },
|
||||
{ 3, "Network congestion tone" },
|
||||
{ 4, "Busy tone" },
|
||||
{ 5, "Confirm tone" },
|
||||
{ 6, "Answer tone" },
|
||||
{ 7, "Call waiting tone" },
|
||||
{ 8, "Off-hook warning tone" },
|
||||
{ 9, "Pre-emption tone" },
|
||||
{ 63, "Tones off" },
|
||||
{ 64, "Alerting on - pattern 0" },
|
||||
{ 65, "Alerting on - pattern 1" },
|
||||
{ 66, "Alerting on - pattern 2" },
|
||||
{ 67, "Alerting on - pattern 3" },
|
||||
{ 68, "Alerting on - pattern 4" },
|
||||
{ 69, "Alerting on - pattern 5" },
|
||||
{ 70, "Alerting on - pattern 6" },
|
||||
{ 71, "Alerting on - pattern 7" },
|
||||
{ 79, "Alerting off" },
|
||||
};
|
||||
return code2str(signal, mtsignal, sizeof(mtsignal) / sizeof(mtsignal[0]));
|
||||
}
|
||||
|
||||
|
||||
static FUNC_DUMP(dump_signal)
|
||||
{
|
||||
pri_message("%c Signal (len=%02d): ", prefix, len);
|
||||
if (len < 3) {
|
||||
pri_message("Invalid length\n");
|
||||
return;
|
||||
}
|
||||
pri_message("Signal %s (%d)\n", signal2str(ie->data[0]), ie->data[0]);
|
||||
}
|
||||
|
||||
|
||||
struct ie ies[] = {
|
||||
/* Codeset 0 - Common */
|
||||
{ NATIONAL_CHANGE_STATUS, "Change Status" },
|
||||
{ Q931_LOCKING_SHIFT, "Locking Shift", dump_shift },
|
||||
{ Q931_BEARER_CAPABILITY, "Bearer Capability", dump_bearer_capability, receive_bearer_capability, transmit_bearer_capability },
|
||||
{ Q931_CAUSE, "Cause", dump_cause, receive_cause, transmit_cause },
|
||||
{ Q931_CALL_STATE, "Call State", dump_call_state, receive_call_state, transmit_call_state },
|
||||
{ Q931_CHANNEL_IDENT, "Channel Identification", dump_channel_id, receive_channel_id, transmit_channel_id },
|
||||
{ Q931_PROGRESS_INDICATOR, "Progress Indicator", dump_progress_indicator, receive_progress_indicator, transmit_progress_indicator },
|
||||
{ Q931_NETWORK_SPEC_FAC, "Network-Specific Facilities", dump_network_spec_fac, receive_network_spec_fac, transmit_network_spec_fac },
|
||||
{ Q931_INFORMATION_RATE, "Information Rate" },
|
||||
{ Q931_TRANSIT_DELAY, "End-to-End Transit Delay" },
|
||||
{ Q931_TRANS_DELAY_SELECT, "Transmit Delay Selection and Indication" },
|
||||
{ Q931_BINARY_PARAMETERS, "Packet-layer Binary Parameters" },
|
||||
{ Q931_WINDOW_SIZE, "Packet-layer Window Size" },
|
||||
{ Q931_CLOSED_USER_GROUP, "Closed User Group" },
|
||||
{ Q931_REVERSE_CHARGE_INDIC, "Reverse Charging Indication" },
|
||||
{ Q931_CALLING_PARTY_NUMBER, "Calling Party Number", dump_calling_party_number, receive_calling_party_number, transmit_calling_party_number },
|
||||
{ Q931_CALLING_PARTY_SUBADDR, "Calling Party Subaddress", dump_calling_party_subaddr, receive_calling_party_subaddr },
|
||||
{ Q931_CALLED_PARTY_NUMBER, "Called Party Number", dump_called_party_number, receive_called_party_number, transmit_called_party_number },
|
||||
{ Q931_CALLED_PARTY_SUBADDR, "Called Party Subaddress", dump_called_party_subaddr },
|
||||
{ Q931_REDIRECTING_NUMBER, "Redirecting Number", dump_redirecting_number, receive_redirecting_number, transmit_redirecting_number },
|
||||
{ Q931_REDIRECTING_SUBADDR, "Redirecting Subaddress", dump_redirecting_subaddr },
|
||||
{ Q931_TRANSIT_NET_SELECT, "Transit Network Selection" },
|
||||
{ Q931_RESTART_INDICATOR, "Restart Indicator", dump_restart_indicator, receive_restart_indicator, transmit_restart_indicator },
|
||||
{ Q931_LOW_LAYER_COMPAT, "Low-layer Compatibility" },
|
||||
{ Q931_HIGH_LAYER_COMPAT, "High-layer Compatibility" },
|
||||
{ Q931_PACKET_SIZE, "Packet Size" },
|
||||
{ Q931_IE_FACILITY, "Facility" , dump_facility, receive_facility, transmit_facility },
|
||||
{ Q931_IE_REDIRECTION_NUMBER, "Redirection Number" },
|
||||
{ Q931_IE_REDIRECTION_SUBADDR, "Redirection Subaddress" },
|
||||
{ Q931_IE_FEATURE_ACTIVATE, "Feature Activation" },
|
||||
{ Q931_IE_INFO_REQUEST, "Feature Request" },
|
||||
{ Q931_IE_FEATURE_IND, "Feature Indication" },
|
||||
{ Q931_IE_SEGMENTED_MSG, "Segmented Message" },
|
||||
{ Q931_IE_CALL_IDENTITY, "Call Identity", dump_call_identity },
|
||||
{ Q931_IE_ENDPOINT_ID, "Endpoint Identification" },
|
||||
{ Q931_IE_NOTIFY_IND, "Notification Indicator", dump_notify, receive_notify, transmit_notify },
|
||||
{ Q931_DISPLAY, "Display", dump_display, receive_display, transmit_display },
|
||||
{ Q931_IE_TIME_DATE, "Date/Time", dump_time_date },
|
||||
{ Q931_IE_KEYPAD_FACILITY, "Keypad Facility" },
|
||||
{ Q931_IE_SIGNAL, "Signal" },
|
||||
{ Q931_IE_SWITCHHOOK, "Switch-hook" },
|
||||
{ Q931_IE_USER_USER, "User-User", dump_user_user, receive_user_user },
|
||||
{ Q931_IE_ESCAPE_FOR_EXT, "Escape for Extension" },
|
||||
{ Q931_IE_CALL_STATUS, "Call Status" },
|
||||
{ Q931_IE_CHANGE_STATUS, "Change Status" },
|
||||
{ Q931_IE_CONNECTED_ADDR, "Connected Number", dump_connected_number },
|
||||
{ Q931_IE_CONNECTED_NUM, "Connected Number", dump_connected_number },
|
||||
{ Q931_IE_ORIGINAL_CALLED_NUMBER, "Original Called Number", dump_redirecting_number, receive_redirecting_number, transmit_redirecting_number },
|
||||
{ Q931_IE_USER_USER_FACILITY, "User-User Facility" },
|
||||
{ Q931_IE_UPDATE, "Update" },
|
||||
{ Q931_SENDING_COMPLETE, "Sending Complete", dump_sending_complete, receive_sending_complete, transmit_sending_complete },
|
||||
{ 1, NATIONAL_CHANGE_STATUS, "Change Status" },
|
||||
{ 0, Q931_LOCKING_SHIFT, "Locking Shift", dump_shift },
|
||||
{ 0, Q931_BEARER_CAPABILITY, "Bearer Capability", dump_bearer_capability, receive_bearer_capability, transmit_bearer_capability },
|
||||
{ 0, Q931_CAUSE, "Cause", dump_cause, receive_cause, transmit_cause },
|
||||
{ 1, Q931_CALL_STATE, "Call State", dump_call_state, receive_call_state, transmit_call_state },
|
||||
{ 0, Q931_CHANNEL_IDENT, "Channel Identification", dump_channel_id, receive_channel_id, transmit_channel_id },
|
||||
{ 0, Q931_PROGRESS_INDICATOR, "Progress Indicator", dump_progress_indicator, receive_progress_indicator, transmit_progress_indicator },
|
||||
{ 0, Q931_NETWORK_SPEC_FAC, "Network-Specific Facilities", dump_network_spec_fac, receive_network_spec_fac, transmit_network_spec_fac },
|
||||
{ 1, Q931_INFORMATION_RATE, "Information Rate" },
|
||||
{ 1, Q931_TRANSIT_DELAY, "End-to-End Transit Delay" },
|
||||
{ 1, Q931_TRANS_DELAY_SELECT, "Transmit Delay Selection and Indication" },
|
||||
{ 1, Q931_BINARY_PARAMETERS, "Packet-layer Binary Parameters" },
|
||||
{ 1, Q931_WINDOW_SIZE, "Packet-layer Window Size" },
|
||||
{ 1, Q931_CLOSED_USER_GROUP, "Closed User Group" },
|
||||
{ 1, Q931_REVERSE_CHARGE_INDIC, "Reverse Charging Indication" },
|
||||
{ 1, Q931_CALLING_PARTY_NUMBER, "Calling Party Number", dump_calling_party_number, receive_calling_party_number, transmit_calling_party_number },
|
||||
{ 1, Q931_CALLING_PARTY_SUBADDR, "Calling Party Subaddress", dump_calling_party_subaddr, receive_calling_party_subaddr },
|
||||
{ 1, Q931_CALLED_PARTY_NUMBER, "Called Party Number", dump_called_party_number, receive_called_party_number, transmit_called_party_number },
|
||||
{ 1, Q931_CALLED_PARTY_SUBADDR, "Called Party Subaddress", dump_called_party_subaddr },
|
||||
{ 0, Q931_REDIRECTING_NUMBER, "Redirecting Number", dump_redirecting_number, receive_redirecting_number, transmit_redirecting_number },
|
||||
{ 1, Q931_REDIRECTING_SUBADDR, "Redirecting Subaddress", dump_redirecting_subaddr },
|
||||
{ 0, Q931_TRANSIT_NET_SELECT, "Transit Network Selection" },
|
||||
{ 1, Q931_RESTART_INDICATOR, "Restart Indicator", dump_restart_indicator, receive_restart_indicator, transmit_restart_indicator },
|
||||
{ 0, Q931_LOW_LAYER_COMPAT, "Low-layer Compatibility" },
|
||||
{ 0, Q931_HIGH_LAYER_COMPAT, "High-layer Compatibility" },
|
||||
{ 1, Q931_PACKET_SIZE, "Packet Size" },
|
||||
{ 1, Q931_IE_FACILITY, "Facility" , dump_facility, receive_facility, transmit_facility },
|
||||
{ 1, Q931_IE_REDIRECTION_NUMBER, "Redirection Number" },
|
||||
{ 1, Q931_IE_REDIRECTION_SUBADDR, "Redirection Subaddress" },
|
||||
{ 1, Q931_IE_FEATURE_ACTIVATE, "Feature Activation" },
|
||||
{ 1, Q931_IE_INFO_REQUEST, "Feature Request" },
|
||||
{ 1, Q931_IE_FEATURE_IND, "Feature Indication" },
|
||||
{ 1, Q931_IE_SEGMENTED_MSG, "Segmented Message" },
|
||||
{ 1, Q931_IE_CALL_IDENTITY, "Call Identity", dump_call_identity },
|
||||
{ 1, Q931_IE_ENDPOINT_ID, "Endpoint Identification" },
|
||||
{ 1, Q931_IE_NOTIFY_IND, "Notification Indicator", dump_notify, receive_notify, transmit_notify },
|
||||
{ 1, Q931_DISPLAY, "Display", dump_display, receive_display, transmit_display },
|
||||
{ 1, Q931_IE_TIME_DATE, "Date/Time", dump_time_date },
|
||||
{ 1, Q931_IE_KEYPAD_FACILITY, "Keypad Facility" },
|
||||
{ 0, Q931_IE_SIGNAL, "Signal", dump_signal },
|
||||
{ 1, Q931_IE_SWITCHHOOK, "Switch-hook" },
|
||||
{ 1, Q931_IE_USER_USER, "User-User", dump_user_user, receive_user_user },
|
||||
{ 1, Q931_IE_ESCAPE_FOR_EXT, "Escape for Extension" },
|
||||
{ 1, Q931_IE_CALL_STATUS, "Call Status" },
|
||||
{ 1, Q931_IE_CHANGE_STATUS, "Change Status" },
|
||||
{ 1, Q931_IE_CONNECTED_ADDR, "Connected Number", dump_connected_number },
|
||||
{ 1, Q931_IE_CONNECTED_NUM, "Connected Number", dump_connected_number },
|
||||
{ 1, Q931_IE_ORIGINAL_CALLED_NUMBER, "Original Called Number", dump_redirecting_number, receive_redirecting_number, transmit_redirecting_number },
|
||||
{ 1, Q931_IE_USER_USER_FACILITY, "User-User Facility" },
|
||||
{ 1, Q931_IE_UPDATE, "Update" },
|
||||
{ 1, Q931_SENDING_COMPLETE, "Sending Complete", dump_sending_complete, receive_sending_complete, transmit_sending_complete },
|
||||
/* Codeset 6 - Network specific */
|
||||
{ Q931_IE_ORIGINATING_LINE_INFO, "Originating Line Information", dump_line_information, receive_line_information, transmit_line_information },
|
||||
{ Q931_IE_FACILITY | Q931_CODESET(6), "Facility", dump_facility, receive_facility, transmit_facility },
|
||||
{ Q931_DISPLAY | Q931_CODESET(6), "Display (CS6)", dump_display, receive_display, transmit_display },
|
||||
{ Q931_IE_GENERIC_DIGITS, "Generic Digits", dump_generic_digits, receive_generic_digits, transmit_generic_digits },
|
||||
{ 1, Q931_IE_ORIGINATING_LINE_INFO, "Originating Line Information", dump_line_information, receive_line_information, transmit_line_information },
|
||||
{ 1, Q931_IE_FACILITY | Q931_CODESET(6), "Facility", dump_facility, receive_facility, transmit_facility },
|
||||
{ 1, Q931_DISPLAY | Q931_CODESET(6), "Display (CS6)", dump_display, receive_display, transmit_display },
|
||||
{ 0, Q931_IE_GENERIC_DIGITS, "Generic Digits", dump_generic_digits, receive_generic_digits, transmit_generic_digits },
|
||||
/* Codeset 7 */
|
||||
};
|
||||
|
||||
@ -1891,8 +2016,9 @@ void __q931_destroycall(struct pri *pri, q931_call *c)
|
||||
static int add_ie(struct pri *pri, q931_call *call, int msgtype, int ie, q931_ie *iet, int maxlen, int *codeset)
|
||||
{
|
||||
unsigned int x;
|
||||
int res;
|
||||
int res, total_res;
|
||||
int have_shift;
|
||||
int ies_count, order;
|
||||
for (x=0;x<sizeof(ies) / sizeof(ies[0]);x++) {
|
||||
if (ies[x].ie == ie) {
|
||||
/* This is our baby */
|
||||
@ -1907,19 +2033,32 @@ static int add_ie(struct pri *pri, q931_call *call, int msgtype, int ie, q931_ie
|
||||
}
|
||||
else
|
||||
have_shift = 0;
|
||||
iet->ie = ie;
|
||||
res = ies[x].transmit(ie, pri, call, msgtype, iet, maxlen);
|
||||
/* Error if res < 0 or ignored if res == 0 */
|
||||
if (res <= 0)
|
||||
return res;
|
||||
if ((iet->ie & 0x80) == 0) /* Multibyte IE */
|
||||
iet->len = res - 2;
|
||||
if (have_shift) {
|
||||
ies_count = ies[x].max_count;
|
||||
if (ies_count == 0)
|
||||
ies_count = INT_MAX;
|
||||
order = 0;
|
||||
total_res = 0;
|
||||
do {
|
||||
iet->ie = ie;
|
||||
res = ies[x].transmit(ie, pri, call, msgtype, iet, maxlen, ++order);
|
||||
/* Error if res < 0 or ignored if res == 0 */
|
||||
if (res < 0)
|
||||
return res;
|
||||
if (res > 0) {
|
||||
if ((iet->ie & 0x80) == 0) /* Multibyte IE */
|
||||
iet->len = res - 2;
|
||||
total_res += res;
|
||||
maxlen -= res;
|
||||
iet = (q931_ie *)((char *)iet + res);
|
||||
}
|
||||
}
|
||||
while (res > 0 && order < ies_count);
|
||||
if (have_shift && total_res) {
|
||||
if (Q931_IE_CODESET(ies[x].ie))
|
||||
*codeset = Q931_IE_CODESET(ies[x].ie);
|
||||
return res + 1; /* Shift is single-byte IE */
|
||||
return total_res + 1; /* Shift is single-byte IE */
|
||||
}
|
||||
return res;
|
||||
return total_res;
|
||||
} else {
|
||||
pri_error("!! Don't know how to add an IE %s (%d)\n", ie2str(ie), ie);
|
||||
return -1;
|
||||
@ -2146,9 +2285,12 @@ int q931_call_progress(struct pri *pri, q931_call *c, int channel, int info)
|
||||
if (info) {
|
||||
c->progloc = LOC_PRIV_NET_LOCAL_USER;
|
||||
c->progcode = CODE_CCITT;
|
||||
c->progress = Q931_PROG_INBAND_AVAILABLE;
|
||||
} else
|
||||
c->progress = -1;
|
||||
c->progressmask = PRI_PROG_INBAND_AVAILABLE;
|
||||
} else {
|
||||
/* PI is mandatory IE for PROGRESS message - Q.931 3.1.8 */
|
||||
pri_error("XXX Progress message requested but no information is provided\n");
|
||||
c->progressmask = 0;
|
||||
}
|
||||
c->alive = 1;
|
||||
return send_message(pri, c, Q931_PROGRESS, call_progress_ies);
|
||||
}
|
||||
@ -2173,9 +2315,9 @@ int q931_call_proceeding(struct pri *pri, q931_call *c, int channel, int info)
|
||||
if (info) {
|
||||
c->progloc = LOC_PRIV_NET_LOCAL_USER;
|
||||
c->progcode = CODE_CCITT;
|
||||
c->progress = Q931_PROG_INBAND_AVAILABLE;
|
||||
c->progressmask = PRI_PROG_INBAND_AVAILABLE;
|
||||
} else
|
||||
c->progress = -1;
|
||||
c->progressmask = 0;
|
||||
c->proc = 1;
|
||||
c->alive = 1;
|
||||
return send_message(pri, c, Q931_CALL_PROCEEDING, call_proceeding_ies);
|
||||
@ -2193,9 +2335,9 @@ int q931_alerting(struct pri *pri, q931_call *c, int channel, int info)
|
||||
if (info) {
|
||||
c->progloc = LOC_PRIV_NET_LOCAL_USER;
|
||||
c->progcode = CODE_CCITT;
|
||||
c->progress = Q931_PROG_INBAND_AVAILABLE;
|
||||
c->progressmask = PRI_PROG_INBAND_AVAILABLE;
|
||||
} else
|
||||
c->progress = -1;
|
||||
c->progressmask = 0;
|
||||
c->ourcallstate = Q931_CALL_STATE_CALL_RECEIVED;
|
||||
c->peercallstate = Q931_CALL_STATE_CALL_DELIVERED;
|
||||
c->alive = 1;
|
||||
@ -2216,9 +2358,9 @@ int q931_setup_ack(struct pri *pri, q931_call *c, int channel, int nonisdn)
|
||||
if (nonisdn && (pri->switchtype != PRI_SWITCH_DMS100)) {
|
||||
c->progloc = LOC_PRIV_NET_LOCAL_USER;
|
||||
c->progcode = CODE_CCITT;
|
||||
c->progress = Q931_PROG_CALLED_NOT_ISDN;
|
||||
c->progressmask = PRI_PROG_CALLED_NOT_ISDN;
|
||||
} else
|
||||
c->progress = -1;
|
||||
c->progressmask = 0;
|
||||
c->ourcallstate = Q931_CALL_STATE_OVERLAP_RECEIVING;
|
||||
c->peercallstate = Q931_CALL_STATE_OVERLAP_SENDING;
|
||||
c->alive = 1;
|
||||
@ -2287,9 +2429,9 @@ int q931_connect(struct pri *pri, q931_call *c, int channel, int nonisdn)
|
||||
if (nonisdn && (pri->switchtype != PRI_SWITCH_DMS100)) {
|
||||
c->progloc = LOC_PRIV_NET_LOCAL_USER;
|
||||
c->progcode = CODE_CCITT;
|
||||
c->progress = Q931_PROG_CALLED_NOT_ISDN;
|
||||
c->progressmask = PRI_PROG_CALLED_NOT_ISDN;
|
||||
} else
|
||||
c->progress = -1;
|
||||
c->progressmask = 0;
|
||||
c->ourcallstate = Q931_CALL_STATE_CONNECT_REQUEST;
|
||||
c->peercallstate = Q931_CALL_STATE_ACTIVE;
|
||||
c->alive = 1;
|
||||
@ -2444,9 +2586,9 @@ int q931_setup(struct pri *pri, q931_call *c, struct pri_sr *req)
|
||||
return -1;
|
||||
|
||||
if (req->nonisdn && (pri->switchtype == PRI_SWITCH_NI2))
|
||||
c->progress = Q931_PROG_CALLER_NOT_ISDN;
|
||||
c->progressmask = PRI_PROG_CALLER_NOT_ISDN;
|
||||
else
|
||||
c->progress = -1;
|
||||
c->progressmask = 0;
|
||||
if (pri->subchannel)
|
||||
res = send_message(pri, c, Q931_SETUP, gr303_setup_ies);
|
||||
else
|
||||
@ -2664,19 +2806,19 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
||||
c->useruserprotocoldisc = -1;
|
||||
strcpy(c->useruserinfo, "");
|
||||
c->complete = 0;
|
||||
break;
|
||||
c->nonisdn = 0;
|
||||
/* Fall through */
|
||||
case Q931_CONNECT:
|
||||
case Q931_ALERTING:
|
||||
case Q931_PROGRESS:
|
||||
case Q931_CALL_PROCEEDING:
|
||||
c->progress = -1;
|
||||
c->progressmask = 0;
|
||||
break;
|
||||
case Q931_CONNECT_ACKNOWLEDGE:
|
||||
if (c->retranstimer)
|
||||
pri_schedule_del(pri, c->retranstimer);
|
||||
c->retranstimer = 0;
|
||||
/* Fall through */
|
||||
case Q931_CALL_PROCEEDING:
|
||||
/* Do nothing */
|
||||
break;
|
||||
case Q931_RELEASE:
|
||||
case Q931_DISCONNECT:
|
||||
@ -2843,11 +2985,17 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
||||
if (!c->newcall) {
|
||||
break;
|
||||
}
|
||||
if (c->progressmask & PRI_PROG_CALLER_NOT_ISDN)
|
||||
c->nonisdn = 1;
|
||||
c->newcall = 0;
|
||||
c->ourcallstate = Q931_CALL_STATE_CALL_PRESENT;
|
||||
c->peercallstate = Q931_CALL_STATE_CALL_INITIATED;
|
||||
/* it's not yet a call since higher level can respond with RELEASE or RELEASE_COMPLETE */
|
||||
c->alive = 0;
|
||||
if (c->transmoderate != TRANS_MODE_64_CIRCUIT) {
|
||||
q931_release_complete(pri, c, PRI_CAUSE_BEARERCAPABILITY_NOTIMPL);
|
||||
break;
|
||||
}
|
||||
pri->ev.e = PRI_EVENT_RING;
|
||||
pri->ev.ring.channel = c->channelno | (c->ds1no << 8);
|
||||
pri->ev.ring.callingpres = c->callerpres;
|
||||
@ -2867,10 +3015,8 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
||||
pri->ev.ring.complete = c->complete;
|
||||
pri->ev.ring.ctype = c->transcapability;
|
||||
pri->ev.ring.redirectingreason = c->redirectingreason;
|
||||
if (c->transmoderate != TRANS_MODE_64_CIRCUIT) {
|
||||
q931_release_complete(pri, c, PRI_CAUSE_BEARERCAPABILITY_NOTIMPL);
|
||||
break;
|
||||
}
|
||||
pri->ev.ring.progress = c->progress;
|
||||
pri->ev.ring.progressmask = c->progressmask;
|
||||
return Q931_RES_HAVEEVENT;
|
||||
case Q931_ALERTING:
|
||||
if (c->newcall) {
|
||||
@ -2884,6 +3030,7 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
||||
pri->ev.ringing.cref = c->cr;
|
||||
pri->ev.ringing.call = c;
|
||||
pri->ev.ringing.progress = c->progress;
|
||||
pri->ev.ringing.progressmask = c->progressmask;
|
||||
return Q931_RES_HAVEEVENT;
|
||||
case Q931_CONNECT:
|
||||
if (c->newcall) {
|
||||
@ -2901,6 +3048,7 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
||||
pri->ev.answer.cref = c->cr;
|
||||
pri->ev.answer.call = c;
|
||||
pri->ev.answer.progress = c->progress;
|
||||
pri->ev.answer.progressmask = c->progressmask;
|
||||
q931_connect_acknowledge(pri, c);
|
||||
return Q931_RES_HAVEEVENT;
|
||||
case Q931_FACILITY:
|
||||
@ -2945,6 +3093,7 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
||||
c->peercallstate = Q931_CALL_STATE_INCOMING_CALL_PROCEEDING;
|
||||
}
|
||||
pri->ev.proceeding.progress = c->progress;
|
||||
pri->ev.proceeding.progressmask = c->progressmask;
|
||||
pri->ev.proceeding.cref = c->cr;
|
||||
pri->ev.proceeding.call = c;
|
||||
return Q931_RES_HAVEEVENT;
|
||||
|
Loading…
Reference in New Issue
Block a user