2005-04-16 15:20:36 -07:00
/*
* Callbacks for the FSM
*
* Copyright ( C ) 1996 Universidade de Lisboa
2012-02-19 19:52:38 -08:00
*
2005-04-16 15:20:36 -07:00
* Written by Pedro Roque Marques ( roque @ di . fc . ul . pt )
*
2012-02-19 19:52:38 -08:00
* This software may be used and distributed according to the terms of
2005-04-16 15:20:36 -07:00
* the GNU General Public License , incorporated herein by reference .
*/
/*
* Fix : 19981230 - Carlos Morgado < chbm @ techie . com >
2012-02-19 19:52:38 -08:00
* Port of Nelson Escravana ' s < nelson . escravana @ usa . net > fix to CalledPN
2005-04-16 15:20:36 -07:00
* NULL pointer dereference in cb_in_1 ( originally fixed in 2.0 )
*/
# include <linux/string.h>
# include <linux/kernel.h>
# include <linux/types.h>
# include <linux/mm.h>
# include <linux/skbuff.h>
# include <asm/io.h>
# include <linux/isdnif.h>
# include "pcbit.h"
# include "layer2.h"
# include "edss1.h"
# include "callbacks.h"
# include "capi.h"
ushort last_ref_num = 1 ;
/*
* send_conn_req
*
*/
2012-02-19 19:52:38 -08:00
void cb_out_1 ( struct pcbit_dev * dev , struct pcbit_chan * chan ,
struct callb_data * cbdata )
2005-04-16 15:20:36 -07:00
{
struct sk_buff * skb ;
int len ;
2012-02-19 19:52:38 -08:00
ushort refnum ;
2005-04-16 15:20:36 -07:00
# ifdef DEBUG
2012-02-19 19:52:38 -08:00
printk ( KERN_DEBUG " Called Party Number: %s \n " ,
cbdata - > data . setup . CalledPN ) ;
2005-04-16 15:20:36 -07:00
# endif
2012-02-19 19:52:38 -08:00
/*
* hdr - kmalloc in capi_conn_req
* - kfree when msg has been sent
*/
2005-04-16 15:20:36 -07:00
2012-02-19 19:52:38 -08:00
if ( ( len = capi_conn_req ( cbdata - > data . setup . CalledPN , & skb ,
2005-04-16 15:20:36 -07:00
chan - > proto ) ) < 0 )
2012-02-19 19:52:38 -08:00
{
printk ( " capi_conn_req failed \n " ) ;
return ;
}
2005-04-16 15:20:36 -07:00
2012-02-19 19:52:38 -08:00
refnum = last_ref_num + + & 0x7fffU ;
2005-04-16 15:20:36 -07:00
2012-02-19 19:52:38 -08:00
chan - > callref = 0 ;
chan - > layer2link = 0 ;
chan - > snum = 0 ;
chan - > s_refnum = refnum ;
2005-04-16 15:20:36 -07:00
2012-02-19 19:52:38 -08:00
pcbit_l2_write ( dev , MSG_CONN_REQ , refnum , skb , len ) ;
2005-04-16 15:20:36 -07:00
}
/*
* rcv CONNECT
* will go into ACTIVE state
* send CONN_ACTIVE_RESP
2012-02-19 19:52:38 -08:00
* send Select protocol request
2005-04-16 15:20:36 -07:00
*/
2012-02-19 19:52:38 -08:00
void cb_out_2 ( struct pcbit_dev * dev , struct pcbit_chan * chan ,
struct callb_data * data )
2005-04-16 15:20:36 -07:00
{
2012-02-19 19:52:38 -08:00
isdn_ctrl ictl ;
struct sk_buff * skb ;
2005-04-16 15:20:36 -07:00
int len ;
2012-02-19 19:52:38 -08:00
ushort refnum ;
2005-04-16 15:20:36 -07:00
2012-02-19 19:52:38 -08:00
if ( ( len = capi_conn_active_resp ( chan , & skb ) ) < 0 )
{
printk ( " capi_conn_active_req failed \n " ) ;
return ;
}
2005-04-16 15:20:36 -07:00
2012-02-19 19:52:38 -08:00
refnum = last_ref_num + + & 0x7fffU ;
chan - > s_refnum = refnum ;
2005-04-16 15:20:36 -07:00
2012-02-19 19:52:38 -08:00
pcbit_l2_write ( dev , MSG_CONN_ACTV_RESP , refnum , skb , len ) ;
2005-04-16 15:20:36 -07:00
2012-02-19 19:52:38 -08:00
ictl . command = ISDN_STAT_DCONN ;
ictl . driver = dev - > id ;
ictl . arg = chan - > id ;
dev - > dev_if - > statcallb ( & ictl ) ;
2005-04-16 15:20:36 -07:00
2012-02-19 19:52:38 -08:00
/* ACTIVE D-channel */
2005-04-16 15:20:36 -07:00
2012-02-19 19:52:38 -08:00
/* Select protocol */
2005-04-16 15:20:36 -07:00
2012-02-19 19:52:38 -08:00
if ( ( len = capi_select_proto_req ( chan , & skb , 1 /*outgoing*/ ) ) < 0 ) {
printk ( " capi_select_proto_req failed \n " ) ;
return ;
}
2005-04-16 15:20:36 -07:00
2012-02-19 19:52:38 -08:00
refnum = last_ref_num + + & 0x7fffU ;
chan - > s_refnum = refnum ;
2005-04-16 15:20:36 -07:00
2012-02-19 19:52:38 -08:00
pcbit_l2_write ( dev , MSG_SELP_REQ , refnum , skb , len ) ;
2005-04-16 15:20:36 -07:00
}
/*
* Incoming call received
* inform user
*/
2012-02-19 19:52:38 -08:00
void cb_in_1 ( struct pcbit_dev * dev , struct pcbit_chan * chan ,
struct callb_data * cbdata )
2005-04-16 15:20:36 -07:00
{
2012-02-19 19:52:38 -08:00
isdn_ctrl ictl ;
unsigned short refnum ;
struct sk_buff * skb ;
2005-04-16 15:20:36 -07:00
int len ;
2012-02-19 19:52:38 -08:00
ictl . command = ISDN_STAT_ICALL ;
ictl . driver = dev - > id ;
ictl . arg = chan - > id ;
/*
* ictl . num > = strlen ( ) + strlen ( ) + 5
*/
2005-04-16 15:20:36 -07:00
if ( cbdata - > data . setup . CallingPN = = NULL ) {
printk ( KERN_DEBUG " NULL CallingPN to phone; using 0 \n " ) ;
strcpy ( ictl . parm . setup . phone , " 0 " ) ;
}
else {
strcpy ( ictl . parm . setup . phone , cbdata - > data . setup . CallingPN ) ;
}
if ( cbdata - > data . setup . CalledPN = = NULL ) {
printk ( KERN_DEBUG " NULL CalledPN to eazmsn; using 0 \n " ) ;
strcpy ( ictl . parm . setup . eazmsn , " 0 " ) ;
}
else {
strcpy ( ictl . parm . setup . eazmsn , cbdata - > data . setup . CalledPN ) ;
}
ictl . parm . setup . si1 = 7 ;
ictl . parm . setup . si2 = 0 ;
ictl . parm . setup . plan = 0 ;
ictl . parm . setup . screen = 0 ;
# ifdef DEBUG
printk ( KERN_DEBUG " statstr: %s \n " , ictl . num ) ;
# endif
2012-02-19 19:52:38 -08:00
dev - > dev_if - > statcallb ( & ictl ) ;
2005-04-16 15:20:36 -07:00
2012-02-19 19:52:38 -08:00
if ( ( len = capi_conn_resp ( chan , & skb ) ) < 0 ) {
printk ( KERN_DEBUG " capi_conn_resp failed \n " ) ;
return ;
2005-04-16 15:20:36 -07:00
}
2012-02-19 19:52:38 -08:00
refnum = last_ref_num + + & 0x7fffU ;
chan - > s_refnum = refnum ;
2005-04-16 15:20:36 -07:00
2012-02-19 19:52:38 -08:00
pcbit_l2_write ( dev , MSG_CONN_RESP , refnum , skb , len ) ;
2005-04-16 15:20:36 -07:00
}
/*
* user has replied
* open the channel
* send CONNECT message CONNECT_ACTIVE_REQ in CAPI
*/
2012-02-19 19:52:38 -08:00
void cb_in_2 ( struct pcbit_dev * dev , struct pcbit_chan * chan ,
2005-04-16 15:20:36 -07:00
struct callb_data * data )
{
2012-02-19 19:52:38 -08:00
unsigned short refnum ;
2005-04-16 15:20:36 -07:00
struct sk_buff * skb ;
2012-02-19 19:52:38 -08:00
int len ;
if ( ( len = capi_conn_active_req ( chan , & skb ) ) < 0 ) {
printk ( KERN_DEBUG " capi_conn_active_req failed \n " ) ;
return ;
}
2005-04-16 15:20:36 -07:00
2012-02-19 19:52:38 -08:00
refnum = last_ref_num + + & 0x7fffU ;
chan - > s_refnum = refnum ;
2005-04-16 15:20:36 -07:00
printk ( KERN_DEBUG " sending MSG_CONN_ACTV_REQ \n " ) ;
2012-02-19 19:52:38 -08:00
pcbit_l2_write ( dev , MSG_CONN_ACTV_REQ , refnum , skb , len ) ;
2005-04-16 15:20:36 -07:00
}
/*
* CONN_ACK arrived
* start b - proto selection
*
*/
2012-02-19 19:52:38 -08:00
void cb_in_3 ( struct pcbit_dev * dev , struct pcbit_chan * chan ,
2005-04-16 15:20:36 -07:00
struct callb_data * data )
{
2012-02-19 19:52:38 -08:00
unsigned short refnum ;
struct sk_buff * skb ;
2005-04-16 15:20:36 -07:00
int len ;
2012-02-19 19:52:38 -08:00
if ( ( len = capi_select_proto_req ( chan , & skb , 0 /*incoming*/ ) ) < 0 )
{
printk ( " capi_select_proto_req failed \n " ) ;
return ;
}
refnum = last_ref_num + + & 0x7fffU ;
chan - > s_refnum = refnum ;
2005-04-16 15:20:36 -07:00
2012-02-19 19:52:38 -08:00
pcbit_l2_write ( dev , MSG_SELP_REQ , refnum , skb , len ) ;
2005-04-16 15:20:36 -07:00
}
/*
* Received disconnect ind on active state
* send disconnect resp
* send msg to user
*/
2012-02-19 19:52:38 -08:00
void cb_disc_1 ( struct pcbit_dev * dev , struct pcbit_chan * chan ,
2005-04-16 15:20:36 -07:00
struct callb_data * data )
{
2012-02-19 19:52:38 -08:00
struct sk_buff * skb ;
2005-04-16 15:20:36 -07:00
int len ;
2012-02-19 19:52:38 -08:00
ushort refnum ;
isdn_ctrl ictl ;
if ( ( len = capi_disc_resp ( chan , & skb ) ) < 0 ) {
printk ( " capi_disc_resp failed \n " ) ;
return ;
}
refnum = last_ref_num + + & 0x7fffU ;
chan - > s_refnum = refnum ;
pcbit_l2_write ( dev , MSG_DISC_RESP , refnum , skb , len ) ;
ictl . command = ISDN_STAT_BHUP ;
ictl . driver = dev - > id ;
ictl . arg = chan - > id ;
dev - > dev_if - > statcallb ( & ictl ) ;
2005-04-16 15:20:36 -07:00
}
2012-02-19 19:52:38 -08:00
2005-04-16 15:20:36 -07:00
/*
* User HANGUP on active / call proceeding state
* send disc . req
*/
2012-02-19 19:52:38 -08:00
void cb_disc_2 ( struct pcbit_dev * dev , struct pcbit_chan * chan ,
2005-04-16 15:20:36 -07:00
struct callb_data * data )
{
2012-02-19 19:52:38 -08:00
struct sk_buff * skb ;
2005-04-16 15:20:36 -07:00
int len ;
2012-02-19 19:52:38 -08:00
ushort refnum ;
2005-04-16 15:20:36 -07:00
2012-02-19 19:52:38 -08:00
if ( ( len = capi_disc_req ( chan - > callref , & skb , CAUSE_NORMAL ) ) < 0 )
{
printk ( " capi_disc_req failed \n " ) ;
return ;
}
2005-04-16 15:20:36 -07:00
2012-02-19 19:52:38 -08:00
refnum = last_ref_num + + & 0x7fffU ;
chan - > s_refnum = refnum ;
2005-04-16 15:20:36 -07:00
2012-02-19 19:52:38 -08:00
pcbit_l2_write ( dev , MSG_DISC_REQ , refnum , skb , len ) ;
2005-04-16 15:20:36 -07:00
}
/*
* Disc confirm received send BHUP
* Problem : when the HL driver sends the disc req itself
* LL receives BHUP
*/
2012-02-19 19:52:38 -08:00
void cb_disc_3 ( struct pcbit_dev * dev , struct pcbit_chan * chan ,
2005-04-16 15:20:36 -07:00
struct callb_data * data )
{
2012-02-19 19:52:38 -08:00
isdn_ctrl ictl ;
2005-04-16 15:20:36 -07:00
2012-02-19 19:52:38 -08:00
ictl . command = ISDN_STAT_BHUP ;
ictl . driver = dev - > id ;
ictl . arg = chan - > id ;
dev - > dev_if - > statcallb ( & ictl ) ;
2005-04-16 15:20:36 -07:00
}
2012-02-19 19:52:38 -08:00
void cb_notdone ( struct pcbit_dev * dev , struct pcbit_chan * chan ,
2005-04-16 15:20:36 -07:00
struct callb_data * data )
{
}
/*
* send activate b - chan protocol
*/
2012-02-19 19:52:38 -08:00
void cb_selp_1 ( struct pcbit_dev * dev , struct pcbit_chan * chan ,
struct callb_data * data )
2005-04-16 15:20:36 -07:00
{
2012-02-19 19:52:38 -08:00
struct sk_buff * skb ;
2005-04-16 15:20:36 -07:00
int len ;
2012-02-19 19:52:38 -08:00
ushort refnum ;
2005-04-16 15:20:36 -07:00
2012-02-19 19:52:38 -08:00
if ( ( len = capi_activate_transp_req ( chan , & skb ) ) < 0 )
{
printk ( " capi_conn_activate_transp_req failed \n " ) ;
return ;
}
2005-04-16 15:20:36 -07:00
2012-02-19 19:52:38 -08:00
refnum = last_ref_num + + & 0x7fffU ;
chan - > s_refnum = refnum ;
2005-04-16 15:20:36 -07:00
2012-02-19 19:52:38 -08:00
pcbit_l2_write ( dev , MSG_ACT_TRANSP_REQ , refnum , skb , len ) ;
2005-04-16 15:20:36 -07:00
}
/*
* Inform User that the B - channel is available
*/
2012-02-19 19:52:38 -08:00
void cb_open ( struct pcbit_dev * dev , struct pcbit_chan * chan ,
struct callb_data * data )
2005-04-16 15:20:36 -07:00
{
2012-02-19 19:52:38 -08:00
isdn_ctrl ictl ;
2005-04-16 15:20:36 -07:00
2012-02-19 19:52:38 -08:00
ictl . command = ISDN_STAT_BCONN ;
ictl . driver = dev - > id ;
ictl . arg = chan - > id ;
dev - > dev_if - > statcallb ( & ictl ) ;
2005-04-16 15:20:36 -07:00
}