304 lines
8.1 KiB
C
304 lines
8.1 KiB
C
/* $Id$
|
|
*
|
|
* Basic declarations, defines and prototypes
|
|
*
|
|
* This file is (c) under GNU PUBLIC LICENSE
|
|
*
|
|
*/
|
|
#ifndef _mISDN_HELPER_H
|
|
#define _mISDN_HELPER_H
|
|
#include <linux/kernel.h>
|
|
#ifdef MISDN_MEMDEBUG
|
|
#include "memdbg.h"
|
|
#endif
|
|
|
|
/* shortcut to report errors locations, sometime also used for debugging !FIXME! */
|
|
#define int_error() \
|
|
printk(KERN_ERR "mISDN: INTERNAL ERROR in %s:%d\n", \
|
|
__FILE__, __LINE__)
|
|
|
|
/* shortcut to report errors locations with an additional message text */
|
|
#define int_errtxt(fmt, arg...) \
|
|
printk(KERN_ERR "mISDN: INTERNAL ERROR in %s:%d " fmt "\n", \
|
|
__FILE__, __LINE__, ## arg)
|
|
|
|
/* cleanup SKB queues, return count of dropped packets */
|
|
static inline int
|
|
discard_queue(struct sk_buff_head *q)
|
|
{
|
|
struct sk_buff *skb;
|
|
int ret=0;
|
|
|
|
while ((skb = skb_dequeue(q))) {
|
|
dev_kfree_skb(skb);
|
|
ret++;
|
|
}
|
|
return(ret);
|
|
}
|
|
|
|
/* allocate a SKB for DATA packets in the mISDN stack with enough headroom
|
|
* the MEMDEBUG version is for debugging memory leaks in the mISDN stack
|
|
*/
|
|
|
|
#ifdef MISDN_MEMDEBUG
|
|
#define alloc_stack_skb(s, r) __mid_alloc_stack_skb(s, r, __FILE__, __LINE__)
|
|
static inline struct sk_buff *
|
|
__mid_alloc_stack_skb(u_int size, u_int reserve, char *fn, int line)
|
|
{
|
|
struct sk_buff *skb;
|
|
|
|
if (!(skb = __mid_alloc_skb(size + reserve, GFP_ATOMIC, fn, line)))
|
|
#else
|
|
static inline struct sk_buff *
|
|
alloc_stack_skb(u_int size, u_int reserve)
|
|
{
|
|
struct sk_buff *skb;
|
|
|
|
if (!(skb = alloc_skb(size + reserve, GFP_ATOMIC)))
|
|
#endif
|
|
printk(KERN_WARNING "%s(%d,%d): no skb size\n", __FUNCTION__,
|
|
size, reserve);
|
|
else
|
|
skb_reserve(skb, reserve);
|
|
return(skb);
|
|
}
|
|
|
|
/*
|
|
* mISDN_set_dchannel_pid(mISDN_pid_t *pid, int protocol, int layermask)
|
|
*
|
|
* set default values for the D-channel protocol ID struct
|
|
*
|
|
* layermask - bitmask which layers should be set (default 0,1,2,3,4)
|
|
* protocol - bitmask for special L2/L3 option (from protocol module parameter of L0 modules)
|
|
*/
|
|
extern void mISDN_set_dchannel_pid(mISDN_pid_t *, int, int);
|
|
|
|
/*
|
|
* int mISDN_get_lowlayer(int layermask)
|
|
*
|
|
* get the lowest layer number of a layermask
|
|
* e.g layermask=0x0c returns 2
|
|
*/
|
|
extern int mISDN_get_lowlayer(int);
|
|
|
|
/*
|
|
* int mISDN_get_up_layer(int layermask)
|
|
*
|
|
* get the next higher layer number, which is not part of the given layermask
|
|
*/
|
|
extern int mISDN_get_up_layer(int);
|
|
|
|
/*
|
|
* int mISDN_get_down_layer(int layermask)
|
|
*
|
|
* get the next lower layer number, which is not part of the given layermask
|
|
*/
|
|
extern int mISDN_get_down_layer(int);
|
|
|
|
/*
|
|
* int mISDN_layermask2layer(int layermask)
|
|
*
|
|
* translate bit position in layermask into the layernumber
|
|
* only valid if only one bit in the mask was set
|
|
*/
|
|
extern int mISDN_layermask2layer(int);
|
|
|
|
/*
|
|
* int mISDN_get_protocol(mISDNstack_t *st, int layer)
|
|
*
|
|
* get the protocol value of layer <layer> in stack <st>
|
|
*/
|
|
extern int mISDN_get_protocol(mISDNstack_t *, int);
|
|
|
|
/*
|
|
* int mISDN_HasProtocol(mISDNobject_t *obj, u_int protocol)
|
|
*
|
|
* test if given object can handle protocol <protocol>
|
|
*
|
|
* return 0 if yes
|
|
*
|
|
*/
|
|
extern int mISDN_HasProtocol(mISDNobject_t *, u_int);
|
|
|
|
/*
|
|
* int mISDN_SetHandledPID(mISDNobject_t *obj, mISDN_pid_t *pid)
|
|
*
|
|
* returns the layermask of the supported protocols of object <obj>
|
|
* from the protocol ID struct <pid>
|
|
*/
|
|
extern int mISDN_SetHandledPID(mISDNobject_t *, mISDN_pid_t *);
|
|
|
|
/*
|
|
* mISDN_RemoveUsedPID(mISDN_pid_t *pid, mISDN_pid_t *used)
|
|
*
|
|
* remove the protocol values from <pid> struct which are also in the
|
|
* <used> struct
|
|
*/
|
|
extern void mISDN_RemoveUsedPID(mISDN_pid_t *, mISDN_pid_t *);
|
|
|
|
/*
|
|
* mISDN_init_instance(mISDNinstance_t *inst, mISDNobject_t *obj, void *data)
|
|
*
|
|
* initialisize the mISDNinstance_t struct <inst>
|
|
*/
|
|
extern void mISDN_init_instance(mISDNinstance_t *, mISDNobject_t *, void *, if_func_t *);
|
|
|
|
/* returns the member count of a list */
|
|
static inline int
|
|
count_list_member(struct list_head *head)
|
|
{
|
|
int cnt = 0;
|
|
struct list_head *m;
|
|
|
|
list_for_each(m, head)
|
|
cnt++;
|
|
return(cnt);
|
|
}
|
|
|
|
/* same as mISDN_HasProtocol, but for a pointer */
|
|
static inline int
|
|
mISDN_HasProtocolP(mISDNobject_t *obj, int *PP)
|
|
{
|
|
if (!PP) {
|
|
int_error();
|
|
return(-EINVAL);
|
|
}
|
|
return(mISDN_HasProtocol(obj, *PP));
|
|
}
|
|
|
|
/* set primitiv and dinfo field of a internal (SKB) mISDN message */
|
|
static inline void
|
|
mISDN_sethead(u_int prim, int dinfo, struct sk_buff *skb)
|
|
{
|
|
mISDN_head_t *hh = mISDN_HEAD_P(skb);
|
|
|
|
hh->prim = prim;
|
|
hh->dinfo = dinfo;
|
|
}
|
|
|
|
static inline int mISDN_send_message(void) {return 0;};
|
|
static inline int mISDN_send_data(void) {return 0;};
|
|
static inline int mISDN_sendup(void) {return 0;};
|
|
static inline int mISDN_sendup_newhead(void) {return 0;};
|
|
static inline int mISDN_senddown(void) {return 0;};
|
|
static inline int mISDN_senddown_newhead(void) {return 0;};
|
|
|
|
|
|
#define mISDN_queue_up(i, a, s) mISDN_queue_message(i, a | FLG_MSG_UP, s)
|
|
#define mISDN_queue_down(i, a, s) mISDN_queue_message(i, a | FLG_MSG_DOWN, s)
|
|
|
|
static inline int
|
|
mISDN_queueup_newhead(mISDNinstance_t *inst, u_int aflag, u_int prim, int dinfo, struct sk_buff *skb)
|
|
{
|
|
mISDN_head_t *hh = mISDN_HEAD_P(skb);
|
|
|
|
hh->prim = prim;
|
|
hh->dinfo = dinfo;
|
|
return(mISDN_queue_up(inst, aflag, skb));
|
|
}
|
|
|
|
static inline int
|
|
mISDN_queuedown_newhead(mISDNinstance_t *inst, u_int aflag, u_int prim, int dinfo, struct sk_buff *skb)
|
|
{
|
|
mISDN_head_t *hh = mISDN_HEAD_P(skb);
|
|
|
|
hh->prim = prim;
|
|
hh->dinfo = dinfo;
|
|
return(mISDN_queue_down(inst, aflag, skb));
|
|
}
|
|
|
|
|
|
/* allocate a mISDN message SKB with enough headroom and set the header fields
|
|
* the MEMDEBUG version is for debugging memory leaks in the mISDN stack
|
|
*/
|
|
#ifdef MISDN_MEMDEBUG
|
|
#define create_link_skb(p, d, l, dp, r) __mid_create_link_skb(p, d, l, dp, r, __FILE__, __LINE__)
|
|
static inline struct sk_buff *
|
|
__mid_create_link_skb(u_int prim, int dinfo, u_int len, void *dp, u_int reserve, char *fn, int line)
|
|
{
|
|
struct sk_buff *skb;
|
|
mISDN_head_t *hh;
|
|
|
|
if (!(skb = __mid_alloc_skb(len + reserve, GFP_ATOMIC, fn, line))) {
|
|
#else
|
|
static inline struct sk_buff *
|
|
create_link_skb(u_int prim, int dinfo, u_int len, void *dp, u_int reserve)
|
|
{
|
|
struct sk_buff *skb;
|
|
mISDN_head_t *hh;
|
|
|
|
if (!(skb = alloc_skb(len + reserve, GFP_ATOMIC))) {
|
|
#endif
|
|
printk(KERN_WARNING "%s: no skb size %d+%d\n",
|
|
__FUNCTION__, len, reserve);
|
|
return(NULL);
|
|
} else
|
|
skb_reserve(skb, reserve);
|
|
if (len)
|
|
memcpy(skb_put(skb, len), dp, len);
|
|
hh = mISDN_HEAD_P(skb);
|
|
hh->prim = prim;
|
|
hh->dinfo = dinfo;
|
|
hh->len = len;
|
|
return(skb);
|
|
}
|
|
|
|
/* allocate a SKB for a mISDN message with enough headroom
|
|
* fill mesage data into this SKB and send it trough the interface
|
|
* the MEMDEBUG version is for debugging memory leaks in the mISDN stack
|
|
*/
|
|
#ifdef MISDN_MEMDEBUG
|
|
#define mISDN_queue_data(i, a, p, d, l, dp, r) __mid_queue_data(i, a, p, d, l, dp, r, __FILE__, __LINE__)
|
|
static inline int
|
|
__mid_queue_data(mISDNinstance_t *inst, u_int aflag, u_int prim, int dinfo, u_int len, void *dp, u_int reserve, char *fn, int line)
|
|
{
|
|
struct sk_buff *skb;
|
|
int err;
|
|
|
|
if (!(skb = __mid_create_link_skb(prim, dinfo, len, dp, reserve, fn, line)))
|
|
#else
|
|
static inline int
|
|
mISDN_queue_data(mISDNinstance_t *inst, u_int aflag, u_int prim, int dinfo, u_int len, void *dp, u_int reserve)
|
|
{
|
|
struct sk_buff *skb;
|
|
int err;
|
|
|
|
if (!(skb = create_link_skb(prim, dinfo, len, dp, reserve)))
|
|
#endif
|
|
return(-ENOMEM);
|
|
err = mISDN_queue_message(inst, aflag, skb);
|
|
if (err)
|
|
kfree_skb(skb);
|
|
return(err);
|
|
}
|
|
|
|
/* L3 data struct helper functions */
|
|
|
|
extern signed int mISDN_l3_ie2pos(u_char);
|
|
extern unsigned char mISDN_l3_pos2ie(int);
|
|
extern void mISDN_initQ931_info(Q931_info_t *);
|
|
#ifdef MISDN_MEMDEBUG
|
|
#define mISDN_alloc_l3msg(a, b) __mid_alloc_l3msg(a, b, __FILE__, __LINE__)
|
|
extern struct sk_buff *__mid_alloc_l3msg(int, u_char, char *, int);
|
|
#else
|
|
extern struct sk_buff *mISDN_alloc_l3msg(int, u_char);
|
|
#endif
|
|
extern void mISDN_AddvarIE(struct sk_buff *, u_char *);
|
|
extern void mISDN_AddIE(struct sk_buff *, u_char, u_char *);
|
|
extern void mISDN_LogL3Msg(struct sk_buff *);
|
|
|
|
/* manager default handler helper macros */
|
|
|
|
#define PRIM_NOT_HANDLED(p) case p: break
|
|
|
|
#define MGR_HASPROTOCOL_HANDLER(p,a,o) \
|
|
if ((MGR_HASPROTOCOL | REQUEST) == p) {\
|
|
if (a) {\
|
|
int prot = *((int *)a);\
|
|
return(mISDN_HasProtocol(o, prot));\
|
|
} else \
|
|
return(-EINVAL);\
|
|
}
|
|
|
|
#endif /* _mISDN_HELPER_H */
|