2470 lines
51 KiB
C
2470 lines
51 KiB
C
#include "primitives.h"
|
|
#include "phone.h"
|
|
#include "streamlib.h"
|
|
#include "phone_1TR6.h"
|
|
#include "q_data.h"
|
|
#include "isdn_23.h"
|
|
#include "isdn3_phone.h"
|
|
#include "isdn_34.h"
|
|
#include "kernel.h"
|
|
#include "prot_1TR6_1.h"
|
|
#include "prot_1TR6_common.h"
|
|
#include "sapi.h"
|
|
|
|
#undef HAS_SUSPEND
|
|
|
|
#define FAC_PENDING 002
|
|
#define SVC_PENDING 004
|
|
|
|
#define RUN_N1_T308 01
|
|
#define RUN_N1_T313 02
|
|
#ifdef HAS_SUSPEND
|
|
#define RUN_N1_T318 04
|
|
#endif
|
|
#define RUN_N1_T305 010
|
|
#define RUN_N1_T3D1 020
|
|
#define RUN_N1_T303 040
|
|
#define RUN_N1_T304 0100
|
|
#define RUN_N1_T310 0200
|
|
#define RUN_N1_T3D2 0400
|
|
#ifdef HAS_SUSPEND
|
|
#define RUN_N1_T319 01000
|
|
#endif
|
|
#define RUN_N1_T3AA 02000
|
|
#define RUN_N1_TCONN 04000
|
|
#define RUN_N1_TALERT 010000
|
|
#define REP_T308 020000
|
|
#define RUN_N1_TFOO 040000
|
|
#define VAL_N1_T308 ( 4 *HZ)
|
|
#define VAL_N1_T313 ( 8 *HZ) /* Should be 4 */
|
|
#ifdef HAS_SUSPEND
|
|
#define VAL_N1_T318 ( 4 *HZ)
|
|
#endif
|
|
#define VAL_N1_T305 ( 4 *HZ)
|
|
#define VAL_N1_T3D1 ( 10 *HZ)
|
|
#define VAL_N1_T303 ( 10 *HZ) /* was 4. L1 startup, TEI, L2 startup ... */
|
|
#define VAL_N1_T304 ( 20 *HZ)
|
|
#define VAL_N1_T310 ( 120 *HZ)
|
|
#define VAL_N1_T3D2 ( 10 *HZ)
|
|
#ifdef HAS_SUSPEND
|
|
#define VAL_N1_T319 ( 4 *HZ)
|
|
#endif
|
|
#define VAL_N1_T3AA ( 120 *HZ)
|
|
#define VAL_N1_TCONN ( 40 * HZ) /* timer for connection establishment */
|
|
#define VAL_N1_TALERT ( 1 *HZ) /* timer for delaying an ALERT response */
|
|
#define VAL_N1_TFOO (4*HZ)
|
|
|
|
static void N1_T308 (isdn3_conn conn);
|
|
static void N1_T313 (isdn3_conn conn);
|
|
|
|
#ifdef HAS_SUSPEND
|
|
static void N1_T318 (isdn3_conn conn);
|
|
|
|
#endif
|
|
static void N1_T305 (isdn3_conn conn);
|
|
static void N1_T3D1 (isdn3_conn conn);
|
|
static void N1_T303 (isdn3_conn conn);
|
|
static void N1_T304 (isdn3_conn conn);
|
|
static void N1_T310 (isdn3_conn conn);
|
|
static void N1_T3D2 (isdn3_conn conn);
|
|
|
|
#ifdef HAS_SUSPEND
|
|
static void N1_T319 (isdn3_conn conn);
|
|
#endif
|
|
static void N1_T3AA (isdn3_conn conn);
|
|
static void N1_TCONN (isdn3_conn conn);
|
|
static void N1_TALERT (isdn3_conn conn);
|
|
static void N1_TFOO (isdn3_conn conn);
|
|
|
|
static int send_disc (isdn3_conn conn, char release, mblk_t * data);
|
|
static void report_terminate (isdn3_conn conn, uchar_t * data, int len, ushort_t cause);
|
|
|
|
struct t_info {
|
|
unsigned short service;
|
|
unsigned char flags;
|
|
unsigned char eaz;
|
|
unsigned char nr[MAXNR];
|
|
};
|
|
|
|
static void
|
|
phone_timerup (isdn3_conn conn)
|
|
{
|
|
rtimer (N1_T308, conn);
|
|
rtimer (N1_T313, conn);
|
|
#ifdef HAS_SUSPEND
|
|
rtimer (N1_T318, conn);
|
|
#endif
|
|
rtimer (N1_T305, conn);
|
|
rtimer (N1_T3D1, conn);
|
|
rtimer (N1_T303, conn);
|
|
rtimer (N1_T304, conn);
|
|
rtimer (N1_T310, conn);
|
|
rtimer (N1_T3D2, conn);
|
|
#ifdef HAS_SUSPEND
|
|
rtimer (N1_T319, conn);
|
|
#endif
|
|
rtimer (N1_T3AA, conn);
|
|
rtimer (N1_TCONN, conn);
|
|
rtimer (N1_TALERT, conn);
|
|
rtimer (N1_TFOO, conn);
|
|
}
|
|
|
|
#define setstate(a,b) Xsetstate((a),(b),__LINE__)
|
|
static void
|
|
Xsetstate (isdn3_conn conn, uchar_t state, int deb_line)
|
|
{
|
|
if(log_34 & 2)printf ("Conn PostN1:%d %ld: State %d --> %d\n", deb_line, conn->call_ref, conn->state, state);
|
|
if (conn->state == state)
|
|
return;
|
|
switch (conn->state) {
|
|
case 1:
|
|
untimer (N1_T303, conn);
|
|
break;
|
|
case 2:
|
|
untimer (N1_T304, conn);
|
|
break;
|
|
case 3:
|
|
untimer (N1_T310, conn);
|
|
break;
|
|
case 8:
|
|
untimer (N1_T313, conn);
|
|
/* FALL THRU */
|
|
case 4:
|
|
case 10:
|
|
case 12:
|
|
case 14:
|
|
untimer (N1_T3D2, conn);
|
|
break;
|
|
case 7:
|
|
untimer (N1_T3D2, conn);
|
|
untimer (N1_TCONN, conn);
|
|
break;
|
|
case 6:
|
|
untimer (N1_TCONN, conn);
|
|
untimer (N1_TALERT, conn);
|
|
break;
|
|
case 11:
|
|
untimer (N1_T305, conn);
|
|
break;
|
|
#ifdef HAS_SUSPEND
|
|
case 15:
|
|
untimer (N1_T319, conn);
|
|
break;
|
|
case 17:
|
|
untimer (N1_T318, conn);
|
|
break;
|
|
#endif
|
|
case 19:
|
|
untimer (N1_T308, conn);
|
|
break;
|
|
case 21:
|
|
case 20:
|
|
untimer (N1_T3D1, conn);
|
|
break;
|
|
case 99:
|
|
untimer(N1_TFOO, conn);
|
|
break;
|
|
}
|
|
conn->state = state;
|
|
if(state > 10 || state == 0)
|
|
report_terminate (conn, NULL,0,0);
|
|
switch (conn->state) {
|
|
case 1:
|
|
timer (N1_T303, conn);
|
|
break;
|
|
case 2:
|
|
timer (N1_T304, conn);
|
|
break;
|
|
case 3:
|
|
timer (N1_T310, conn);
|
|
break;
|
|
case 6:
|
|
ftimer (N1_TALERT, conn);
|
|
/* FALL THRU */
|
|
case 7:
|
|
ftimer (N1_TCONN, conn);
|
|
break;
|
|
case 8:
|
|
timer (N1_T313, conn);
|
|
break;
|
|
case 11:
|
|
timer (N1_T305, conn);
|
|
break;
|
|
#ifdef HAS_SUSPEND
|
|
case 15:
|
|
timer (N1_T319, conn);
|
|
break;
|
|
case 17:
|
|
timer (N1_T318, conn);
|
|
break;
|
|
#endif
|
|
case 19:
|
|
timer (N1_T308, conn);
|
|
break;
|
|
case 21:
|
|
case 20:
|
|
timer (N1_T3D1, conn);
|
|
break;
|
|
case 99:
|
|
timer(N1_TFOO, conn);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static int
|
|
get_serviceInd (isdn3_conn conn, uchar_t * data, int len)
|
|
{
|
|
int qd_len;
|
|
uchar_t *qd_data;
|
|
|
|
qd_data = qd_find (data, len, 6, PT_N6_serviceInd, &qd_len);
|
|
if (qd_data == NULL)
|
|
return 0;
|
|
if (qd_len < 1)
|
|
return 0;
|
|
((struct t_info *)conn->p_data)->service = *qd_data++ << 8;
|
|
if (qd_len > 1)
|
|
((struct t_info *)conn->p_data)->service += *qd_data;
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
get_nr (isdn3_conn conn, uchar_t * data, int len, uchar_t what)
|
|
{
|
|
int qd_len;
|
|
uchar_t *qd_data;
|
|
uchar_t *nrpos;
|
|
|
|
((struct t_info *)conn->p_data)->nr[0] = '\0';
|
|
qd_data = qd_find (data, len, 0, what, &qd_len);
|
|
if (qd_data == NULL)
|
|
return 0;
|
|
while (qd_len-- > 0 && (*qd_data++ & 0x80) == 0) ;
|
|
if (qd_len < 1)
|
|
return 0;
|
|
if (qd_len > MAXNR)
|
|
qd_len = MAXNR;
|
|
nrpos = ((struct t_info *)conn->p_data)->nr;
|
|
while (qd_len-- > 0) {
|
|
*nrpos++ = *qd_data & 0x7F;
|
|
if (*qd_data++ & 0x80)
|
|
break;
|
|
}
|
|
*nrpos = '\0';
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
get_eaz (isdn3_conn conn, uchar_t * data, int len, uchar_t what)
|
|
{
|
|
int qd_len;
|
|
uchar_t *qd_data;
|
|
|
|
((struct t_info *)conn->p_data)->eaz = 0;
|
|
qd_data = qd_find (data, len, 0, what, &qd_len);
|
|
if (qd_data == NULL)
|
|
return 0;
|
|
while (qd_len-- > 0 && (*qd_data++ & 0x80) == 0) ;
|
|
if (qd_len < 1)
|
|
return 0;
|
|
if (qd_len > MAXNR)
|
|
qd_len = MAXNR;
|
|
while (qd_len-- > 0) {
|
|
((struct t_info *)conn->p_data)->eaz = *qd_data & 0x7F;
|
|
if (*qd_data++ & 0x80)
|
|
break;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
get_chanID (isdn3_conn conn, uchar_t * data, int len)
|
|
{
|
|
int qd_len;
|
|
uchar_t *qd_data;
|
|
|
|
qd_data = qd_find (data, len, 0, PT_N0_chanID, &qd_len);
|
|
if (qd_data == NULL)
|
|
return 0;
|
|
if (qd_len < 1)
|
|
return 0;
|
|
switch (*qd_data & 0xF0) {
|
|
case 0x80:
|
|
conn->bchan = *qd_data & 0x03;
|
|
if (conn->bchan == 3) {
|
|
if (conn->card == NULL)
|
|
conn->bchan = 0;
|
|
else
|
|
conn->bchan = isdn3_free_b (conn->card);
|
|
} else if (conn->bchan != 0) {
|
|
if(!(conn->minorstate & MS_BCHAN)) {
|
|
conn->minorstate |= MS_BCHAN;
|
|
isdn3_setup_conn(conn,EST_SETUP);
|
|
}
|
|
}
|
|
break;
|
|
case 0xA0:
|
|
if ((*qd_data & 0x03) != 1) {
|
|
conn->bchan = 0;
|
|
break;
|
|
}
|
|
if (qd_len < 3)
|
|
return 0;
|
|
conn->bchan = qd_data[2];
|
|
if (conn->bchan != 0) {
|
|
if(!(conn->minorstate & MS_BCHAN)) {
|
|
conn->minorstate |= MS_BCHAN;
|
|
isdn3_setup_conn(conn,EST_SETUP);
|
|
}
|
|
}
|
|
if (conn->card != NULL && conn->card->bchans < conn->bchan)
|
|
return 0;
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
report_setup (isdn3_conn conn, uchar_t * data, int len)
|
|
/* Send SETUP up */
|
|
{
|
|
int err = 0;
|
|
|
|
mblk_t *mb = allocb (256, BPRI_MED);
|
|
|
|
if (mb == NULL) {
|
|
setstate (conn, 0);
|
|
return -ENOMEM;
|
|
}
|
|
m_putid (mb, IND_INCOMING);
|
|
conn_info (conn, mb);
|
|
|
|
report_addisplay (mb, data, len);
|
|
|
|
if ((err = isdn3_at_send (conn, mb, 0)) != 0) {
|
|
freemsg (mb);
|
|
setstate (conn, 99);
|
|
return err;
|
|
}
|
|
return err;
|
|
}
|
|
|
|
static int
|
|
report_setup_ack (isdn3_conn conn, uchar_t * data, int len)
|
|
{
|
|
int err = 0;
|
|
|
|
mblk_t *mb = allocb (256, BPRI_MED);
|
|
|
|
if (mb == NULL) {
|
|
setstate (conn, 0);
|
|
return -ENOMEM;
|
|
}
|
|
m_putid (mb, IND_INFO);
|
|
m_putid (mb, ID_N1_SETUP_ACK);
|
|
conn_info (conn, mb);
|
|
|
|
report_addisplay (mb, data, len);
|
|
|
|
if ((err = isdn3_at_send (conn, mb, 0)) != 0) {
|
|
freemsg (mb);
|
|
setstate (conn, 99);
|
|
return err;
|
|
}
|
|
return err;
|
|
}
|
|
|
|
static int
|
|
report_call_sent (isdn3_conn conn, uchar_t * data, int len)
|
|
{
|
|
int err = 0;
|
|
|
|
mblk_t *mb = allocb (256, BPRI_MED);
|
|
|
|
if (mb == NULL) {
|
|
setstate (conn, 0);
|
|
return -ENOMEM;
|
|
}
|
|
m_putid (mb, IND_INFO);
|
|
m_putid (mb, ID_N1_CALL_SENT);
|
|
conn_info (conn, mb);
|
|
|
|
report_addisplay (mb, data, len);
|
|
|
|
if ((err = isdn3_at_send (conn, mb, 0)) != 0) {
|
|
freemsg (mb);
|
|
setstate (conn, 99);
|
|
return err;
|
|
}
|
|
return err;
|
|
}
|
|
|
|
static int
|
|
report_alert (isdn3_conn conn, uchar_t * data, int len)
|
|
{
|
|
int err = 0;
|
|
|
|
mblk_t *mb = allocb (256, BPRI_MED);
|
|
|
|
if (mb == NULL) {
|
|
setstate (conn, 0);
|
|
return -ENOMEM;
|
|
}
|
|
m_putid (mb, IND_INFO);
|
|
m_putid (mb, ID_N1_ALERT);
|
|
|
|
conn_info (conn, mb);
|
|
|
|
report_addisplay (mb, data, len);
|
|
report_addstatus (mb, data, len);
|
|
|
|
if ((err = isdn3_at_send (conn, mb, 0)) != 0) {
|
|
freemsg (mb);
|
|
setstate (conn, 99);
|
|
return err;
|
|
}
|
|
return err;
|
|
}
|
|
|
|
static int
|
|
report_user_info (isdn3_conn conn, uchar_t * data, int len)
|
|
{
|
|
int err = 0;
|
|
int qd_len;
|
|
uchar_t *qd_data;
|
|
|
|
mblk_t *mb = allocb (256, BPRI_MED);
|
|
|
|
if (mb == NULL) {
|
|
setstate (conn, 0);
|
|
return -ENOMEM;
|
|
}
|
|
m_putid (mb, IND_INFO);
|
|
m_putid (mb, ID_N1_ALERT);
|
|
conn_info (conn, mb);
|
|
|
|
qd_data = qd_find (data, len, 0, PT_N0_userInfo, &qd_len);
|
|
if (qd_data == NULL)
|
|
return 0;
|
|
m_putsx (mb, ID_N0_userInfo);
|
|
m_puts (mb, qd_data, qd_len);
|
|
|
|
qd_data = qd_find (data, len, 0, PT_N0_moreData, &qd_len);
|
|
if (qd_data != NULL)
|
|
m_putsx (mb, ID_N0_moreData);
|
|
|
|
if ((err = isdn3_at_send (conn, mb, 0)) != 0) {
|
|
freemsg (mb);
|
|
setstate (conn, 99);
|
|
return err;
|
|
}
|
|
return err;
|
|
}
|
|
|
|
static int
|
|
report_conn (isdn3_conn conn, uchar_t * data, int len)
|
|
{
|
|
int err = 0;
|
|
|
|
mblk_t *mb = allocb (256, BPRI_MED);
|
|
|
|
if (mb == NULL) {
|
|
setstate (conn, 0);
|
|
return -ENOMEM;
|
|
}
|
|
m_putid (mb, IND_CONN);
|
|
conn_info (conn, mb);
|
|
report_addisplay (mb, data, len);
|
|
report_addnsf (mb, data, len);
|
|
report_addcost (mb, data, len);
|
|
report_adddate (mb, data, len);
|
|
|
|
if ((err = isdn3_at_send (conn, mb, 0)) != 0) {
|
|
freemsg (mb);
|
|
setstate (conn, 99);
|
|
return err;
|
|
}
|
|
return err;
|
|
}
|
|
|
|
static int
|
|
report_conn_ack (isdn3_conn conn, uchar_t * data, int len)
|
|
{
|
|
int err = 0;
|
|
|
|
mblk_t *mb = allocb (256, BPRI_MED);
|
|
|
|
if (mb == NULL) {
|
|
setstate (conn, 0);
|
|
return -ENOMEM;
|
|
}
|
|
m_putid (mb, IND_INFO);
|
|
m_putid (mb, ID_N1_CONN_ACK);
|
|
conn_info (conn, mb);
|
|
|
|
report_addisplay (mb, data, len);
|
|
report_addcost (mb, data, len);
|
|
report_adddate (mb, data, len);
|
|
|
|
if ((err = isdn3_at_send (conn, mb, 0)) != 0) {
|
|
freemsg (mb);
|
|
setstate (conn, 99);
|
|
return err;
|
|
}
|
|
return err;
|
|
}
|
|
|
|
static int
|
|
report_info (isdn3_conn conn, uchar_t * data, int len)
|
|
{
|
|
int err = 0;
|
|
|
|
mblk_t *mb = allocb (256, BPRI_MED);
|
|
|
|
if (mb == NULL) {
|
|
setstate (conn, 0);
|
|
return -ENOMEM;
|
|
}
|
|
m_putid (mb, IND_INFO);
|
|
m_putid (mb, ID_N1_INFO);
|
|
conn_info (conn, mb);
|
|
|
|
report_addisplay (mb, data, len);
|
|
report_addcost (mb, data, len);
|
|
report_addnsf (mb, data, len);
|
|
|
|
if ((err = isdn3_at_send (conn, mb, 0)) != 0) {
|
|
freemsg (mb);
|
|
setstate (conn, 99);
|
|
return err;
|
|
}
|
|
return err;
|
|
}
|
|
|
|
static int
|
|
report_stat (isdn3_conn conn, uchar_t * data, int len)
|
|
{
|
|
int err = 0;
|
|
char cval;
|
|
|
|
mblk_t *mb = allocb (256, BPRI_MED);
|
|
|
|
if (mb == NULL) {
|
|
setstate (conn, 0);
|
|
return -ENOMEM;
|
|
}
|
|
m_putid (mb, IND_INFO);
|
|
m_putid (mb, ID_N1_STAT);
|
|
conn_info (conn, mb);
|
|
|
|
cval = report_addcause (mb, data, len);
|
|
conn->lockit++;
|
|
switch (cval) {
|
|
case N1_RemoteUserSuspend:
|
|
isdn3_setup_conn (conn, EST_DISCONNECT /* was INTERRUPT */ );
|
|
break;
|
|
case N1_RemoteUserResumed:
|
|
switch (conn->state) {
|
|
case 7:
|
|
case 8:
|
|
isdn3_setup_conn (conn, EST_LISTEN);
|
|
break;
|
|
case 14:
|
|
break;
|
|
#ifdef HAS_SUSPEND
|
|
case 15:
|
|
#endif
|
|
case 10:
|
|
isdn3_setup_conn (conn, EST_CONNECT);
|
|
}
|
|
break;
|
|
}
|
|
|
|
if ((err = isdn3_at_send (conn, mb, 0)) != 0) {
|
|
freemsg (mb);
|
|
conn->lockit--;
|
|
setstate (conn, 99);
|
|
return err;
|
|
}
|
|
conn->lockit--;
|
|
return err;
|
|
}
|
|
|
|
|
|
static void
|
|
report_terminate (isdn3_conn conn, uchar_t * data, int len, ushort_t cause)
|
|
{
|
|
int err = 0;
|
|
|
|
mblk_t *mb = allocb (256, BPRI_MED);
|
|
|
|
if (mb == NULL) {
|
|
setstate (conn, 0);
|
|
return;
|
|
}
|
|
if(conn->state == 0 || conn->state == 99)
|
|
m_putid (mb, IND_DISCONNECT);
|
|
else
|
|
m_putid (mb, IND_DISCONNECTING);
|
|
if(cause != 0) {
|
|
m_putsx(mb,ARG_CAUSE);
|
|
m_putsx2(mb,cause);
|
|
}
|
|
conn_info (conn, mb);
|
|
if (data != NULL) {
|
|
report_addisplay (mb, data, len);
|
|
if(cause == 0)
|
|
report_addcause (mb, data, len);
|
|
report_addcost (mb, data, len);
|
|
}
|
|
if ((err = isdn3_at_send (conn, mb, 0)) != 0) {
|
|
freemsg (mb);
|
|
setstate (conn, 99);
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void
|
|
checkterm (isdn3_conn conn, uchar_t * data, int len)
|
|
{
|
|
if (conn->state == 0) {
|
|
report_terminate (conn, data, len,0);
|
|
isdn3_killconn (conn, 1); /* XXX */
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
N1_T313 (isdn3_conn conn)
|
|
{
|
|
if(log_34 & 2)printf ("Timer N1_T313\n");
|
|
conn->timerflags &= ~RUN_N1_T313;
|
|
switch (conn->state) {
|
|
case 8:
|
|
phone_sendback (conn, MT_N1_DISC, NULL);
|
|
setstate (conn, 11);
|
|
break;
|
|
}
|
|
checkterm (conn, NULL, 0);
|
|
}
|
|
|
|
#ifdef HAS_SUSPEND
|
|
static void
|
|
N1_T318 (isdn3_conn conn)
|
|
{
|
|
if(log_34 & 2)printf ("Timer N1_T318\n");
|
|
conn->timerflags &= ~RUN_N1_T318;
|
|
switch (conn->state) {
|
|
case 17:
|
|
/* Err */
|
|
setstate (conn, 99);
|
|
break;
|
|
}
|
|
checkterm (conn, NULL, 0);
|
|
}
|
|
|
|
#endif
|
|
|
|
static void
|
|
N1_T305 (isdn3_conn conn)
|
|
{
|
|
if(log_34 & 2)printf ("Timer N1_T305\n");
|
|
conn->timerflags &= ~RUN_N1_T305;
|
|
switch (conn->state) {
|
|
case 11:
|
|
/* Err */
|
|
phone_sendback (conn, MT_N1_REL, NULL);
|
|
setstate (conn, 19);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
N1_T3D1 (isdn3_conn conn)
|
|
{
|
|
if(log_34 & 2)printf ("Timer N1_T3D1\n");
|
|
conn->timerflags &= ~RUN_N1_T3D1;
|
|
switch (conn->state) {
|
|
case 20:
|
|
case 21:
|
|
/* Err */
|
|
phone_sendback (conn, MT_N1_REL, NULL);
|
|
setstate (conn, 19);
|
|
break;
|
|
}
|
|
checkterm (conn, NULL, 0);
|
|
}
|
|
|
|
static void
|
|
N1_T303 (isdn3_conn conn)
|
|
{
|
|
if(log_34 & 2)printf ("Timer N1_T303\n");
|
|
conn->timerflags &= ~RUN_N1_T303;
|
|
switch (conn->state) {
|
|
case 1:
|
|
/* Err */
|
|
send_disc(conn,0,NULL);
|
|
isdn3_setup_conn (conn, EST_DISCONNECT);
|
|
report_terminate (conn, NULL,0,ID_NOREPLY);
|
|
break;
|
|
}
|
|
checkterm (conn, NULL, 0);
|
|
}
|
|
|
|
static void
|
|
N1_T304 (isdn3_conn conn)
|
|
{
|
|
if(log_34 & 2)printf ("Timer N1_T304\n");
|
|
conn->timerflags &= ~RUN_N1_T304;
|
|
switch (conn->state) {
|
|
case 2:
|
|
/* Err */
|
|
phone_sendback (conn, MT_N1_DISC, NULL);
|
|
setstate (conn, 11);
|
|
break;
|
|
}
|
|
checkterm (conn, NULL, 0);
|
|
}
|
|
|
|
static void
|
|
N1_T310 (isdn3_conn conn)
|
|
{
|
|
if(log_34 & 2)printf ("Timer N1_T310\n");
|
|
conn->timerflags &= ~RUN_N1_T310;
|
|
switch (conn->state) {
|
|
case 3:
|
|
/* Err */
|
|
phone_sendback (conn, MT_N1_DISC, NULL);
|
|
setstate (conn, 11);
|
|
break;
|
|
}
|
|
checkterm (conn, NULL, 0);
|
|
}
|
|
|
|
static void
|
|
N1_T3D2 (isdn3_conn conn)
|
|
{
|
|
if(log_34 & 2)printf ("Timer N1_T3D2\n");
|
|
conn->timerflags &= ~RUN_N1_T3D2;
|
|
switch (conn->state) {
|
|
case 4:
|
|
case 7:
|
|
case 8:
|
|
case 10:
|
|
case 14:
|
|
case 12:
|
|
if (((struct t_info *)conn->p_data)->flags & FAC_PENDING) {
|
|
((struct t_info *)conn->p_data)->flags &= ~FAC_PENDING;
|
|
isdn3_setup_conn (conn, EST_NO_CHANGE);
|
|
}
|
|
break;
|
|
}
|
|
checkterm (conn, NULL, 0);
|
|
}
|
|
|
|
static void
|
|
N1_T308 (isdn3_conn conn)
|
|
{
|
|
if(log_34 & 2)printf ("Timer N1_T308\n");
|
|
conn->timerflags &= ~RUN_N1_T308;
|
|
switch (conn->state) {
|
|
case 19:
|
|
if (conn->timerflags & REP_T308) {
|
|
setstate (conn, 99);
|
|
} else {
|
|
conn->timerflags |= REP_T308;
|
|
phone_sendback (conn, MT_N1_REL, NULL);
|
|
timer (N1_T308, conn);
|
|
}
|
|
}
|
|
checkterm (conn, NULL, 0);
|
|
}
|
|
|
|
#ifdef HAS_SUSPEND
|
|
static void
|
|
N1_T319 (isdn3_conn conn)
|
|
{
|
|
if(log_34 & 2)printf ("Timer N1_T319\n");
|
|
conn->timerflags &= ~RUN_N1_T319;
|
|
switch (conn->state) {
|
|
case 15:
|
|
/* Err */
|
|
setstate (conn, 10);
|
|
break;
|
|
}
|
|
checkterm (conn, NULL, 0);
|
|
}
|
|
|
|
#endif
|
|
|
|
static void
|
|
release_postn1 (isdn3_conn conn, uchar_t minor, char force)
|
|
{
|
|
switch (conn->state) {
|
|
case 1:
|
|
untimer (N1_T303, conn);
|
|
if (force) {
|
|
/* technically an error */
|
|
}
|
|
break;
|
|
case 2:
|
|
untimer (N1_T304, conn);
|
|
if (force) {
|
|
/* technically an error */
|
|
}
|
|
break;
|
|
case 3:
|
|
untimer (N1_T310, conn);
|
|
if (force) {
|
|
/* technically an error */
|
|
}
|
|
break;
|
|
case 8:
|
|
untimer (N1_T313, conn);
|
|
/* FALL THRU */
|
|
case 4:
|
|
case 7:
|
|
case 10:
|
|
if (force) {
|
|
/* technically an error */
|
|
}
|
|
/* FALL THRU */
|
|
case 14:
|
|
untimer (N1_T3D2, conn);
|
|
break;
|
|
case 6:
|
|
break;
|
|
#ifdef HAS_SUSPEND
|
|
case 15:
|
|
untimer (N1_T319, conn);
|
|
if (force) {
|
|
/* technically an error */
|
|
}
|
|
break;
|
|
case 17:
|
|
untimer (N1_T318, conn);
|
|
if (force) {
|
|
/* technically an error */
|
|
}
|
|
break;
|
|
#endif
|
|
case 11:
|
|
untimer (N1_T305, conn);
|
|
if (!force) {
|
|
/* Technically an error */
|
|
force = 1;
|
|
}
|
|
case 12:
|
|
force = 1;
|
|
untimeout (N1_T3D2, conn);
|
|
break;
|
|
case 19:
|
|
/* Technically an error */
|
|
return;
|
|
case 20:
|
|
case 21:
|
|
untimer (N1_T3D1, conn);
|
|
break;
|
|
case 99:
|
|
return;
|
|
default:
|
|
setstate (conn, 99);
|
|
return;
|
|
}
|
|
if (force) {
|
|
phone_sendback (conn, MT_N1_REL, NULL);
|
|
switch (conn->state) {
|
|
#ifdef HAS_SUSPEND
|
|
case 15:
|
|
#endif
|
|
case 10:
|
|
case 4:
|
|
case 3:
|
|
case 2:
|
|
case 11:
|
|
isdn3_setup_conn (conn, EST_DISCONNECT);
|
|
}
|
|
conn->bchan = 0;
|
|
conn->minorstate &=~ MS_BCHAN;
|
|
setstate (conn, 19);
|
|
} else {
|
|
phone_sendback (conn, MT_N1_DISC, NULL);
|
|
setstate (conn, 11);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
N1_T3AA (isdn3_conn conn)
|
|
{
|
|
if(log_34 & 2)printf ("Timer N1_T3AA\n");
|
|
conn->timerflags &= ~RUN_N1_T3AA;
|
|
switch (conn->state) {
|
|
case 0:
|
|
/* Err */
|
|
break;
|
|
default:
|
|
if (conn->bchan != 0)
|
|
release_postn1 (conn, 0, 0);
|
|
}
|
|
checkterm (conn, NULL, 0);
|
|
}
|
|
|
|
static void N1_TFOO(isdn3_conn conn)
|
|
{
|
|
setstate(conn, 0);
|
|
checkterm (conn, NULL, 0);
|
|
}
|
|
|
|
static void
|
|
N1_TCONN (isdn3_conn conn)
|
|
{
|
|
if(log_34 & 2)printf ("Timer N1_TCONN\n");
|
|
conn->timerflags &= ~RUN_N1_TCONN;
|
|
conn->lockit++;
|
|
switch (conn->state) {
|
|
case 7: {
|
|
mblk_t *mb = NULL;
|
|
int qd_len = 0;
|
|
streamchar *qd_d;
|
|
if((mb = allocb(20,BPRI_LO)) != NULL) {
|
|
|
|
if ((qd_d = qd_insert ((uchar_t *) mb->b_rptr, &qd_len, 0, PT_N0_cause, 4, 1)) == NULL) {
|
|
freeb(mb);
|
|
mb = NULL;
|
|
} else {
|
|
if(!(conn->minorstate & MS_BCHAN))
|
|
*qd_d = N1_UserBusy;
|
|
else if(!(conn->minorstate & MS_SETUP_MASK))
|
|
*qd_d = N1_NumberChanged; /* XXX ;-) */
|
|
else
|
|
*qd_d = N1_OutOfOrder;
|
|
*qd_d |= 0x80;
|
|
mb->b_wptr = mb->b_rptr + qd_len;
|
|
}
|
|
}
|
|
if(send_disc (conn, 0, mb) != 0 && mb != NULL)
|
|
freemsg(mb);
|
|
goto term;
|
|
}
|
|
case 6:
|
|
setstate (conn, 99);
|
|
break;
|
|
}
|
|
term:
|
|
conn->lockit--;
|
|
checkterm (conn, NULL, 0);
|
|
}
|
|
|
|
static void
|
|
N1_TALERT (isdn3_conn conn)
|
|
{
|
|
if(log_34 & 2)printf ("Timer N1_TALERT\n");
|
|
conn->timerflags &= ~RUN_N1_TALERT;
|
|
conn->lockit++;
|
|
switch (conn->state) {
|
|
case 6:
|
|
{
|
|
mblk_t *asn = NULL;
|
|
int qd_len = 0;
|
|
uchar_t *qd_d;
|
|
|
|
if ((((struct t_info *)conn->p_data)->flags & SVC_PENDING) && (asn = allocb (32, BPRI_MED)) != NULL) {
|
|
if ((qd_d = qd_insert ((uchar_t *) asn->b_rptr, &qd_len, 0, PT_N0_netSpecFac, 4, 1)) == NULL) {
|
|
freeb(asn);
|
|
asn = NULL;
|
|
} else {
|
|
*(uchar_t *) qd_d++ = 0;
|
|
*(uchar_t *) qd_d++ = N1_FAC_SVC;
|
|
*(ushort_t *) qd_d = 0;
|
|
asn->b_wptr = asn->b_rptr + qd_len;
|
|
}
|
|
}
|
|
|
|
if(phone_sendback (conn, MT_N1_ALERT, asn) != 0 && asn != NULL)
|
|
freemsg(asn);
|
|
|
|
setstate (conn, 7);
|
|
}
|
|
break;
|
|
}
|
|
conn->lockit--;
|
|
checkterm (conn, NULL, 0);
|
|
}
|
|
|
|
static int
|
|
recv (isdn3_conn conn, uchar_t msgtype, char isUI, uchar_t * data, ushort_t len)
|
|
{
|
|
if (0)
|
|
printf (" N1: Recv %x in state %d\n", msgtype, conn->state);
|
|
if(conn->p_data == NULL) {
|
|
if((conn->p_data = malloc(sizeof(struct t_info))) == NULL) {
|
|
return -ENOMEM;
|
|
}
|
|
bzero(conn->p_data,sizeof(struct t_info));
|
|
}
|
|
switch (conn->state) {
|
|
case 0:
|
|
switch (msgtype) {
|
|
case MT_N1_SETUP:
|
|
conn->minorstate |= MS_INCOMING;
|
|
setstate (conn, 6);
|
|
|
|
(void) get_chanID (conn, data, len);
|
|
if (!get_serviceInd (conn, data, len)) {
|
|
setstate(conn,99);
|
|
goto pack_err;
|
|
}
|
|
if (isdn3_setup_conn (conn, EST_LISTEN) != 0)
|
|
goto pack_err;
|
|
get_nr (conn, data, len, PT_N0_origAddr);
|
|
get_eaz (conn, data, len, PT_N0_destAddr);
|
|
|
|
/*
|
|
* Check if transferred call. If we are forwarding this B channel
|
|
* to another device, ignore the call.
|
|
*/
|
|
{
|
|
isdn3_conn nconn;
|
|
|
|
QD_INIT (data, len)
|
|
break;
|
|
|
|
((struct t_info *)conn->p_data)->flags &=~ SVC_PENDING;
|
|
QD {
|
|
QD_CASE (0, PT_N0_netSpecFac):
|
|
if (qd_len < 4)
|
|
continue;
|
|
switch (qd_data[1]) {
|
|
case N1_FAC_SVC:
|
|
((struct t_info *)conn->p_data)->flags |= SVC_PENDING;
|
|
break;
|
|
case N1_FAC_DisplayUebergeben:
|
|
if (!(conn->minorstate & MS_BCHAN))
|
|
break;
|
|
for (nconn = conn->talk->conn; nconn != NULL; nconn = nconn->next)
|
|
if ((nconn->minorstate & MS_FORWARDING) && (nconn->minorstate & MS_BCHAN) && (nconn->bchan == conn->bchan))
|
|
goto out;
|
|
}
|
|
}
|
|
QD_EXIT;
|
|
}
|
|
{
|
|
long flags = isdn3_flags(conn->card->info,-1,-1);
|
|
if(flags & FL_ANS_IMMED) {
|
|
untimer(N1_TALERT,conn);
|
|
N1_TALERT(conn);
|
|
}
|
|
}
|
|
report_setup (conn, data, len);
|
|
break;
|
|
case MT_N1_CANC_ACK:
|
|
case MT_N1_CANC_REJ:
|
|
case MT_N1_REG_ACK:
|
|
case MT_N1_REG_REJ:
|
|
case MT_N1_SUSP_ACK:
|
|
case MT_N1_RES_REJ:
|
|
break;
|
|
case MT_N1_REL:
|
|
phone_sendback (conn, MT_N1_REL_ACK, NULL);
|
|
case MT_N1_REL_ACK:
|
|
break;
|
|
default:
|
|
phone_sendback (conn, MT_N1_REL, NULL);
|
|
setstate (conn, 19);
|
|
break;
|
|
}
|
|
break;
|
|
case 1:
|
|
switch (msgtype) {
|
|
case MT_N1_SETUP_ACK:
|
|
(void) get_chanID (conn, data, len);
|
|
if (isdn3_setup_conn (conn, EST_LISTEN) != 0)
|
|
goto pack_err;
|
|
report_setup_ack (conn, data, len);
|
|
setstate (conn, 2);
|
|
break;
|
|
case MT_N1_CALL_SENT:
|
|
(void) get_chanID (conn, data, len);
|
|
if (isdn3_setup_conn (conn, EST_LISTEN) != 0)
|
|
goto pack_err;
|
|
report_call_sent (conn, data, len);
|
|
setstate (conn, 3);
|
|
break;
|
|
case MT_N1_REL:
|
|
/* send REL up -- done when dropping out below */
|
|
phone_sendback (conn, MT_N1_REL_ACK, NULL);
|
|
setstate (conn, 0);
|
|
report_terminate (conn, data, len,0);
|
|
break;
|
|
case MT_N1_DISC:
|
|
isdn3_setup_conn (conn, EST_DISCONNECT);
|
|
(void)send_disc (conn, 1, NULL);
|
|
report_terminate (conn, data, len,0);
|
|
break;
|
|
case MT_N1_REL_ACK:
|
|
isdn3_setup_conn (conn, EST_DISCONNECT);
|
|
phone_sendback (conn, MT_N1_REL, NULL);
|
|
setstate (conn, 19);
|
|
report_terminate (conn, data, len,0);
|
|
break;
|
|
case MT_N1_SUSP_ACK:
|
|
case MT_N1_RES_REJ:
|
|
case MT_N1_REG_ACK:
|
|
case MT_N1_REG_REJ:
|
|
case MT_N1_CANC_ACK:
|
|
case MT_N1_CANC_REJ:
|
|
/* Fehlermeldung */
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case 2:
|
|
switch (msgtype) {
|
|
case MT_N1_CALL_SENT:
|
|
(void) get_chanID (conn, data, len);
|
|
if (isdn3_setup_conn (conn, EST_LISTEN) != 0)
|
|
goto pack_err;
|
|
report_call_sent (conn, data, len);
|
|
setstate (conn, 3);
|
|
break;
|
|
case MT_N1_ALERT:
|
|
report_alert (conn, data, len);
|
|
setstate (conn, 4);
|
|
break;
|
|
case MT_N1_CONN:
|
|
(void) get_chanID (conn, data, len);
|
|
if (!(conn->minorstate & MS_BCHAN))
|
|
goto pack_err;
|
|
get_serviceInd (conn, data, len);
|
|
if (isdn3_setup_conn (conn, EST_CONNECT) != 0)
|
|
goto pack_err;
|
|
report_conn (conn, data, len);
|
|
phone_sendback (conn, MT_N1_CONN_ACK, NULL);
|
|
setstate (conn, 10);
|
|
break;
|
|
case MT_N1_INFO:
|
|
{
|
|
QD_INIT (data, len) break;
|
|
report_info (conn, data, len);
|
|
QD {
|
|
QD_CASE (0, PT_N0_netSpecFac):
|
|
{
|
|
char nlen;
|
|
uchar_t facility;
|
|
|
|
if (qd_len == 0)
|
|
break;
|
|
nlen = *qd_data++;
|
|
if (qd_len < nlen + 1)
|
|
break;
|
|
qd_data += nlen;
|
|
facility = *qd_data++;
|
|
if (facility != N1_FAC_Forward1 && facility != N1_FAC_Forward2) {
|
|
setstate (conn, 3);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case MT_N1_REL:
|
|
/* send REL up */
|
|
phone_sendback (conn, MT_N1_REL, NULL);
|
|
setstate (conn, 99);
|
|
break;
|
|
case MT_N1_DISC:
|
|
isdn3_setup_conn (conn, EST_DISCONNECT);
|
|
(void)send_disc (conn, 1, NULL);
|
|
report_terminate (conn, data, len,0);
|
|
break;
|
|
case MT_N1_REL_ACK:
|
|
/* send REL_ACK up */
|
|
phone_sendback (conn, MT_N1_REL, NULL);
|
|
setstate (conn, 19);
|
|
break;
|
|
case MT_N1_SUSP_ACK:
|
|
case MT_N1_RES_REJ:
|
|
case MT_N1_REG_ACK:
|
|
case MT_N1_REG_REJ:
|
|
case MT_N1_CANC_ACK:
|
|
case MT_N1_CANC_REJ:
|
|
/* Fehlermeldung */
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case 3:
|
|
switch (msgtype) {
|
|
case MT_N1_ALERT:
|
|
report_alert (conn, data, len);
|
|
setstate (conn, 4);
|
|
break;
|
|
case MT_N1_CONN:
|
|
(void) get_chanID (conn, data, len);
|
|
if (!(conn->minorstate & MS_BCHAN))
|
|
goto pack_err;
|
|
if (isdn3_setup_conn (conn, EST_CONNECT) != 0)
|
|
goto pack_err;
|
|
report_conn (conn, data, len);
|
|
phone_sendback (conn, MT_N1_CONN_ACK, NULL);
|
|
setstate (conn, 10);
|
|
break;
|
|
case MT_N1_INFO:
|
|
report_info (conn, data, len);
|
|
setstate (conn, 3);
|
|
break;
|
|
case MT_N1_DISC:
|
|
isdn3_setup_conn (conn, EST_DISCONNECT);
|
|
(void)send_disc (conn, 1, NULL);
|
|
report_terminate (conn, data, len,0);
|
|
break;
|
|
case MT_N1_REL:
|
|
/* send REL up */
|
|
phone_sendback (conn, MT_N1_REL_ACK, NULL);
|
|
setstate (conn, 0);
|
|
break;
|
|
case MT_N1_REL_ACK:
|
|
/* send REL_ACK up */
|
|
untimer (N1_T310, conn);
|
|
phone_sendback (conn, MT_N1_REL, NULL);
|
|
setstate (conn, 19);
|
|
break;
|
|
case MT_N1_SUSP_ACK:
|
|
case MT_N1_RES_REJ:
|
|
case MT_N1_REG_ACK:
|
|
case MT_N1_REG_REJ:
|
|
case MT_N1_CANC_ACK:
|
|
case MT_N1_CANC_REJ:
|
|
/* Err */
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case 4:
|
|
switch (msgtype) {
|
|
case MT_N1_CONN:
|
|
(void) get_chanID (conn, data, len);
|
|
if (!(conn->minorstate & MS_BCHAN))
|
|
goto pack_err;
|
|
if (isdn3_setup_conn (conn, EST_CONNECT) != 0)
|
|
goto pack_err;
|
|
report_conn (conn, data, len);
|
|
phone_sendback (conn, MT_N1_CONN_ACK, NULL);
|
|
setstate (conn, 10);
|
|
break;
|
|
case MT_N1_FAC_ACK:
|
|
/* send FAC_ACK up */
|
|
untimer (N1_T3D2, conn);
|
|
break;
|
|
case MT_N1_FAC_REJ:
|
|
/* send FAC_REJ up */
|
|
untimer (N1_T3D2, conn);
|
|
break;
|
|
case MT_N1_ALERT:
|
|
report_alert (conn, data, len);
|
|
break;
|
|
case MT_N1_INFO:
|
|
report_info (conn, data, len);
|
|
break;
|
|
case MT_N1_REL:
|
|
/* send REL up */
|
|
phone_sendback (conn, MT_N1_REL_ACK, NULL);
|
|
setstate (conn, 0);
|
|
break;
|
|
case MT_N1_DISC:
|
|
isdn3_setup_conn (conn, EST_DISCONNECT);
|
|
(void)send_disc (conn, 1, NULL);
|
|
report_terminate (conn, data, len,0);
|
|
break;
|
|
case MT_N1_REL_ACK:
|
|
untimer (N1_T3D2, conn);
|
|
phone_sendback (conn, MT_N1_REL, NULL);
|
|
setstate (conn, 19);
|
|
break;
|
|
case MT_N1_SUSP_ACK:
|
|
case MT_N1_RES_REJ:
|
|
case MT_N1_REG_ACK:
|
|
case MT_N1_REG_REJ:
|
|
case MT_N1_CANC_ACK:
|
|
case MT_N1_CANC_REJ:
|
|
/* Fehlermeldung */
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case 6:
|
|
switch (msgtype) {
|
|
case MT_N1_SETUP:
|
|
break;
|
|
case MT_N1_REL:
|
|
phone_sendback (conn, MT_N1_REL_ACK, NULL);
|
|
setstate (conn, 99);
|
|
break;
|
|
case MT_N1_DISC:
|
|
isdn3_setup_conn (conn, EST_DISCONNECT);
|
|
(void)send_disc (conn, 1, NULL);
|
|
report_terminate (conn, data, len,0);
|
|
break;
|
|
case MT_N1_REL_ACK:
|
|
phone_sendback (conn, MT_N1_REL, NULL);
|
|
setstate (conn, 19);
|
|
break;
|
|
case MT_N1_SUSP_ACK:
|
|
case MT_N1_RES_REJ:
|
|
case MT_N1_REG_ACK:
|
|
case MT_N1_REG_REJ:
|
|
case MT_N1_CANC_ACK:
|
|
case MT_N1_CANC_REJ:
|
|
/* Fehlermeldung */
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case 7:
|
|
switch (msgtype) {
|
|
case MT_N1_SETUP:
|
|
(void) get_chanID (conn, data, len);
|
|
if (isdn3_setup_conn (conn, EST_LISTEN) != 0)
|
|
goto pack_err;
|
|
break;
|
|
case MT_N1_FAC_ACK:
|
|
/* send FAC_ACK up */
|
|
untimer (N1_T3D2, conn);
|
|
break;
|
|
case MT_N1_FAC_REJ:
|
|
/* send FAC_REJ up */
|
|
untimer (N1_T3D2, conn);
|
|
break;
|
|
case MT_N1_INFO:
|
|
report_info (conn, data, len);
|
|
break;
|
|
case MT_N1_STAT:
|
|
report_stat (conn, data, len);
|
|
break;
|
|
case MT_N1_REL:
|
|
/* send REL up */
|
|
phone_sendback (conn, MT_N1_REL_ACK, NULL);
|
|
setstate (conn, 99);
|
|
break;
|
|
case MT_N1_DISC:
|
|
isdn3_setup_conn (conn, EST_DISCONNECT);
|
|
(void)send_disc (conn, 1, NULL);
|
|
report_terminate (conn, data, len,0);
|
|
break;
|
|
case MT_N1_REL_ACK:
|
|
/* send REL_ACK up */
|
|
untimer (N1_T3D2, conn);
|
|
phone_sendback (conn, MT_N1_REL, NULL);
|
|
setstate (conn, 19);
|
|
break;
|
|
case MT_N1_SUSP_ACK:
|
|
case MT_N1_RES_REJ:
|
|
case MT_N1_REG_ACK:
|
|
case MT_N1_REG_REJ:
|
|
case MT_N1_CANC_ACK:
|
|
case MT_N1_CANC_REJ:
|
|
/* Fehlermeldung */
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case 8:
|
|
switch (msgtype) {
|
|
case MT_N1_CONN_ACK:
|
|
(void) get_chanID (conn, data, len);
|
|
if (!(conn->minorstate & MS_BCHAN))
|
|
goto pack_err;
|
|
if (isdn3_setup_conn (conn, EST_CONNECT) != 0)
|
|
goto pack_err;
|
|
report_conn_ack (conn, data, len);
|
|
setstate (conn, 10);
|
|
break;
|
|
case MT_N1_SETUP:
|
|
break;
|
|
case MT_N1_FAC_ACK:
|
|
/* send FAC_ACK up */
|
|
untimer (N1_T3D2, conn);
|
|
break;
|
|
case MT_N1_FAC_REJ:
|
|
/* send FAC_REJ up */
|
|
untimer (N1_T3D2, conn);
|
|
break;
|
|
case MT_N1_INFO:
|
|
report_info (conn, data, len);
|
|
break;
|
|
case MT_N1_STAT:
|
|
report_stat (conn, data, len);
|
|
break;
|
|
case MT_N1_REL:
|
|
/* send REL up */
|
|
phone_sendback (conn, MT_N1_REL_ACK, NULL);
|
|
setstate (conn, 0);
|
|
break;
|
|
case MT_N1_DISC:
|
|
isdn3_setup_conn (conn, EST_DISCONNECT);
|
|
(void)send_disc (conn, 1, NULL);
|
|
report_terminate (conn, data, len,0);
|
|
break;
|
|
case MT_N1_REL_ACK:
|
|
/* send REL_ACK up */
|
|
phone_sendback (conn, MT_N1_REL, NULL);
|
|
setstate (conn, 19);
|
|
break;
|
|
case MT_N1_SUSP_ACK:
|
|
case MT_N1_RES_REJ:
|
|
case MT_N1_REG_ACK:
|
|
case MT_N1_REG_REJ:
|
|
case MT_N1_CANC_ACK:
|
|
case MT_N1_CANC_REJ:
|
|
/* Fehlermeldung */
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case 10:
|
|
switch (msgtype) {
|
|
case MT_N1_SETUP:
|
|
break;
|
|
case MT_N1_FAC:
|
|
/* send FAC up */
|
|
break;
|
|
case MT_N1_FAC_ACK:
|
|
/* send FAC_ACK up */
|
|
untimer (N1_T3D2, conn);
|
|
break;
|
|
case MT_N1_FAC_REJ:
|
|
/* send FAC_REJ up */
|
|
untimer (N1_T3D2, conn);
|
|
break;
|
|
case MT_N1_INFO:
|
|
report_info (conn, data, len);
|
|
break;
|
|
case MT_N1_STAT:
|
|
report_stat (conn, data, len);
|
|
break;
|
|
case MT_N1_USER_INFO:
|
|
report_user_info (conn, data, len);
|
|
break;
|
|
case MT_N1_CON_CON:
|
|
/* send CON_CON up */
|
|
break;
|
|
case MT_N1_REL:
|
|
/* send REL up */
|
|
phone_sendback (conn, MT_N1_REL_ACK, NULL);
|
|
setstate (conn, 0);
|
|
break;
|
|
case MT_N1_DISC:
|
|
setstate (conn, 12);
|
|
isdn3_setup_conn (conn, EST_DISCONNECT);
|
|
(void)send_disc (conn, 1, NULL);
|
|
report_terminate (conn, data, len,0);
|
|
break;
|
|
case MT_N1_REL_ACK:
|
|
/* send REL_ACK up */
|
|
phone_sendback (conn, MT_N1_REL, NULL);
|
|
setstate (conn, 19);
|
|
break;
|
|
case MT_N1_SUSP_ACK:
|
|
/* Fehler */
|
|
break;
|
|
case MT_N1_RES_REJ:
|
|
case MT_N1_REG_ACK:
|
|
case MT_N1_REG_REJ:
|
|
case MT_N1_CANC_ACK:
|
|
case MT_N1_CANC_REJ:
|
|
/* Fehlermeldung */
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case 14:
|
|
switch (msgtype) {
|
|
case MT_N1_SETUP:
|
|
break;
|
|
case MT_N1_FAC_ACK:
|
|
/* send FAC_ACK up */
|
|
untimer (N1_T3D2, conn);
|
|
break;
|
|
case MT_N1_FAC_REJ:
|
|
/* send FAC_REJ up */
|
|
untimer (N1_T3D2, conn);
|
|
break;
|
|
case MT_N1_INFO:
|
|
report_info (conn, data, len);
|
|
break;
|
|
case MT_N1_STAT:
|
|
report_stat (conn, data, len);
|
|
break;
|
|
case MT_N1_CONN_ACK:
|
|
(void) get_chanID (conn, data, len);
|
|
if (!(conn->minorstate & MS_BCHAN))
|
|
goto pack_err;
|
|
if (isdn3_setup_conn (conn, EST_CONNECT) != 0)
|
|
goto pack_err;
|
|
report_conn_ack (conn, data, len);
|
|
setstate (conn, 10);
|
|
break;
|
|
case MT_N1_REL:
|
|
/* send REL up */
|
|
phone_sendback (conn, MT_N1_REL_ACK, NULL);
|
|
setstate (conn, 0);
|
|
break;
|
|
case MT_N1_DISC:
|
|
isdn3_setup_conn (conn, EST_DISCONNECT);
|
|
(void)send_disc (conn, 1, NULL);
|
|
report_terminate (conn, data, len,0);
|
|
break;
|
|
case MT_N1_REL_ACK:
|
|
phone_sendback (conn, MT_N1_REL, NULL);
|
|
setstate (conn, 19);
|
|
break;
|
|
case MT_N1_SUSP_ACK:
|
|
case MT_N1_RES_REJ:
|
|
case MT_N1_REG_ACK:
|
|
case MT_N1_REG_REJ:
|
|
case MT_N1_CANC_ACK:
|
|
case MT_N1_CANC_REJ:
|
|
/* Fehlermeldung */
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
#ifdef HAS_SUSPEND
|
|
case 15:
|
|
switch (msgtype) {
|
|
case MT_N1_SETUP:
|
|
break;
|
|
case MT_N1_SUSP_ACK:
|
|
/* send SUSP_ACK up */
|
|
setstate (conn, 99);
|
|
break;
|
|
case MT_N1_SUSP_REJ:
|
|
/* send SUSP_REJ up */
|
|
setstate (conn, 10);
|
|
break;
|
|
case MT_N1_INFO:
|
|
report_info (conn, data, len);
|
|
break;
|
|
case MT_N1_STAT:
|
|
report_stat (conn, data, len);
|
|
break;
|
|
case MT_N1_REL:
|
|
/* send REL up */
|
|
phone_sendback (conn, MT_N1_REL_ACK, NULL);
|
|
setstate (conn, 0);
|
|
break;
|
|
case MT_N1_DISC:
|
|
isdn3_setup_conn (conn, EST_DISCONNECT);
|
|
(void)send_disc (conn, 1, NULL);
|
|
report_terminate (conn, data, len,0);
|
|
break;
|
|
case MT_N1_REL_ACK:
|
|
/* send REL_ACK up */
|
|
phone_sendback (conn, MT_N1_REL, NULL);
|
|
setstate (conn, 19);
|
|
break;
|
|
case MT_N1_RES_REJ:
|
|
case MT_N1_REG_ACK:
|
|
case MT_N1_REG_REJ:
|
|
case MT_N1_CANC_ACK:
|
|
case MT_N1_CANC_REJ:
|
|
/* Fehlermeldung */
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case 17:
|
|
switch (msgtype) {
|
|
case MT_N1_RES_ACK:
|
|
/* send RES_ACK up */
|
|
(void) get_chanID (conn, data, len);
|
|
if (isdn3_setup_conn (conn, EST_CONNECT) != 0)
|
|
goto pack_err;
|
|
setstate (conn, 10);
|
|
break;
|
|
case MT_N1_RES_REJ:
|
|
/* send RES_REJ up */
|
|
setstate (conn, 99);
|
|
break;
|
|
case MT_N1_REL:
|
|
/* send REL up */
|
|
phone_sendback (conn, MT_N1_REL_ACK, NULL);
|
|
setstate (conn, 0);
|
|
break;
|
|
case MT_N1_REL_ACK:
|
|
/* send REL_ACK up */
|
|
goto common_17_REL;
|
|
case MT_N1_DISC:
|
|
isdn3_setup_conn (conn, EST_DISCONNECT);
|
|
common_17_REL:
|
|
phone_sendback (conn, MT_N1_REL, NULL);
|
|
setstate (conn, 19);
|
|
report_terminate (conn, data, len,0);
|
|
break;
|
|
case MT_N1_SUSP_ACK:
|
|
case MT_N1_REG_ACK:
|
|
case MT_N1_REG_REJ:
|
|
case MT_N1_CANC_ACK:
|
|
case MT_N1_CANC_REJ:
|
|
/* Fehlermeldung */
|
|
setstate (conn, 4);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
#endif
|
|
case 11:
|
|
switch (msgtype) {
|
|
case MT_N1_SETUP:
|
|
break;
|
|
case MT_N1_REL:
|
|
/* send REL up */
|
|
phone_sendback (conn, MT_N1_REL_ACK, NULL);
|
|
setstate (conn, 0);
|
|
break;
|
|
case MT_N1_SUSP_ACK:
|
|
/* xxx */
|
|
break;
|
|
case MT_N1_FAC_ACK:
|
|
/* send FAC_ACK up */
|
|
break;
|
|
case MT_N1_FAC_REJ:
|
|
/* send FAC_REJ up */
|
|
break;
|
|
case MT_N1_INFO:
|
|
report_info (conn, data, len);
|
|
break;
|
|
case MT_N1_STAT:
|
|
report_stat (conn, data, len);
|
|
break;
|
|
case MT_N1_REL_ACK:
|
|
/* send REL_ACK up */
|
|
/* Release B chan */
|
|
phone_sendback (conn, MT_N1_REL, NULL);
|
|
setstate (conn, 19);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case 12:
|
|
switch (msgtype) {
|
|
case MT_N1_SETUP:
|
|
break;
|
|
case MT_N1_REL:
|
|
/* send REL up */
|
|
phone_sendback (conn, MT_N1_REL_ACK, NULL);
|
|
setstate (conn, 0);
|
|
break;
|
|
case MT_N1_FAC_ACK:
|
|
/* send FAC_ACK up */
|
|
untimer (N1_T3D2, conn);
|
|
break;
|
|
case MT_N1_FAC_REJ:
|
|
/* send FAC_REJ up */
|
|
untimer (N1_T3D2, conn);
|
|
break;
|
|
case MT_N1_INFO:
|
|
report_info (conn, data, len);
|
|
break;
|
|
case MT_N1_STAT:
|
|
report_stat (conn, data, len);
|
|
break;
|
|
case MT_N1_REL_ACK:
|
|
/* send REL_ACK up */
|
|
phone_sendback (conn, MT_N1_REL, NULL);
|
|
setstate (conn, 19);
|
|
break;
|
|
case MT_N1_SUSP_ACK:
|
|
case MT_N1_RES_REJ:
|
|
case MT_N1_REG_ACK:
|
|
case MT_N1_REG_REJ:
|
|
case MT_N1_CANC_ACK:
|
|
case MT_N1_CANC_REJ:
|
|
/* Fehlermeldung */
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case 19:
|
|
switch (msgtype) {
|
|
case MT_N1_SETUP:
|
|
break;
|
|
case MT_N1_REL:
|
|
/* send REL up */
|
|
setstate (conn, 99);
|
|
break;
|
|
case MT_N1_REL_ACK:
|
|
/* send REL_ACK up */
|
|
setstate (conn, 0);
|
|
break;
|
|
case MT_N1_FAC_ACK:
|
|
/* send FAC_ACK up */
|
|
break;
|
|
case MT_N1_FAC_REJ:
|
|
/* send FAC_REJ up */
|
|
break;
|
|
case MT_N1_INFO:
|
|
report_info (conn, data, len);
|
|
break;
|
|
case MT_N1_STAT:
|
|
report_stat (conn, data, len);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case 20:
|
|
switch (msgtype) {
|
|
case MT_N1_REL:
|
|
/* send REL up */
|
|
phone_sendback (conn, MT_N1_REL_ACK, NULL);
|
|
setstate (conn, 0);
|
|
break;
|
|
case MT_N1_REG_ACK:
|
|
/* send REG_ACK up */
|
|
setstate (conn, 99);
|
|
break;
|
|
case MT_N1_REG_REJ:
|
|
/* send REG_REJ up */
|
|
setstate (conn, 99);
|
|
break;
|
|
case MT_N1_DISC:
|
|
isdn3_setup_conn (conn, EST_DISCONNECT);
|
|
goto common_20_REL_ACK;
|
|
case MT_N1_REL_ACK:
|
|
/* send REL_ACK up */
|
|
common_20_REL_ACK:
|
|
phone_sendback (conn, MT_N1_REL, NULL);
|
|
setstate (conn, 19);
|
|
report_terminate (conn, data, len,0);
|
|
break;
|
|
case MT_N1_SUSP_ACK:
|
|
case MT_N1_RES_REJ:
|
|
case MT_N1_CANC_ACK:
|
|
case MT_N1_CANC_REJ:
|
|
/* Fehlermeldung */
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case 21:
|
|
switch (msgtype) {
|
|
case MT_N1_REL:
|
|
/* send REL up */
|
|
phone_sendback (conn, MT_N1_REL_ACK, NULL);
|
|
setstate (conn, 0);
|
|
break;
|
|
case MT_N1_CANC_ACK:
|
|
/* send CANC_ACK up */
|
|
setstate (conn, 99);
|
|
break;
|
|
case MT_N1_CANC_REJ:
|
|
/* send CANC_REJ up */
|
|
setstate (conn, 99);
|
|
break;
|
|
case MT_N1_DISC:
|
|
isdn3_setup_conn (conn, EST_DISCONNECT);
|
|
goto common_21_REL_ACK;
|
|
case MT_N1_REL_ACK:
|
|
/* send REL_ACK up */
|
|
common_21_REL_ACK:
|
|
phone_sendback (conn, MT_N1_REL, NULL);
|
|
setstate (conn, 19);
|
|
report_terminate (conn, data, len,0);
|
|
break;
|
|
case MT_N1_SUSP_ACK:
|
|
case MT_N1_RES_REJ:
|
|
case MT_N1_REG_ACK:
|
|
case MT_N1_REG_REJ:
|
|
/* Fehlermeldung */
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case 99:
|
|
break;
|
|
default:
|
|
setstate (conn, 99);
|
|
break;
|
|
}
|
|
out:
|
|
checkterm (conn, data, len);
|
|
return 0;
|
|
pack_err:
|
|
release_postn1 (conn, 0, 1);
|
|
goto out;
|
|
}
|
|
|
|
static int
|
|
chstate (isdn3_conn conn, uchar_t ind, short add)
|
|
{
|
|
if(0)printf ("PHONE state for card %d says %d:%o\n", conn->card->nr, ind, add);
|
|
if(conn->p_data == NULL) {
|
|
if((conn->p_data = malloc(sizeof(struct t_info))) == NULL) {
|
|
return -ENOMEM;
|
|
}
|
|
bzero(conn->p_data,sizeof(struct t_info));
|
|
}
|
|
switch (ind) {
|
|
case DL_ESTABLISH_IND:
|
|
case DL_ESTABLISH_CONF:
|
|
if (conn->talk->state & PHONE_UP) { /* Reestablishment */
|
|
switch (conn->state) {
|
|
case 1:
|
|
case 3:
|
|
case 4:
|
|
case 8:
|
|
case 10:
|
|
#ifdef HAS_SUSPEND
|
|
case 15:
|
|
case 17:
|
|
#endif
|
|
case 12:
|
|
case 20:
|
|
case 21:
|
|
/* Error */
|
|
/* FALL THRU */
|
|
case 11:
|
|
case 19:
|
|
break;
|
|
case 2:
|
|
/* Error */
|
|
phone_sendback (conn, MT_N1_DISC, NULL);
|
|
setstate (conn, 11);
|
|
break;
|
|
case 7:
|
|
if (0) { /* Last MSG war ALERT */
|
|
case 14:
|
|
untimer (N1_T3D2, conn);
|
|
phone_sendback (conn, MT_N1_DISC, NULL);
|
|
timer (N1_T305, conn);
|
|
} else {
|
|
/* Error */
|
|
}
|
|
break;
|
|
}
|
|
checkterm (conn, NULL, 0);
|
|
} else
|
|
phone_timerup (conn);
|
|
break;
|
|
case MDL_ERROR_IND:
|
|
if(!(add & ERR_G))
|
|
break;
|
|
/* FALL THRU */
|
|
case DL_RELEASE_IND:
|
|
case DL_RELEASE_CONF:
|
|
case PH_DEACTIVATE_CONF:
|
|
case PH_DEACTIVATE_IND:
|
|
case PH_DISCONNECT_IND:
|
|
setstate (conn, 99);
|
|
checkterm (conn, NULL, 0);
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
send_disc (isdn3_conn conn, char release, mblk_t * data)
|
|
{
|
|
int err = 0, err2;
|
|
|
|
switch (conn->state) {
|
|
case 0:
|
|
break;
|
|
#ifdef HAS_SUSPEND
|
|
case 17:
|
|
#endif
|
|
case 14:
|
|
case 20:
|
|
case 21:
|
|
case 8:
|
|
common_off2:
|
|
if ((err = phone_sendback (conn, MT_N1_DISC, data)) == 0)
|
|
data = NULL;
|
|
if (release) {
|
|
case 6:
|
|
case 7:
|
|
#if 1
|
|
if (release > 1) {
|
|
release = 0;
|
|
goto common_off2;
|
|
}
|
|
#endif
|
|
if ((err2 = phone_sendback (conn, MT_N1_REL, data)) != 0)
|
|
err = err2;
|
|
setstate (conn, 19);
|
|
} else {
|
|
setstate (conn, 11);
|
|
}
|
|
break;
|
|
case 11:
|
|
if (release) {
|
|
goto common_off_noconn;
|
|
} else
|
|
return -EBUSY;
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
#ifdef HAS_SUSPEND
|
|
case 15:
|
|
#endif
|
|
case 4:
|
|
case 10:
|
|
/* common_off: */
|
|
if ((err = phone_sendback (conn, MT_N1_DISC, data)) == 0)
|
|
data = NULL;
|
|
if (!release)
|
|
setstate (conn, 11);
|
|
else
|
|
setstate (conn, 12);
|
|
break; /* NO FALL THRU */
|
|
case 12:
|
|
common_off_noconn:
|
|
/* B-Kanal trennen */
|
|
if ((err2 = phone_sendback (conn, MT_N1_REL, data)) != 0)
|
|
err = err2;
|
|
setstate (conn, 19);
|
|
break;
|
|
case 19:
|
|
break;
|
|
}
|
|
return err;
|
|
}
|
|
|
|
static int
|
|
sendcmd (isdn3_conn conn, ushort_t id, mblk_t * data)
|
|
{
|
|
streamchar *oldpos = data->b_rptr;
|
|
ulong_t service = ~0;
|
|
int err = 0;
|
|
ushort_t typ;
|
|
char suppress = 0;
|
|
char svc = 0;
|
|
char doforce = 0;
|
|
char donodisc = 0;
|
|
long cause = -1;
|
|
|
|
if(conn->p_data == NULL) {
|
|
if((conn->p_data = malloc(sizeof(struct t_info))) == NULL) {
|
|
return -ENOMEM;
|
|
}
|
|
bzero(conn->p_data,sizeof(struct t_info));
|
|
}
|
|
if(data != NULL) {
|
|
while (m_getsx (data, &typ) == 0) {
|
|
switch (typ) {
|
|
case ARG_FASTDROP:
|
|
if (conn->state == 6 || conn->state == 7 ||
|
|
conn->state == 8)
|
|
doforce = 1;
|
|
break;
|
|
case ARG_CAUSE:
|
|
{
|
|
ushort_t causeid;
|
|
|
|
if (m_getid (data, &causeid) != 0)
|
|
break;
|
|
cause = n1_idtocause(causeid);
|
|
}
|
|
break;
|
|
case ARG_FORCE:
|
|
doforce = 1;
|
|
break;
|
|
case ARG_NODISC:
|
|
donodisc = 1;
|
|
break;
|
|
case ARG_SUPPRESS:
|
|
suppress = 1;
|
|
break;
|
|
case ARG_SPV:
|
|
svc = 1;
|
|
break;
|
|
case ARG_SERVICE:
|
|
if ((err = m_getx (data, &service)) != 0) {
|
|
data->b_rptr = oldpos;
|
|
return err;
|
|
}
|
|
break;
|
|
case ARG_NUMBER:
|
|
m_getskip (data);
|
|
if ((err = m_getstr (data, (char *) ((struct t_info *)conn->p_data)->nr, MAXNR)) != 0) {
|
|
printf("GetStr Number: ");
|
|
return err;
|
|
}
|
|
break;
|
|
case ARG_LNUMBER:
|
|
{
|
|
char nbuf[MAXNR];
|
|
m_getskip (data);
|
|
if ((err = m_getstr (data, nbuf, MAXNR)) != 0) {
|
|
printf("GetX EAZans: ");
|
|
return err;
|
|
}
|
|
((struct t_info *)conn->p_data)->eaz = nbuf[strlen(nbuf)-1];
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
conn->lockit++;
|
|
switch (id) {
|
|
case CMD_DIAL:
|
|
{
|
|
if (data == NULL) {
|
|
printf("DataNull: ");
|
|
conn->lockit--;
|
|
return -EINVAL;
|
|
}
|
|
/* end_arg_dial: */
|
|
if (service == ~0) {
|
|
if(log_34 & 2)printf("No Service: ");
|
|
conn->lockit--;
|
|
return -EINVAL;
|
|
}
|
|
|
|
conn->minorstate |= MS_OUTGOING | MS_WANTCONN;
|
|
|
|
conn->lockit++;
|
|
isdn3_setup_conn (conn, EST_SETUP);
|
|
conn->lockit--;
|
|
|
|
switch (conn->state) {
|
|
case 0:
|
|
if (conn->minor == 0) {
|
|
printf("ConnMinorZero: ");
|
|
conn->lockit--;
|
|
return -ENOENT;
|
|
}
|
|
{
|
|
mblk_t *asn = allocb (256, BPRI_MED);
|
|
int qd_len = 0;
|
|
uchar_t *qd_d;
|
|
|
|
if (asn == NULL) {
|
|
conn->lockit--;
|
|
return -ENOMEM;
|
|
}
|
|
|
|
if (suppress) {
|
|
if ((qd_d = qd_insert ((uchar_t *) asn->b_rptr, &qd_len, 0, PT_N0_netSpecFac, 4, 1)) == NULL) {
|
|
conn->lockit--;
|
|
return -EIO;
|
|
}
|
|
*(uchar_t *) qd_d++ = 0;
|
|
*(uchar_t *) qd_d++ = N1_FAC_Unterdruecke;
|
|
*(ushort_t *) qd_d = 0;
|
|
}
|
|
if (svc) {
|
|
if ((qd_d = qd_insert ((uchar_t *) asn->b_rptr, &qd_len, 0, PT_N0_netSpecFac, 4, 1)) == NULL) {
|
|
conn->lockit--;
|
|
return -EIO;
|
|
}
|
|
*(uchar_t *) qd_d++ = 0;
|
|
*(uchar_t *) qd_d++ = N1_FAC_SVC;
|
|
*(ushort_t *) qd_d = 0;
|
|
if ((qd_d = qd_insert ((uchar_t *) asn->b_rptr, &qd_len, 0, PT_N0_netSpecFac, 4, 1)) == NULL) {
|
|
conn->lockit--;
|
|
return -EIO;
|
|
}
|
|
*(uchar_t *) qd_d++ = 0;
|
|
*(uchar_t *) qd_d++ = N1_FAC_Activate;
|
|
*(ushort_t *) qd_d = 0;
|
|
}
|
|
if ((qd_d = qd_insert ((uchar_t *) asn->b_rptr, &qd_len, 6, PT_N6_serviceInd, 2, 0)) == NULL) {
|
|
conn->lockit--;
|
|
return -EIO;
|
|
}
|
|
*((uchar_t *) qd_d) = service >> 8;
|
|
*(((uchar_t *) qd_d)+1) = service & 0xFF;
|
|
if (((struct t_info *)conn->p_data)->eaz != 0) {
|
|
if ((qd_d = qd_insert ((uchar_t *) asn->b_rptr, &qd_len, 0, PT_N0_origAddr, 2, 0)) == NULL) {
|
|
conn->lockit--;
|
|
return -EIO;
|
|
}
|
|
*qd_d++ = 0x81;
|
|
*qd_d++ = ((struct t_info *)conn->p_data)->eaz;
|
|
}
|
|
if (((struct t_info *)conn->p_data)->nr[0] != '\0') {
|
|
int i;
|
|
|
|
for (i = 0; i < MAXNR; i++)
|
|
if (((struct t_info *)conn->p_data)->nr[i] == '\0')
|
|
break;
|
|
if ((qd_d = qd_insert ((uchar_t *) asn->b_rptr, &qd_len, 0, PT_N0_destAddr, i + 1, 0)) == NULL) {
|
|
conn->lockit--;
|
|
return -EIO;
|
|
}
|
|
*qd_d++ = 0x81;
|
|
while (i--)
|
|
qd_d[i] = ((struct t_info *)conn->p_data)->nr[i];
|
|
}
|
|
if (conn->bchan != 0) {
|
|
if ((qd_d = qd_insert ((uchar_t *) asn->b_rptr, &qd_len, 0, PT_N0_chanID, (conn->bchan <= 2) ? 1 : 3, 0)) == NULL) {
|
|
conn->lockit--;
|
|
return -EIO;
|
|
}
|
|
if (conn->bchan <= 2) {
|
|
*qd_d = 0x80 | conn->bchan;
|
|
} else {
|
|
*qd_d++ = 0xA1;
|
|
*qd_d++ = 0xC3;
|
|
*qd_d++ = conn->bchan;
|
|
}
|
|
conn->bchan = 0; /* Network will tell us which
|
|
* to use */
|
|
}
|
|
/* NSF: SemiPerm etc. */
|
|
asn->b_wptr = asn->b_rptr + qd_len;
|
|
if ((err = phone_sendback (conn, MT_N1_SETUP, asn)) != 0) {
|
|
freeb (asn);
|
|
printf("SendBack: ");
|
|
conn->lockit--;
|
|
return err;
|
|
}
|
|
setstate (conn, 1);
|
|
}
|
|
break;
|
|
default:
|
|
printf("Default %d: ", conn->state);
|
|
conn->lockit--;
|
|
return -EBUSY;
|
|
}
|
|
}
|
|
break;
|
|
case CMD_PREPANSWER:
|
|
switch (conn->state) {
|
|
case 6: {
|
|
mblk_t *asn = NULL;
|
|
int qd_len = 0;
|
|
uchar_t *qd_d;
|
|
setstate (conn, 7);
|
|
|
|
if ((((struct t_info *)conn->p_data)->flags & SVC_PENDING) && (asn = allocb (32, BPRI_MED)) != NULL) {
|
|
if ((qd_d = qd_insert ((uchar_t *) asn->b_rptr, &qd_len, 0, PT_N0_netSpecFac, 4, 1)) == NULL) {
|
|
freeb(asn);
|
|
asn = NULL;
|
|
} else {
|
|
*(uchar_t *) qd_d++ = 0;
|
|
*(uchar_t *) qd_d++ = N1_FAC_SVC;
|
|
*(ushort_t *) qd_d = 0;
|
|
asn->b_wptr = asn->b_rptr + qd_len;
|
|
}
|
|
}
|
|
|
|
if(phone_sendback (conn, MT_N1_ALERT, asn) != 0 && asn != NULL)
|
|
freemsg(asn);
|
|
|
|
} break;
|
|
default:
|
|
printf("BadState1: ");
|
|
err = -EINVAL;
|
|
}
|
|
break;
|
|
case CMD_ANSWER:
|
|
{
|
|
mblk_t *asn = NULL;
|
|
|
|
if (data != NULL) {
|
|
int qd_len = 0;
|
|
uchar_t *qd_d;
|
|
|
|
if ((asn = allocb (32, BPRI_MED)) == NULL) {
|
|
conn->lockit--;
|
|
return -ENOMEM;
|
|
}
|
|
|
|
if (((struct t_info *)conn->p_data)->flags & SVC_PENDING) {
|
|
if ((qd_d = qd_insert ((uchar_t *) asn->b_rptr, &qd_len, 0, PT_N0_netSpecFac, 4, 1)) == NULL) {
|
|
freeb(asn);
|
|
conn->lockit--;
|
|
return -EIO;
|
|
}
|
|
*(uchar_t *) qd_d++ = 0;
|
|
*(uchar_t *) qd_d++ = N1_FAC_SVC;
|
|
*(ushort_t *) qd_d = 0;
|
|
if ((qd_d = qd_insert ((uchar_t *) asn->b_rptr, &qd_len, 0, PT_N0_netSpecFac, 4, 1)) == NULL) {
|
|
freeb(asn);
|
|
conn->lockit--;
|
|
return -EIO;
|
|
}
|
|
*(uchar_t *) qd_d++ = 0;
|
|
*(uchar_t *) qd_d++ = N1_FAC_Activate;
|
|
*(ushort_t *) qd_d = 0;
|
|
}
|
|
|
|
if ((qd_d = qd_insert ((uchar_t *) asn->b_rptr, &qd_len, 6, PT_N6_serviceInd, 2, 0)) == NULL) {
|
|
freeb (asn);
|
|
conn->lockit--;
|
|
return -EIO;
|
|
}
|
|
*((uchar_t *) qd_d) = service >> 8;
|
|
*(((uchar_t *) qd_d)+1) = service & 0xFF;
|
|
if (((struct t_info *)conn->p_data)->eaz != 0) {
|
|
if ((qd_d = qd_insert ((uchar_t *) asn->b_rptr, &qd_len, 0, PT_N0_origAddr, 2, 0)) == NULL) {
|
|
conn->lockit--;
|
|
return -EIO;
|
|
}
|
|
*qd_d++ = 0x81;
|
|
*qd_d++ = ((struct t_info *)conn->p_data)->eaz;
|
|
}
|
|
asn->b_wptr = asn->b_rptr + qd_len;
|
|
}
|
|
switch (conn->state) {
|
|
case 6:
|
|
case 7:
|
|
break;
|
|
default:
|
|
printf("BadState2 ");
|
|
err = -EINVAL;
|
|
if(asn != NULL)
|
|
freemsg(asn);
|
|
goto ex;
|
|
}
|
|
conn->minorstate |= MS_WANTCONN;
|
|
|
|
isdn3_setup_conn (conn, EST_SETUP);
|
|
|
|
if (((conn->delay > 0) && (conn->minorstate & MS_DELAYING))
|
|
|| !(conn->minorstate & MS_INITPROTO)
|
|
/* || !(conn->minorstate & MS_BCHAN) */ ) {
|
|
data->b_rptr = oldpos;
|
|
isdn3_repeat (conn, id, data);
|
|
if (asn != NULL)
|
|
freemsg (asn);
|
|
conn->lockit--;
|
|
return 0;
|
|
}
|
|
setstate (conn, 8);
|
|
if ((err = phone_sendback (conn, MT_N1_CONN, asn)) == 0)
|
|
asn = NULL;
|
|
isdn3_setup_conn (conn, EST_LISTEN);
|
|
if (asn != NULL)
|
|
freemsg (asn);
|
|
}
|
|
ex:
|
|
break;
|
|
#if 0
|
|
case CMD_FORWARD:
|
|
{
|
|
mblk_t *asn = NULL;
|
|
char donum = 0;
|
|
char gotservice = 0;
|
|
char eaz = 0;
|
|
char eaz2 = 0;
|
|
|
|
service = ((struct t_info *)conn->p_data)->service;
|
|
|
|
if (data == NULL) {
|
|
conn->lockit--;
|
|
return -ENOENT;
|
|
}
|
|
isdn3_setup_conn (conn, EST_NO_CHANGE);
|
|
|
|
if (((conn->delay > 0) && (conn->minorstate & MS_DELAYING))
|
|
|| !(conn->minorstate & MS_INITPROTO)
|
|
|| !(conn->minorstate & MS_BCHAN)
|
|
|| (((struct t_info *)conn->p_data)->flags & FAC_PENDING)) {
|
|
data->b_rptr = oldpos;
|
|
isdn3_repeat (conn, id, data);
|
|
conn->lockit--;
|
|
return 0;
|
|
}
|
|
if ((conn->minorstate & MS_CONN_MASK) == MS_CONN_NONE) {
|
|
printf("NoConnThere ");
|
|
conn->lockit--;
|
|
return -EINVAL;
|
|
}
|
|
if ((conn->minorstate & MS_CONN_MASK) != MS_CONN_INTERRUPT) {
|
|
isdn3_setup_conn (conn, EST_WILL_INTERRUPT);
|
|
data->b_rptr = oldpos;
|
|
isdn3_repeat (conn, id, data);
|
|
conn->lockit--;
|
|
return 0;
|
|
}
|
|
{
|
|
int qd_len = 0;
|
|
uchar_t *qd_d;
|
|
|
|
if ((asn = allocb (32, BPRI_MED)) == NULL) {
|
|
conn->lockit--;
|
|
return -ENOMEM;
|
|
}
|
|
|
|
if ((qd_d = qd_insert ((uchar_t *) asn->b_rptr, &qd_len, 0, PT_N0_netSpecFac, (gotservice || eaz2 != 0) ? ((eaz != 0 || eaz2 != 0) ? 6 : 4) : (eaz != 0) ? 5 : 4, 0)) == NULL) {
|
|
freeb (asn);
|
|
conn->lockit--;
|
|
return -EIO;
|
|
}
|
|
qd_d[0] = 0;
|
|
qd_d[1] = (eaz2 > 0) ? N1_FAC_Dienstwechsel2 : N1_FAC_Dienstwechsel1;
|
|
qd_d[2] = service >> 8;
|
|
qd_d[3] = service & 0xFF;
|
|
if ((gotservice && eaz != 0) || eaz2 != 0) {
|
|
qd_d[4] = (eaz != 0) ? eaz : '0';
|
|
qd_d[5] = (eaz2 != 0) ? eaz2 : '0';
|
|
} else if (eaz != 0)
|
|
qd_d[4] = eaz;
|
|
asn->b_wptr = asn->b_rptr + qd_len;
|
|
}
|
|
|
|
switch (conn->state) {
|
|
case 4:
|
|
case 7:
|
|
case 8:
|
|
if (!doforce) {
|
|
data->b_rptr = oldpos;
|
|
isdn3_repeat (conn, id, data);
|
|
if (asn != NULL)
|
|
freemsg (asn);
|
|
conn->lockit--;
|
|
return 0;
|
|
}
|
|
case 10:
|
|
if (!donum)
|
|
conn->minorstate |= MS_FORWARDING;
|
|
((struct t_info *)conn->p_data)->flags |= FAC_PENDING;
|
|
|
|
if ((err = phone_sendback (conn, MT_N1_FAC, asn)) == 0)
|
|
asn = NULL;
|
|
isdn3_setup_conn (conn, EST_LISTEN);
|
|
setstate (conn, 8);
|
|
break;
|
|
default:
|
|
printf("BadState4 ");
|
|
err = -EINVAL;
|
|
break;
|
|
}
|
|
if (asn != NULL)
|
|
freemsg (asn);
|
|
}
|
|
break;
|
|
#endif
|
|
case CMD_OFF:
|
|
{
|
|
mblk_t *mb = NULL;
|
|
|
|
conn->minorstate &= ~MS_WANTCONN;
|
|
if(cause != -1) {
|
|
int len;
|
|
uchar_t *dp;
|
|
|
|
if ((mb = allocb (16, BPRI_LO)) == NULL)
|
|
break;
|
|
|
|
len = mb->b_wptr - mb->b_rptr;
|
|
dp = qd_insert ((uchar_t *) mb->b_rptr, &len, 0, PT_N0_cause, 1, 0);
|
|
if (dp != NULL) {
|
|
mb->b_wptr = mb->b_rptr + len;
|
|
*dp = cause | 0x80;
|
|
}
|
|
}
|
|
/* set Data */
|
|
if (conn->state == 6 && cause == -1) {
|
|
setstate(conn,99);
|
|
if(mb != NULL)
|
|
freemsg(mb);
|
|
} else {
|
|
if(doforce && donodisc) {
|
|
doforce = 0;
|
|
/* Hmmm */
|
|
}
|
|
if (send_disc (conn, 1 + doforce, mb) != 0 && mb != NULL)
|
|
freemsg (mb);
|
|
}
|
|
|
|
isdn3_setup_conn (conn, EST_DISCONNECT);
|
|
err = 0;
|
|
}
|
|
break;
|
|
default:
|
|
printf("UnknownCmd ");
|
|
err = -EINVAL;
|
|
break;
|
|
}
|
|
if (data != NULL && err == 0)
|
|
freemsg (data);
|
|
|
|
checkterm (conn, NULL, 0);
|
|
conn->lockit--;
|
|
return err;
|
|
}
|
|
|
|
static void
|
|
killconn (isdn3_conn conn, char force)
|
|
{
|
|
if (force) {
|
|
untimer (N1_T308, conn);
|
|
untimer (N1_T313, conn);
|
|
#ifdef HAS_SUSPEND
|
|
untimer (N1_T318, conn);
|
|
#endif
|
|
untimer (N1_T305, conn);
|
|
untimer (N1_T3D1, conn);
|
|
untimer (N1_T303, conn);
|
|
untimer (N1_T304, conn);
|
|
untimer (N1_T310, conn);
|
|
untimer (N1_T3D2, conn);
|
|
#ifdef HAS_SUSPEND
|
|
untimer (N1_T319, conn);
|
|
#endif
|
|
untimer (N1_T3AA, conn);
|
|
untimer (N1_TCONN, conn);
|
|
untimer (N1_TALERT, conn);
|
|
untimer (N1_TFOO, conn);
|
|
}
|
|
if(conn->state != 0) {
|
|
if(conn->state == 99)
|
|
setstate(conn, 0);
|
|
else if(force)
|
|
(void) phone_sendback (conn, MT_N1_REL, NULL);
|
|
else
|
|
(void) send_disc (conn, 1, NULL);
|
|
}
|
|
}
|
|
|
|
static void report (isdn3_conn conn, mblk_t *mb)
|
|
{
|
|
struct t_info *info = conn->p_data;
|
|
if (info == NULL)
|
|
return;
|
|
if (info->nr[0] != 0) {
|
|
m_putsx (mb, ARG_NUMBER);
|
|
m_putsz (mb, info->nr);
|
|
}
|
|
if (info->eaz != 0) {
|
|
m_putsx (mb, ARG_LNUMBER);
|
|
*mb->b_wptr++=' ';
|
|
*mb->b_wptr++='/';
|
|
*mb->b_wptr++=info->eaz;
|
|
}
|
|
if (info->service != 0) {
|
|
m_putsx (mb, ARG_SERVICE);
|
|
m_putx (mb, info->service);
|
|
}
|
|
}
|
|
|
|
struct _isdn3_prot prot_1TR6_1 =
|
|
{
|
|
NULL, SAPI_PHONE_1TR6_1,
|
|
NULL, &chstate, &report, &recv, NULL, &sendcmd, &killconn, NULL,
|
|
};
|