u-isdn/include/isdn_3.h

432 lines
14 KiB
C

#ifndef _ISDN_3
#define _ISDN_3
#ifdef __KERNEL__
#include <linux/types.h>
#include <linux/param.h>
#else
#include <sys/types.h>
#include <sys/param.h>
#endif
#include "streams.h"
#include "isdn_limits.h"
#include "config.h"
/**
** Interface of the Level 3 driver
**
** Streams module isdn3_3
**/
/* Forward decl's */
struct _isdn3_card;
struct _isdn3_conn;
struct _isdn3_talk;
/**
** One struct isdn3_card is allocated per connected card.
**/
typedef struct _isdn3_card { /* One per card */
struct _isdn3_talk *talk; /* Connections on the D channel. */
long id; /* Card ID, identifies the card to L4. */
struct _isdn3_card *next;
mblk_t *info; /* Protocols to attach */
ulong_t modes; /* Mask of permitted modes on this card. */
uchar_t nr; /* Card number, for L2. */
uchar_t TEI; /* For reference */
uchar_t dchans; /* Number of D channels per card. */
uchar_t bchans; /* Number of B channels per D channel. */
unsigned is_up:2;
} *isdn3_card;
/**
** A Handler talks across a L2 D-channel connection.
**
** Handlers are registered with isdn3_attach_hndl.
** You should never call a handler directly.
**/
/*
* Initialization
*/
typedef void (*P_hndl_init) (void);
/*
* Called when a new card is registered. This routine would usually set up
* protocol handlers for TEI management and for incoming connections.
*/
typedef void (*P_hndl_newcard) (struct _isdn3_card * card);
/*
* Incoming data. isUI != zero if this was an UI frame. Bit 1 of isUI is set if
* this is a broadcast packet.
*/
typedef int (*P_hndl_recv) (struct _isdn3_talk * talk, char isUI, mblk_t * data);
/*
* Add protcol specific information to the mblk.
*/
typedef void (*P_hndl_report) (struct _isdn3_conn * conn, mblk_t * data);
/*
* Data from the device. When talking through a D channel connection.
*/
typedef int (*P_hndl_send) (struct _isdn3_conn * conn, mblk_t * data);
/*
* Config string for the connection. "id" is the device which sent the data and
* presumably the one that should get the error message back. ;-)
*/
typedef int (*P_hndl_sendcmd) (struct _isdn3_conn * conn, ushort_t id, mblk_t * data);
/*
* Card or connection changes state. See primitives.h.
*/
typedef int (*P_hndl_chstate) (struct _isdn3_talk * talk, uchar_t ind, short add);
/*
* Notify when a talker is being killed (protocol down) if force == 1. If force
* == 0, handler should check if the protocol can be deactivated
* temporarily,eg. if no connections are active on it.
*/
typedef void (*P_hndl_kill) (struct _isdn3_talk * talk, char force);
/*
* Notify when a connection is being killed. If "force" is set, the connection
* must be aborted unconditionally. If not, shut it down normally.
*/
typedef void (*P_hndl_killconn) (struct _isdn3_conn * conn, char force);
/*
* Notify when isdn3_setup_conn got called.
*/
typedef void (*P_hndl_hook) (struct _isdn3_conn * conn);
/*
* Catch what's sent down to L2. If data returns NULL, forward nothing.
*/
typedef int (*P_hndl_proto) (struct _isdn3_conn * conn, mblk_t **data, char down);
typedef struct _isdn3_hndl {
struct _isdn3_hndl *next; /* Next handler */
uchar_t SAPI;
uchar_t broadcast;
P_hndl_init init;
P_hndl_newcard newcard; /* New card shows up */
P_hndl_chstate chstate; /* L2 goes up or down */
P_hndl_report report; /* Report settings */
P_hndl_recv recv; /* Data from L2 */
P_hndl_send send; /* Data from the device, if attached to a D
* channel connection */
P_hndl_sendcmd sendcmd; /* Config data */
P_hndl_kill kill; /* Say goodbye */
P_hndl_killconn killconn; /* terminate a connection */
P_hndl_hook hook; /* isdn3_setup_conn was called */
P_hndl_proto proto; /* Send cmd; used for catching protocol lists */
} *isdn3_hndl;
/**
** One struct isdn3_talk is created per L2 D-channel connection.
**
** Calls managed by this connection are chained off the struct.
**/
#define NITALK 11
#define NSTALK 5
typedef struct _isdn3_talk { /* one per card's D channel connection */
struct _isdn3_conn *conn; /* connections managed on this channel */
struct _isdn3_card *card; /* Back ref to my card */
struct _isdn3_talk *next; /* next talker (chained card->talk->next) */
struct _isdn3_hndl *hndl; /* Handler for this type of talk. */
uchar_t state; /* . Zero: first call / uninitialized. Others
* depend on the talker. */
long talki[NITALK];
void *talks[NSTALK];
} *isdn3_talk;
/**
** One struct isdn3_conn represents one ISDN call.
**/
#define STACK_LEN 30
#define NICONN 25
#define NSCONN 3
#define NBCONN 2
typedef struct _isdn3_conn {
struct _isdn3_card *card; /* Card this call is running on */
struct _isdn3_talk *talk; /* Back ref to management */
struct _isdn3_conn *next; /* Next connection (chained talk->conn->next) */
int conn_id; /* Sequence number to uniquely identify a connection */
long call_ref; /* Protocol dependent. Uniquely identifies
* this connection if used together with
* card/protocol/subprotocol. */
long subprotocol; /* Protocol dependent. Phone: Q931 vs Post
* vs... */
char stack[STACK_LEN]; /* Protocol stack to set up on this connection */
char site[STACK_LEN]; /* System to talk to */
int delay; /* don't get at it right away */
long conni[NICONN]; /* additional variables, handler dependent */
void *conns[NSCONN];
mblk_t *connb[NBCONN];
#ifdef NEW_TIMEOUT /* Grumble */
int start_timer;
int delay_timer;
int later_timer;
int disc_timer;
#endif /* Ignore this... */
uchar_t state; /* Protocol dependent. Zero means
* free&unassigned. */
uchar_t lockit; /* Lock against inadvertent free */
uchar_t bchan; /* number of B channel. Zero if none or
* through D. */
SUBDEV minor; /* minor number for data. Zero if none yet. */
SUBDEV fminor; /* minor number for control. Zero if none yet. */
ulong_t minorstate; /* Activity status. See below for flag bits. */
uchar_t hupdelay; /* Delay between sending PROTO_DISC and
* actually disconnecting, in seconds */
ushort_t id; /* If a protocol needs to delay a command */
mblk_t *id_msg; /* for some UL action to complete */
void *p_data; /* protocol specific */
long timerflags; /* for controlling timers */
} *isdn3_conn;
/** Minorstate flags */
/* State */
#define MS_INCOMING 02 /* This is an incoming connection */
#define MS_OUTGOING 04 /* This is an outgoing connection */
#define MS_CONN_NONE 000
#define MS_CONN_SETUP 010 /* B channel associated, but no data transfer yet */
#define MS_CONN_LISTEN 020 /* B channel connected, but connection not fully established */
#define MS_CONN 030 /* B channel connected */
#define MS_CONN_MASK 030
#define MS_CONN_TIMER 040 /* Supervisory timer running. The connection
* is forcibly terminated if it is not
* completed within two minutes. */
#define MS_BCHAN 0100 /* The B channel is known and set up. (if
* zero, it's connected through the D channel */
#define MS_WANTCONN 0200 /* Set on CMD_DIAL/ANSWER, clear on CMD_OFF. */
#define MS_DETACHED 0400 /* temporarily not connected */
/* Actions */
#define MS_DIR_SENT 01000 /* The directional info is sent to the
* device. */
#define MS_SETUP_MASK 06000 /* what attach has been sent */
#define MS_SETUP_NONE 00000
#define MS_SETUP_ATTACH 02000
#define MS_SETUP_LISTEN 04000
#define MS_SETUP_CONN 06000
#define MS_END_TIMER 010000 /* The delay timer to end the connection
* cleanly is running */
#define MS_SENTINFO 020000 /* Sent pertinent data up */
#define MS_DELAYING 040000 /* Wait a bit */
#define MS_INITPROTO 0100000 /* card protocols set */
#define MS_INITPROTO_SENT 0200000 /* asked for setup */
#define MS_NOMINOR 0400000
/*
* if set and ms->delay == zero, we got killconn. This is a hack...
*/
#define MS_CONNDELAY_TIMER 02000000 /* Delay sending PROTO_CONN because the
* back channel may get delayed */
#define MS_FORWARDING 04000000 /* Forwarding this call; in progress. */
#define MS_FORCING 010000000 /* call is enforced. */
/*
* Register a handler
*/
int isdn3_attach_hndl (isdn3_hndl hndl);
/*
* send a reply back to a device. The bypass flag, if not set, causes the
* message to be passed through L4 to be formatted according to the handler's
* needs.
*/
int isdn3_at_send (isdn3_conn conn, mblk_t * data, char bypass);
/*
* send data to this D channel connection
*/
int isdn3_send (isdn3_talk talk, char what, mblk_t * data);
#define AS_DATA 0 /* I data */
#define AS_UIDATA 1 /* UI data */
#define AS_UIBROADCAST 2 /* UI broadcast data */
/*
* send data to the device
*/
int isdn3_send_conn (SUBDEV minor, char what, mblk_t * data);
#define AS_PROTO 3 /* Protocol setup */
#define AS_PROTO_NOERR 4 /* Protocol setup, don't report errors */
#define AS_XDATA 5 /* Data to be sent up to a device. When
* talking across the D channel. */
/*
* change the state of this connection
*/
int isdn3_chstate (isdn3_talk talk, uchar_t ind, short add, char what);
#define CH_MSG 0 /* send HDR_NOTIFY */
#define CH_OPENPROT 1 /* send HDR_OPENPROT */
#define CH_CLOSEPROT 2 /* send HDR_CLOSEPROT */
/*
* Find the handler for a specific SAPI. Returns NULL if not found.
*/
isdn3_hndl isdn3_findhndl (uchar_t SAPI);
/*
* Find the card with the appropriate ID.
*/
isdn3_card isdn3_findcard (uchar_t cardnr);
/*
* Find the card with the appropriate ID.
*/
isdn3_card isdn3_findcardid (ulong_t cardid);
/*
* Find the card with the appropriate name.
*/
isdn3_card isdn3_findcardsig (ulong_t cardsig);
/*
* Find the talk structure for this card/handler pair. Creates a new talker if
* not found and requested and info matches.
*/
isdn3_talk isdn3_findtalk (isdn3_card card, isdn3_hndl hndl, mblk_t *info, int create);
/*
* Drop the talker. Usually called by a handler when the last connection
* terminates.
*/
void isdn3_killtalk (isdn3_talk talk);
/*
* Drop the connection. If force is clear, run an ordinary shutdown procedure.
* If set, immediately forget the connection -- this is done when L2 dies.
*/
#ifdef CONFIG_DEBUG_ISDN
void deb_isdn3_killconn (isdn3_conn conn, char force, const char *deb_file, int deb_line);
#define isdn3_killconn(a,b) deb_isdn3_killconn(a,b,__FILE__,__LINE__)
#else
void isdn3_killconn (isdn3_conn conn, char force);
#endif
/*
* Find the connection this device is associated with.
*/
isdn3_conn isdn3_findminor (ushort_t minor);
/*
* Find the first connection this device is controlling.
*/
isdn3_conn isdn3_findatcmd (ushort_t minor);
/*
* Find the connection associated with this call_ref (valid for this protocol).
*/
isdn3_conn isdn3_findconn (isdn3_talk talk, long protocol, long call_ref);
/*
* Trigger connection chamge management.
*
* Setup the state flags in conn->minorstate and call isdn3_setup_conn whenever
* something changes.
*/
int Xisdn3_setup_conn (isdn3_conn conn, char established, const char*,unsigned);
#define isdn3_setup_conn(a,b) Xisdn3_setup_conn((a),(b),__FILE__,__LINE__)
#define EST_DISCONNECT 0 /* The connection is not established. */
#define EST_NO_REAL_CHANGE 2 /* Marker value. Do not use */
#define EST_WILL_DISCONNECT 4 /* The connection will be disconnected shortly. */
#define EST_NO_CHANGE 6 /* Something else happened (minorstate!) */
#define EST_SETUP 8 /* Associate with card channel */
#define EST_LISTEN 9 /* half-way communications, backwards */
#define EST_CONNECT 10 /* End-to-end connection is established */
/*
* Get a free call reference number.
*/
int isdn3_new_callref (isdn3_talk talk);
/*
* Find the next free B channel
*/
uchar_t isdn3_free_b (isdn3_card card);
/*
* get a new free connection and attach it to this talker.
*/
isdn3_conn isdn3_new_conn (isdn3_talk talk);
/*
* Send a header down; see isdn3_23.h. Handle with care. Used by the TEI
* handler.
*/
int isdn3_sendhdr (mblk_t * mb);
/*
* Try this again when conditions change.
*/
void isdn3_repeat (isdn3_conn conn, ushort_t id, mblk_t * data);
/*
* Add information about the connection to the mblk for reporting to L4.
*/
void conn_info (isdn3_conn conn, mblk_t * mb);
/*
* Extract flags from conn info.
*/
long isdn3_flags(mblk_t *info, uchar_t protocol, uchar_t subprot);
#define FL_UPDELAY 017
#define FL_UPDELAY_SHIFT 3
#define FL_L2KEEP 020 /* default is to close L2 */
#define FL_TEI_IMMED 040 /* default is to do that later */
#define FL_POINTOPOINT 0100 /* point-to-point */
#define FL_MULTIPOINT1 0200 /* variable ID */
#define FL_MULTIPOINT2 0000 /* fixed ID; special -> default */
#define FL_MULTIPOINT3 0300 /* fixed TEI */
#define FL_POINTMASK 0300
#define FL_ANS_IMMED 0400 /* default is to delay */
#define FL_BUG1 01000
#define FL_BUG2 02000
#define FL_BUG3 04000
/**
* Convenience macros for handling connection timeouts.
*
* // repeat for each timer XXX: //
* #define RUN_XXX 0001 // flag bit for this timer //
* #define VAL_XXX (xx * HZ) // timeout value for this timer //
* static void XXX(isdn3_conn conn); // timeout handler //
*
* timer(XXX,conn) registers a timeout and starts it if (conn->timerflags & IS_UP)
* untimer(XXX,conn) drops a timeout
* rtimer(XXX,conn) starts a timeout registered with timer() after L2 comes up
*/
#define IS_UP 001
#define UNTIMER(T,c,w,f) do { if((c)->timerflags & f) { untimeout(w,(c)); (c)->timerflags &=~ f; } } while(0)
#define untimer(T,c) UNTIMER(T,c,T,RUN_##T)
#define TIMER(T,c,w,v,f) do { if(!((c)->timerflags & f)) { if((c)->talk->state & IS_UP) timeout(w,(c),v); (c)->timerflags |= f; } } while(0)
#define timer(T,c) TIMER(T,(c),T,VAL_##T,RUN_##T)
#define ntimer(T,c,n) TIMER(T,(c),T,(n),RUN_##T)
#define FTIMER(T,c,w,v,f) do { if(!((c)->timerflags & f)) { timeout(w,(c),v); (c)->timerflags |= f; } } while(0)
#define ftimer(T,c) FTIMER(T,(c),T,VAL_##T,RUN_##T)
#define fntimer(T,c) FTIMER(T,(c),T,(n),RUN_##T)
#define RTIMER(T,c,w,v,f) do { if((c)->timerflags & f) { untimeout(w,(c)); timeout(w,(c),v); } } while(0)
#define rtimer(T,c) RTIMER(T,(c),T,VAL_##T,RUN_##T)
#define rntimer(T,c,n) RTIMER(T,(c),T,(n),RUN_##T)
#endif /* _ISDN_3 */