2005-04-17 02:20:36 +04:00
/*
* CAPI encoder / decoder for
* Portugal Telecom CAPI 2.0
*
* Copyright ( C ) 1996 Universidade de Lisboa
2012-02-20 07:52:38 +04:00
*
2005-04-17 02:20:36 +04:00
* Written by Pedro Roque Marques ( roque @ di . fc . ul . pt )
*
2012-02-20 07:52:38 +04:00
* This software may be used and distributed according to the terms of
2005-04-17 02:20:36 +04:00
* the GNU General Public License , incorporated herein by reference .
*
* Not compatible with the AVM Gmbh . CAPI 2.0
*
*/
/*
* Documentation :
2007-10-20 01:21:04 +04:00
* - " Common ISDN API - Perfil Português - Versão 2.1 " ,
2005-04-17 02:20:36 +04:00
* Telecom Portugal , Fev 1992.
2007-10-20 01:21:04 +04:00
* - " Common ISDN API - Especificação de protocolos para
2005-04-17 02:20:36 +04:00
* acesso aos canais B " , Inesc, Jan 1994.
*/
/*
* TODO : better decoding of Information Elements
* for debug purposes mainly
* encode our number in CallerPN and ConnectedPN
*/
# include <linux/string.h>
# include <linux/kernel.h>
# include <linux/types.h>
# include <linux/slab.h>
# include <linux/mm.h>
# include <linux/skbuff.h>
# include <asm/io.h>
# include <asm/string.h>
# include <linux/isdnif.h>
# include "pcbit.h"
# include "edss1.h"
# include "capi.h"
/*
* Encoding of CAPI messages
*
*/
2012-02-20 07:52:38 +04:00
int capi_conn_req ( const char * calledPN , struct sk_buff * * skb , int proto )
2005-04-17 02:20:36 +04:00
{
2012-02-20 07:52:38 +04:00
ushort len ;
/*
* length
* AppInfoMask - 2
* BC0 - 3
* BC1 - 1
* Chan - 2
* Keypad - 1
* CPN - 1
* CPSA - 1
* CalledPN - 2 + strlen
* CalledPSA - 1
* rest . . . - 4
* - - - - - - - - - - - - - - - -
* Total 18 + strlen
*/
len = 18 + strlen ( calledPN ) ;
2005-04-17 02:20:36 +04:00
if ( proto = = ISDN_PROTO_L2_TRANS )
len + + ;
if ( ( * skb = dev_alloc_skb ( len ) ) = = NULL ) {
2012-02-20 07:52:38 +04:00
printk ( KERN_WARNING " capi_conn_req: alloc_skb failed \n " ) ;
2005-04-17 02:20:36 +04:00
return - 1 ;
}
2012-02-20 07:52:38 +04:00
/* InfoElmMask */
* ( ( ushort * ) skb_put ( * skb , 2 ) ) = AppInfoMask ;
2005-04-17 02:20:36 +04:00
if ( proto = = ISDN_PROTO_L2_TRANS )
{
/* Bearer Capability - Mandatory*/
* ( skb_put ( * skb , 1 ) ) = 3 ; /* BC0.Length */
* ( skb_put ( * skb , 1 ) ) = 0x80 ; /* Speech */
* ( skb_put ( * skb , 1 ) ) = 0x10 ; /* Circuit Mode */
* ( skb_put ( * skb , 1 ) ) = 0x23 ; /* A-law */
}
else
{
/* Bearer Capability - Mandatory*/
* ( skb_put ( * skb , 1 ) ) = 2 ; /* BC0.Length */
* ( skb_put ( * skb , 1 ) ) = 0x88 ; /* Digital Information */
* ( skb_put ( * skb , 1 ) ) = 0x90 ; /* BC0.Octect4 */
}
2012-02-20 07:52:38 +04:00
/* Bearer Capability - Optional*/
* ( skb_put ( * skb , 1 ) ) = 0 ; /* BC1.Length = 0 */
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
* ( skb_put ( * skb , 1 ) ) = 1 ; /* ChannelID.Length = 1 */
* ( skb_put ( * skb , 1 ) ) = 0x83 ; /* Basic Interface - Any Channel */
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
* ( skb_put ( * skb , 1 ) ) = 0 ; /* Keypad.Length = 0 */
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
* ( skb_put ( * skb , 1 ) ) = 0 ; /* CallingPN.Length = 0 */
* ( skb_put ( * skb , 1 ) ) = 0 ; /* CallingPSA.Length = 0 */
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
/* Called Party Number */
* ( skb_put ( * skb , 1 ) ) = strlen ( calledPN ) + 1 ;
* ( skb_put ( * skb , 1 ) ) = 0x81 ;
memcpy ( skb_put ( * skb , strlen ( calledPN ) ) , calledPN , strlen ( calledPN ) ) ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
/* '#' */
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
* ( skb_put ( * skb , 1 ) ) = 0 ; /* CalledPSA.Length = 0 */
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
/* LLC.Length = 0; */
/* HLC0.Length = 0; */
/* HLC1.Length = 0; */
/* UTUS.Length = 0; */
memset ( skb_put ( * skb , 4 ) , 0 , 4 ) ;
return len ;
2005-04-17 02:20:36 +04:00
}
2012-02-20 07:52:38 +04:00
int capi_conn_resp ( struct pcbit_chan * chan , struct sk_buff * * skb )
2005-04-17 02:20:36 +04:00
{
2012-02-20 07:52:38 +04:00
2005-04-17 02:20:36 +04:00
if ( ( * skb = dev_alloc_skb ( 5 ) ) = = NULL ) {
2012-02-20 07:52:38 +04:00
2005-04-17 02:20:36 +04:00
printk ( KERN_WARNING " capi_conn_resp: alloc_skb failed \n " ) ;
return - 1 ;
}
2012-02-20 07:52:38 +04:00
* ( ( ushort * ) skb_put ( * skb , 2 ) ) = chan - > callref ;
* ( skb_put ( * skb , 1 ) ) = 0x01 ; /* ACCEPT_CALL */
* ( skb_put ( * skb , 1 ) ) = 0 ;
* ( skb_put ( * skb , 1 ) ) = 0 ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
return 5 ;
2005-04-17 02:20:36 +04:00
}
2012-02-20 07:52:38 +04:00
int capi_conn_active_req ( struct pcbit_chan * chan , struct sk_buff * * skb )
2005-04-17 02:20:36 +04:00
{
2012-02-20 07:52:38 +04:00
/*
* 8 bytes
*/
2005-04-17 02:20:36 +04:00
if ( ( * skb = dev_alloc_skb ( 8 ) ) = = NULL ) {
2012-02-20 07:52:38 +04:00
2005-04-17 02:20:36 +04:00
printk ( KERN_WARNING " capi_conn_active_req: alloc_skb failed \n " ) ;
return - 1 ;
}
2012-02-20 07:52:38 +04:00
* ( ( ushort * ) skb_put ( * skb , 2 ) ) = chan - > callref ;
2005-04-17 02:20:36 +04:00
# ifdef DEBUG
2012-02-20 07:52:38 +04:00
printk ( KERN_DEBUG " Call Reference: %04x \n " , chan - > callref ) ;
2005-04-17 02:20:36 +04:00
# endif
2012-02-20 07:52:38 +04:00
* ( skb_put ( * skb , 1 ) ) = 0 ; /* BC.Length = 0; */
* ( skb_put ( * skb , 1 ) ) = 0 ; /* ConnectedPN.Length = 0 */
* ( skb_put ( * skb , 1 ) ) = 0 ; /* PSA.Length */
* ( skb_put ( * skb , 1 ) ) = 0 ; /* LLC.Length = 0; */
* ( skb_put ( * skb , 1 ) ) = 0 ; /* HLC.Length = 0; */
* ( skb_put ( * skb , 1 ) ) = 0 ; /* UTUS.Length = 0; */
2005-04-17 02:20:36 +04:00
return 8 ;
}
2012-02-20 07:52:38 +04:00
int capi_conn_active_resp ( struct pcbit_chan * chan , struct sk_buff * * skb )
2005-04-17 02:20:36 +04:00
{
2012-02-20 07:52:38 +04:00
/*
* 2 bytes
*/
2005-04-17 02:20:36 +04:00
if ( ( * skb = dev_alloc_skb ( 2 ) ) = = NULL ) {
2012-02-20 07:52:38 +04:00
2005-04-17 02:20:36 +04:00
printk ( KERN_WARNING " capi_conn_active_resp: alloc_skb failed \n " ) ;
return - 1 ;
}
2012-02-20 07:52:38 +04:00
* ( ( ushort * ) skb_put ( * skb , 2 ) ) = chan - > callref ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
return 2 ;
2005-04-17 02:20:36 +04:00
}
2012-02-20 07:52:38 +04:00
int capi_select_proto_req ( struct pcbit_chan * chan , struct sk_buff * * skb ,
int outgoing )
2005-04-17 02:20:36 +04:00
{
2012-02-20 07:52:38 +04:00
/*
* 18 bytes
*/
2005-04-17 02:20:36 +04:00
if ( ( * skb = dev_alloc_skb ( 18 ) ) = = NULL ) {
2012-02-20 07:52:38 +04:00
2005-04-17 02:20:36 +04:00
printk ( KERN_WARNING " capi_select_proto_req: alloc_skb failed \n " ) ;
return - 1 ;
}
2012-02-20 07:52:38 +04:00
* ( ( ushort * ) skb_put ( * skb , 2 ) ) = chan - > callref ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
/* Layer2 protocol */
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
switch ( chan - > proto ) {
case ISDN_PROTO_L2_X75I :
* ( skb_put ( * skb , 1 ) ) = 0x05 ; /* LAPB */
break ;
case ISDN_PROTO_L2_HDLC :
* ( skb_put ( * skb , 1 ) ) = 0x02 ;
break ;
2005-04-17 02:20:36 +04:00
case ISDN_PROTO_L2_TRANS :
2012-02-20 07:52:38 +04:00
/*
2005-04-17 02:20:36 +04:00
* Voice ( a - law )
*/
* ( skb_put ( * skb , 1 ) ) = 0x06 ;
break ;
2012-02-20 07:52:38 +04:00
default :
# ifdef DEBUG
printk ( KERN_DEBUG " Transparent \n " ) ;
2005-04-17 02:20:36 +04:00
# endif
2012-02-20 07:52:38 +04:00
* ( skb_put ( * skb , 1 ) ) = 0x03 ;
break ;
}
* ( skb_put ( * skb , 1 ) ) = ( outgoing ? 0x02 : 0x42 ) ; /* Don't ask */
* ( skb_put ( * skb , 1 ) ) = 0x00 ;
* ( ( ushort * ) skb_put ( * skb , 2 ) ) = MRU ;
* ( skb_put ( * skb , 1 ) ) = 0x08 ; /* Modulo */
* ( skb_put ( * skb , 1 ) ) = 0x07 ; /* Max Window */
* ( skb_put ( * skb , 1 ) ) = 0x01 ; /* No Layer3 Protocol */
/*
* 2 - layer3 MTU [ 10 ]
* - Modulo [ 12 ]
* - Window
* - layer1 proto [ 14 ]
* - bitrate
* - sub - channel [ 16 ]
* - layer1dataformat [ 17 ]
*/
memset ( skb_put ( * skb , 8 ) , 0 , 8 ) ;
return 18 ;
2005-04-17 02:20:36 +04:00
}
int capi_activate_transp_req ( struct pcbit_chan * chan , struct sk_buff * * skb )
{
if ( ( * skb = dev_alloc_skb ( 7 ) ) = = NULL ) {
2012-02-20 07:52:38 +04:00
2005-04-17 02:20:36 +04:00
printk ( KERN_WARNING " capi_activate_transp_req: alloc_skb failed \n " ) ;
return - 1 ;
}
2012-02-20 07:52:38 +04:00
* ( ( ushort * ) skb_put ( * skb , 2 ) ) = chan - > callref ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
* ( skb_put ( * skb , 1 ) ) = chan - > layer2link ; /* Layer2 id */
* ( skb_put ( * skb , 1 ) ) = 0x00 ; /* Transmit by default */
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
* ( ( ushort * ) skb_put ( * skb , 2 ) ) = MRU ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
* ( skb_put ( * skb , 1 ) ) = 0x01 ; /* Enables reception*/
return 7 ;
2005-04-17 02:20:36 +04:00
}
2012-02-20 07:52:38 +04:00
int capi_tdata_req ( struct pcbit_chan * chan , struct sk_buff * skb )
2005-04-17 02:20:36 +04:00
{
ushort data_len ;
2012-02-20 07:52:38 +04:00
/*
* callref - 2
2005-04-17 02:20:36 +04:00
* layer2link - 1
2012-02-20 07:52:38 +04:00
* wBlockLength - 2
2005-04-17 02:20:36 +04:00
* data - 4
* sernum - 1
*/
2012-02-20 07:52:38 +04:00
2005-04-17 02:20:36 +04:00
data_len = skb - > len ;
2012-02-20 07:52:38 +04:00
if ( skb_headroom ( skb ) < 10 )
2005-04-17 02:20:36 +04:00
{
printk ( KERN_CRIT " No headspace (%u) on headroom %p for capi header \n " , skb_headroom ( skb ) , skb ) ;
}
else
2012-02-20 07:52:38 +04:00
{
2005-04-17 02:20:36 +04:00
skb_push ( skb , 10 ) ;
}
* ( ( u16 * ) ( skb - > data ) ) = chan - > callref ;
skb - > data [ 2 ] = chan - > layer2link ;
* ( ( u16 * ) ( skb - > data + 3 ) ) = data_len ;
chan - > s_refnum = ( chan - > s_refnum + 1 ) % 8 ;
* ( ( u32 * ) ( skb - > data + 5 ) ) = chan - > s_refnum ;
skb - > data [ 9 ] = 0 ; /* HDLC frame number */
return 10 ;
}
2012-02-20 07:52:38 +04:00
int capi_tdata_resp ( struct pcbit_chan * chan , struct sk_buff * * skb )
2005-04-17 02:20:36 +04:00
{
if ( ( * skb = dev_alloc_skb ( 4 ) ) = = NULL ) {
2012-02-20 07:52:38 +04:00
2005-04-17 02:20:36 +04:00
printk ( KERN_WARNING " capi_tdata_resp: alloc_skb failed \n " ) ;
return - 1 ;
}
2012-02-20 07:52:38 +04:00
* ( ( ushort * ) skb_put ( * skb , 2 ) ) = chan - > callref ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
* ( skb_put ( * skb , 1 ) ) = chan - > layer2link ;
* ( skb_put ( * skb , 1 ) ) = chan - > r_refnum ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
return ( * skb ) - > len ;
2005-04-17 02:20:36 +04:00
}
int capi_disc_req ( ushort callref , struct sk_buff * * skb , u_char cause )
{
if ( ( * skb = dev_alloc_skb ( 6 ) ) = = NULL ) {
2012-02-20 07:52:38 +04:00
2005-04-17 02:20:36 +04:00
printk ( KERN_WARNING " capi_disc_req: alloc_skb failed \n " ) ;
return - 1 ;
}
2012-02-20 07:52:38 +04:00
* ( ( ushort * ) skb_put ( * skb , 2 ) ) = callref ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
* ( skb_put ( * skb , 1 ) ) = 2 ; /* Cause.Length = 2; */
* ( skb_put ( * skb , 1 ) ) = 0x80 ;
* ( skb_put ( * skb , 1 ) ) = 0x80 | cause ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
/*
* Change it : we should send ' Sic transit gloria Mundi ' here ; - )
*/
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
* ( skb_put ( * skb , 1 ) ) = 0 ; /* UTUS.Length = 0; */
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
return 6 ;
2005-04-17 02:20:36 +04:00
}
int capi_disc_resp ( struct pcbit_chan * chan , struct sk_buff * * skb )
{
if ( ( * skb = dev_alloc_skb ( 2 ) ) = = NULL ) {
2012-02-20 07:52:38 +04:00
2005-04-17 02:20:36 +04:00
printk ( KERN_WARNING " capi_disc_resp: alloc_skb failed \n " ) ;
return - 1 ;
}
2012-02-20 07:52:38 +04:00
* ( ( ushort * ) skb_put ( * skb , 2 ) ) = chan - > callref ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
return 2 ;
2005-04-17 02:20:36 +04:00
}
/*
* Decoding of CAPI messages
*
*/
2012-02-20 07:52:38 +04:00
int capi_decode_conn_ind ( struct pcbit_chan * chan ,
struct sk_buff * skb ,
struct callb_data * info )
2005-04-17 02:20:36 +04:00
{
2012-02-20 07:52:38 +04:00
int CIlen , len ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
/* Call Reference [CAPI] */
chan - > callref = * ( ( ushort * ) skb - > data ) ;
skb_pull ( skb , 2 ) ;
2005-04-17 02:20:36 +04:00
# ifdef DEBUG
2012-02-20 07:52:38 +04:00
printk ( KERN_DEBUG " Call Reference: %04x \n " , chan - > callref ) ;
2005-04-17 02:20:36 +04:00
# endif
2012-02-20 07:52:38 +04:00
/* Channel Identification */
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
/* Expect
Len = 1
Octect 3 = 0100 10 CC - [ 7 Basic , 4 , 2 - 1 chan ]
*/
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
CIlen = skb - > data [ 0 ] ;
2005-04-17 02:20:36 +04:00
# ifdef DEBUG
2012-02-20 07:52:38 +04:00
if ( CIlen = = 1 ) {
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
if ( ( ( skb - > data [ 1 ] ) & 0xFC ) = = 0x48 )
printk ( KERN_DEBUG " decode_conn_ind: chan ok \n " ) ;
printk ( KERN_DEBUG " phyChan = %d \n " , skb - > data [ 1 ] & 0x03 ) ;
}
2005-04-17 02:20:36 +04:00
else
printk ( KERN_DEBUG " conn_ind: CIlen = %d \n " , CIlen ) ;
# endif
2012-02-20 07:52:38 +04:00
skb_pull ( skb , CIlen + 1 ) ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
/* Calling Party Number */
/* An "additional service" as far as Portugal Telecom is concerned */
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
len = skb - > data [ 0 ] ;
2005-04-17 02:20:36 +04:00
if ( len > 0 ) {
int count = 1 ;
2012-02-20 07:52:38 +04:00
2005-04-17 02:20:36 +04:00
# ifdef DEBUG
printk ( KERN_DEBUG " CPN: Octect 3 %02x \n " , skb - > data [ 1 ] ) ;
# endif
if ( ( skb - > data [ 1 ] & 0x80 ) = = 0 )
count = 2 ;
2012-02-20 07:52:38 +04:00
2005-04-17 02:20:36 +04:00
if ( ! ( info - > data . setup . CallingPN = kmalloc ( len - count + 1 , GFP_ATOMIC ) ) )
return - 1 ;
2012-02-20 07:52:38 +04:00
2007-03-28 01:55:52 +04:00
skb_copy_from_linear_data_offset ( skb , count + 1 ,
info - > data . setup . CallingPN ,
len - count ) ;
2005-04-17 02:20:36 +04:00
info - > data . setup . CallingPN [ len - count ] = 0 ;
}
else {
info - > data . setup . CallingPN = NULL ;
printk ( KERN_DEBUG " NULL CallingPN \n " ) ;
}
skb_pull ( skb , len + 1 ) ;
2012-02-20 07:52:38 +04:00
/* Calling Party Subaddress */
skb_pull ( skb , skb - > data [ 0 ] + 1 ) ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
/* Called Party Number */
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
len = skb - > data [ 0 ] ;
2005-04-17 02:20:36 +04:00
if ( len > 0 ) {
int count = 1 ;
2012-02-20 07:52:38 +04:00
2005-04-17 02:20:36 +04:00
if ( ( skb - > data [ 1 ] & 0x80 ) = = 0 )
count = 2 ;
2012-02-20 07:52:38 +04:00
2005-04-17 02:20:36 +04:00
if ( ! ( info - > data . setup . CalledPN = kmalloc ( len - count + 1 , GFP_ATOMIC ) ) )
return - 1 ;
2012-02-20 07:52:38 +04:00
2007-03-28 01:55:52 +04:00
skb_copy_from_linear_data_offset ( skb , count + 1 ,
info - > data . setup . CalledPN ,
len - count ) ;
2005-04-17 02:20:36 +04:00
info - > data . setup . CalledPN [ len - count ] = 0 ;
}
else {
info - > data . setup . CalledPN = NULL ;
printk ( KERN_DEBUG " NULL CalledPN \n " ) ;
}
skb_pull ( skb , len + 1 ) ;
2012-02-20 07:52:38 +04:00
/* Called Party Subaddress */
skb_pull ( skb , skb - > data [ 0 ] + 1 ) ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
/* LLC */
skb_pull ( skb , skb - > data [ 0 ] + 1 ) ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
/* HLC */
skb_pull ( skb , skb - > data [ 0 ] + 1 ) ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
/* U2U */
skb_pull ( skb , skb - > data [ 0 ] + 1 ) ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
/*
* returns errcode
*/
2012-02-20 07:52:38 +04:00
int capi_decode_conn_conf ( struct pcbit_chan * chan , struct sk_buff * skb ,
int * complete )
2005-04-17 02:20:36 +04:00
{
2012-02-20 07:52:38 +04:00
int errcode ;
chan - > callref = * ( ( ushort * ) skb - > data ) ; /* Update CallReference */
skb_pull ( skb , 2 ) ;
errcode = * ( ( ushort * ) skb - > data ) ; /* read errcode */
skb_pull ( skb , 2 ) ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
* complete = * ( skb - > data ) ;
skb_pull ( skb , 1 ) ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
/* FIX ME */
/* This is actually a firmware bug */
if ( ! * complete )
{
printk ( KERN_DEBUG " complete=%02x \n " , * complete ) ;
* complete = 1 ;
}
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
/* Optional Bearer Capability */
skb_pull ( skb , * ( skb - > data ) + 1 ) ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
/* Channel Identification */
skb_pull ( skb , * ( skb - > data ) + 1 ) ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
/* High Layer Compatibility follows */
skb_pull ( skb , * ( skb - > data ) + 1 ) ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
return errcode ;
2005-04-17 02:20:36 +04:00
}
2012-02-20 07:52:38 +04:00
int capi_decode_conn_actv_ind ( struct pcbit_chan * chan , struct sk_buff * skb )
2005-04-17 02:20:36 +04:00
{
2012-02-20 07:52:38 +04:00
ushort len ;
2005-04-17 02:20:36 +04:00
# ifdef DEBUG
2012-02-20 07:52:38 +04:00
char str [ 32 ] ;
2005-04-17 02:20:36 +04:00
# endif
2012-02-20 07:52:38 +04:00
/* Yet Another Bearer Capability */
skb_pull ( skb , * ( skb - > data ) + 1 ) ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
/* Connected Party Number */
len = * ( skb - > data ) ;
2005-04-17 02:20:36 +04:00
# ifdef DEBUG
if ( len > 1 & & len < 31 ) {
2007-03-28 01:55:52 +04:00
skb_copy_from_linear_data_offset ( skb , 2 , str , len - 1 ) ;
2005-04-17 02:20:36 +04:00
str [ len ] = 0 ;
printk ( KERN_DEBUG " Connected Party Number: %s \n " , str ) ;
}
else
printk ( KERN_DEBUG " actv_ind CPN len = %d \n " , len ) ;
# endif
2012-02-20 07:52:38 +04:00
skb_pull ( skb , len + 1 ) ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
/* Connected Subaddress */
skb_pull ( skb , * ( skb - > data ) + 1 ) ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
/* Low Layer Capability */
skb_pull ( skb , * ( skb - > data ) + 1 ) ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
/* High Layer Capability */
skb_pull ( skb , * ( skb - > data ) + 1 ) ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
2012-02-20 07:52:38 +04:00
int capi_decode_conn_actv_conf ( struct pcbit_chan * chan , struct sk_buff * skb )
2005-04-17 02:20:36 +04:00
{
2012-02-20 07:52:38 +04:00
ushort errcode ;
errcode = * ( ( ushort * ) skb - > data ) ;
skb_pull ( skb , 2 ) ;
/* Channel Identification
skb_pull ( skb , skb - > data [ 0 ] + 1 ) ;
*/
return errcode ;
2005-04-17 02:20:36 +04:00
}
int capi_decode_sel_proto_conf ( struct pcbit_chan * chan , struct sk_buff * skb )
{
2012-02-20 07:52:38 +04:00
ushort errcode ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
chan - > layer2link = * ( skb - > data ) ;
skb_pull ( skb , 1 ) ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
errcode = * ( ( ushort * ) skb - > data ) ;
skb_pull ( skb , 2 ) ;
return errcode ;
2005-04-17 02:20:36 +04:00
}
int capi_decode_actv_trans_conf ( struct pcbit_chan * chan , struct sk_buff * skb )
{
2012-02-20 07:52:38 +04:00
ushort errcode ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
if ( chan - > layer2link ! = * ( skb - > data ) )
printk ( " capi_decode_actv_trans_conf: layer2link doesn't match \n " ) ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
skb_pull ( skb , 1 ) ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
errcode = * ( ( ushort * ) skb - > data ) ;
skb_pull ( skb , 2 ) ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
return errcode ;
2005-04-17 02:20:36 +04:00
}
int capi_decode_disc_ind ( struct pcbit_chan * chan , struct sk_buff * skb )
{
2012-02-20 07:52:38 +04:00
ushort len ;
2005-04-17 02:20:36 +04:00
# ifdef DEBUG
2012-02-20 07:52:38 +04:00
int i ;
2005-04-17 02:20:36 +04:00
# endif
2012-02-20 07:52:38 +04:00
/* Cause */
len = * ( skb - > data ) ;
skb_pull ( skb , 1 ) ;
2005-04-17 02:20:36 +04:00
# ifdef DEBUG
2012-02-20 07:52:38 +04:00
for ( i = 0 ; i < len ; i + + )
printk ( KERN_DEBUG " Cause Octect %d: %02x \n " , i + 3 ,
* ( skb - > data + i ) ) ;
2005-04-17 02:20:36 +04:00
# endif
2012-02-20 07:52:38 +04:00
skb_pull ( skb , len ) ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
# ifdef DEBUG
int capi_decode_debug_188 ( u_char * hdr , ushort hdrlen )
{
2012-02-20 07:52:38 +04:00
char str [ 64 ] ;
int len ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
len = hdr [ 0 ] ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
if ( len < 64 & & len = = hdrlen - 1 ) {
memcpy ( str , hdr + 1 , hdrlen - 1 ) ;
str [ hdrlen - 1 ] = 0 ;
printk ( " %s \n " , str ) ;
}
else
printk ( " debug message incorrect \n " ) ;
2005-04-17 02:20:36 +04:00
2012-02-20 07:52:38 +04:00
return 0 ;
}
# endif