Add helper functions to encode and decode L3 messages

Signed-off-by: Karsten Keil <kkeil@linux-pingi.de>
This commit is contained in:
Karsten Keil 2011-06-15 10:49:19 +02:00 committed by Karsten Keil
parent 10444c84e6
commit 45a0d3b856
2 changed files with 741 additions and 11 deletions

View File

@ -149,6 +149,7 @@
#define CAUSE_NORMALUNSPECIFIED 31
#define CAUSE_NO_CHANNEL 34
#define CAUSE_TEMPORARY_FAILURE 41
#define CAUSE_REQUESTED_CHANNEL 44
#define CAUSE_RESOURCES_UNAVAIL 47
#define CAUSE_INVALID_CALLREF 81
#define CAUSE_INCOMPATIBLE_DEST 88
@ -162,15 +163,6 @@
#define NO_CAUSE 254
/*
* Progress values
*/
#define PROGRESS_NOT_E2E_ISDN 1
#define PROGRESS_DEST_NOT_ISDN 2
#define PROGRESS_ORIG_NOT_ISDN 3
#define PROGRESS_RET_TO_ISDN 4
#define PROGRESS_TONE 8
/*
* Parser error codes
*/
@ -181,6 +173,118 @@
#define Q931_ERROR_IELEN 0x100000
#define Q931_ERROR_UNKNOWN 0x200000
#define Q931_ERROR_COMPREH 0x400000
#define Q931_ERROR_IESEQ 0x800000 /* do not carein our implementation */
#define Q931_ERROR_IESEQ 0x800000 /* do not care in our implementation */
/* Bearer capability */
#define Q931_CAP_SPEECH 0x00
#define Q931_CAP_UNRES_DIGITAL 0x08
#define Q931_CAP_RES_DIGITAL 0x09
#define Q931_CAP_3KHZ_AUDIO 0x10
#define Q931_CAP_7KHZ_AUDIO 0x11
#define Q931_CAP_VIDEO 0x18
/* Bearer L1 user info */
#define Q931_L1INFO_V110 0x01
#define Q931_L1INFO_ULAW 0x02
#define Q931_L1INFO_ALAW 0x03
#define Q931_L1INFO_G721 0x04
#define Q931_L1INFO_G722_5 0x05
#define Q931_L1INFO_G7XX_VIDEO 0x06
#define Q931_L1INFO_NONE_CCITT 0x07
#define Q931_L1INFO_V120 0x08
#define Q931_L1INFO_X31 0x09
struct misdn_channel_info {
unsigned char nr; /* channel number/slot or special */
unsigned char flags; /* exclusiv, not Basic, ANY, NONE */
unsigned char type; /* B-channel, D-channel, H0, H11, H12 */
unsigned char ctrl; /* Allocated, updated, needsend, sent */
} __attribute__((packed));
/*
* special channel number defines
*/
#define MI_CHAN_ANY 0xff
#define MI_CHAN_NONE 0xfe
#define MI_CHAN_DCHANNEL 0xfd
#define MI_CHAN_FLG_NONE 0x01
#define MI_CHAN_FLG_ANY 0x02
#define MI_CHAN_FLG_DCHANNEL 0x04
#define MI_CHAN_FLG_EXCLUSIVE 0x08
#define MI_CHAN_FLG_OTHER_IF 0x20
#define MI_CHAN_TYP_NONE 0
#define MI_CHAN_TYP_B 1
#define MI_CHAN_TYP_D 2
#define MI_CHAN_TYP_H0 3
#define MI_CHAN_TYP_H11 4
#define MI_CHAN_TYP_H12 5
#define MI_CHAN_CTRL_UPDATED 0x01
#define MI_CHAN_CTRL_NEEDSEND 0x02
#define MI_CHAN_CTRL_SENT 0x04
#define MI_CHAN_CTRL_ALLOCATED 0x10
#define MI_CHAN_CTRL_DOWN 0x20
/* progress info */
struct misdn_progress_info {
unsigned char loc; /* location, octet 3 */
unsigned char desc; /* description, octet 3 */
unsigned char resv; /* reserved */
unsigned char ctrl; /* ctrl info flags */
} __attribute__((packed));
/*
* Q931 location
*/
#define Q931_LOC_USER 0
#define Q931_LOC_PRVN_LOCUSER 1
#define Q931_LOC_PUBN_LOCUSER 2
#define Q931_LOC_PUBN_RMTUSER 4
#define Q931_LOC_PRVN_RMTUSER 5
#define Q931_LOC_INTERNATIONAL 7
/*
* Progress values
*/
#define PROGRESS_NOT_E2E_ISDN 1
#define PROGRESS_DEST_NOT_ISDN 2
#define PROGRESS_ORIG_NOT_ISDN 3
#define PROGRESS_RET_TO_ISDN 4
#define PROGRESS_INBAND 8
/* Progress control flags */
#define MI_PROG_CTRL_UPDATED 0x01
#define MI_PROG_CTRL_NEEDSEND 0x02
#define MI_PROG_CTRL_SENT 0x04
/* Common IE encode helpers */
struct l3_msg;
extern int mi_encode_bearer(struct l3_msg *, unsigned int, unsigned int, unsigned int, unsigned int);
extern int mi_encode_channel_id(struct l3_msg *, struct misdn_channel_info *);
extern int mi_encode_calling_nr(struct l3_msg *, char *, int, unsigned int, unsigned int, unsigned int);
extern int mi_encode_called_nr(struct l3_msg *, char *, unsigned int, unsigned int);
extern int mi_encode_redir_nr(struct l3_msg *, char *, int, unsigned int, unsigned int, unsigned int, int);
extern int mi_encode_useruser(struct l3_msg *, int, int, char *);
extern int mi_encode_cause(struct l3_msg *l, int cause, int, int, unsigned char *);
extern int mi_encode_progress(struct l3_msg *, struct misdn_progress_info *);
extern int mi_encode_date(struct l3_msg *, time_t);
/* Common IE decode helpers */
extern int mi_decode_progress(struct l3_msg *, struct misdn_progress_info *);
extern int mi_decode_bearer_capability(struct l3_msg *, int *, int *, int *, int *, int *,
int *, int *, int *, int *, int *, int *, int *, int *, int *);
extern int mi_decode_cause(struct l3_msg *, int *, int *, int *, int *, int *, unsigned char *);
extern int mi_decode_channel_id(struct l3_msg *, struct misdn_channel_info *);
extern int mi_decode_calling_nr(struct l3_msg *, int *, int *, int *, int *, char *);
extern int mi_decode_called_nr(struct l3_msg *, int *, int *, char *);
extern int mi_decode_display(struct l3_msg *, char *, int);
extern int mi_decode_useruser(struct l3_msg *, int *, int *, char *, int);
/* some print helpers */
extern const char *mi_bearer2str(int);
extern const char *mi_msg_type2str(unsigned int);
#endif

View File

@ -5,6 +5,7 @@
* Author Karsten Keil <kkeil@novell.com>
*
* Copyright 2007 by Karsten Keil <kkeil@novell.com>
* Copyright 2010 by Karsten Keil <kkeil@linux-pingi.de>
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
@ -202,7 +203,7 @@ int
assembleQ931(l3_process_t *pc, struct l3_msg *l3m)
{
struct mbuffer *mb = container_of(l3m, struct mbuffer, l3);
unsigned char ie = 0, **v_ie = &l3m->bearer_capability;
unsigned char ie, **v_ie = &l3m->bearer_capability;
int i, l, eidx = -1;
mb->data = mb->tail = mb->head;
@ -302,3 +303,628 @@ add_layer3_ie(struct l3_msg *l3m, unsigned char ie, int len, unsigned char *data
}
return 0;
}
/* helper functions to encode common Q931 info elements */
int
mi_encode_bearer(struct l3_msg *l3m, unsigned int capability, unsigned int l1user, unsigned int mode, unsigned int rate)
{
unsigned char ie[8];
int l = 2, multi = -1, user;
user = l1user;
switch (capability) {
case Q931_CAP_UNRES_DIGITAL:
user = -1;
break;
case Q931_CAP_RES_DIGITAL:
user = -1;
break;
default:
rate = 0x10;
mode = 0;
break;
}
ie[0] = 0x80 | capability;
ie[1] = 0x80 | (mode << 5) | rate;
if (multi >= 0) {
ie[2] = 0x80 | multi;
l++;
}
if (user >= 0) {
ie[l] = 0xa0 | user;
l++;
}
return add_layer3_ie(l3m, IE_BEARER, l, ie);
}
int
mi_encode_channel_id(struct l3_msg *l3m, struct misdn_channel_info *ci)
{
unsigned char ie[3];
int ret, l, excl = 1;
if (ci->ctrl & MI_CHAN_CTRL_SENT) /* already sent */
return 0;
if (!(ci->ctrl & MI_CHAN_CTRL_NEEDSEND)) /* we do not need send the ie */
return 0;
if (ci->nr == MI_CHAN_ANY || ci->nr == MI_CHAN_NONE ||
(ci->flags & MI_CHAN_FLG_NONE) || (ci->flags & MI_CHAN_FLG_ANY))
excl = 0;
if (ci->flags & MI_CHAN_FLG_OTHER_IF) { /* PRI */
if (ci->nr == MI_CHAN_NONE)
return 0; /* IE is not included */
else if (ci->nr == MI_CHAN_ANY || (ci->flags & MI_CHAN_FLG_ANY)) {
l = 1;
ie[0] = 0x80 | 0x20 | 0x03;
} else {
l = 3;
ie[0] = 0x80 | 0x20 | (excl << 3) | 1;
if (ci->type & MI_CHAN_TYP_H0)
ie[1] = 0x86;
else if (ci->type & MI_CHAN_TYP_H11)
ie[1] = 0x88;
else if (ci->type & MI_CHAN_TYP_H12)
ie[1] = 0x89;
else /* default B-channel */
ie[1] = 0x83;
ie[2] = 0x80 | ci->nr;
}
} else { /* BRI */
l = 1;
if (ci->nr == MI_CHAN_DCHANNEL || ci->type == MI_CHAN_TYP_D || (ci->flags & MI_CHAN_FLG_DCHANNEL))
ie[0] = MI_CHAN_FLG_DCHANNEL;
else if (ci->nr == MI_CHAN_ANY || (ci->flags & MI_CHAN_FLG_ANY))
ie[0] = 3;
else if (ci->nr == MI_CHAN_NONE || (ci->flags & MI_CHAN_FLG_NONE))
ie[0] = 0;
else
ie[0] = ci->nr & 3;
ie[0] |= 0x80 | (excl << 3);
}
ret = add_layer3_ie(l3m, IE_CHANNEL_ID, l, ie);
if (!ret) {
ci->ctrl |= MI_CHAN_CTRL_SENT;
ci->ctrl &= ~MI_CHAN_CTRL_SENT;
}
return ret;
}
int
mi_encode_calling_nr(struct l3_msg *l3m, char *nr, int pres, unsigned int screen, unsigned int type, unsigned int plan)
{
unsigned char ie[32];
int l;
if (pres < 0 && screen < 0 && (nr == NULL || *nr == 0)) /* defaults, no number provided */
return 0;
if (nr && strlen(nr) > 30)
return -EINVAL;
if (pres >= 0) {
l = 2;
ie[0] = (type << 4) | plan;
ie[1] = 0x80 | (pres << 5) | screen;
} else {
l = 1;
ie[0] = 0x80 | (type << 4) | plan;
}
if (nr && *nr) {
strncpy((char *)&ie[l], nr, 30);
l += strlen(nr);
}
return add_layer3_ie(l3m, IE_CALLING_PN, l, ie);
}
int
mi_encode_called_nr(struct l3_msg *l3m, char *nr, unsigned int type, unsigned int plan)
{
unsigned char ie[32];
int l;
if (nr == NULL || *nr == 0) /* not provided */
return 0;
if (nr && strlen(nr) > 30)
return -EINVAL;
l = 1;
ie[0] = 0x80 | (type << 4) | plan;
if (nr && *nr) {
strncpy((char *)&ie[l], nr, 30);
l += strlen(nr);
}
return add_layer3_ie(l3m, IE_CALLED_PN, l, ie);
}
int
mi_encode_redir_nr(struct l3_msg *l3m, char *nr, int pres, unsigned int screen, unsigned int type, unsigned int plan, int reason)
{
unsigned char ie[34];
int l;
if (nr == NULL || *nr == 0) /* not provided */
return 0;
if (nr && strlen(nr) > 30)
return -EINVAL;
if (pres >= 0) {
l = 2;
ie[0] = (type << 4) | plan;
ie[1] = (pres << 5) | screen;
if (reason >= 0) {
l++;
ie[2] = 0x80 | reason;
} else
ie[1] |= 0x80;
} else {
l = 1;
ie[0] = 0x80 | (type << 4) | plan;
}
if (nr && *nr) {
strncpy((char *)&ie[l], nr, 30);
l += strlen(nr);
}
return add_layer3_ie(l3m, IE_REDIR_NR, l, ie);
}
int
mi_encode_useruser(struct l3_msg *l3m, int protocol, int len, char *data)
{
unsigned char ie[256];
if (len <= 0) /* not included */
return 0;
if (len > 250 || !data)
return -EINVAL;
if (protocol<0 || protocol>127)
return -EINVAL;
ie[0] = protocol & 0xff;
memcpy(&ie[1], data, len);
return add_layer3_ie(l3m, IE_USER_USER, len + 1, ie);
}
int
mi_encode_cause(struct l3_msg *l3m, int cause, int loc, int dlen, unsigned char *diag)
{
unsigned char ie[32];
int l;
if (cause < 0 || cause == NO_CAUSE) /* not included */
return 0;
if (cause > 127)
return -EINVAL;
if (loc < 0 || loc > 7)
return -EINVAL;
if (dlen > 30)
return -EINVAL;
if (dlen && !diag)
return -EINVAL;
l = 2 + dlen;
ie[0] = 0x80 | loc;
ie[1] = 0x80 | cause;
if (dlen)
memcpy(&ie[2], diag, dlen);
return add_layer3_ie(l3m, IE_CAUSE, l, ie);
}
int
mi_encode_progress(struct l3_msg *l3m, struct misdn_progress_info *prg)
{
unsigned char ie[2];
int ret;
if (prg->ctrl & MI_PROG_CTRL_SENT)
return 0;
if (!(prg->ctrl & MI_PROG_CTRL_NEEDSEND))
return 0;
ie[0] = 0x80 | prg->loc;
ie[1] = 0x80 | prg->desc;
ret = add_layer3_ie(l3m, IE_PROGRESS, 2, ie);
if (!ret) {
prg->ctrl |= MI_PROG_CTRL_SENT;
prg->ctrl &= ~MI_PROG_CTRL_SENT;
}
return ret;
}
int
mi_encode_date(struct l3_msg *l3m, time_t ti)
{
unsigned char ie[5];
struct tm tm;
localtime_r(&ti, &tm);
ie[0] = tm.tm_year % 100;
ie[1] = tm.tm_mon + 1;
ie[2] = tm.tm_mday;
ie[3] = tm.tm_hour;
ie[4] = tm.tm_min;
return add_layer3_ie(l3m, IE_DATE, 5, ie);
}
/* helper functions to decode common IE */
#define _ASSIGN_PVAL(p, v) if (p) *p = (v)
int
mi_decode_progress(struct l3_msg *l3m, struct misdn_progress_info *progress)
{
struct misdn_progress_info prg;
if (l3m == NULL || !l3m->progress)
return 0;
if (l3m->progress[0] < 2)
return -EINVAL;
prg.loc = l3m->progress[1] & 0x7f;
prg.desc = l3m->progress[2] & 0x7f;
prg.ctrl = MI_PROG_CTRL_UPDATED;
_ASSIGN_PVAL(progress, prg);
return 0;
}
int
mi_decode_bearer_capability(struct l3_msg *l3m, int *coding, int *capability, int *mode, int *rate,
int *oct_4a, int *oct_4b, int *oct_5, int *oct_5a, int *oct_5b1,
int *oct_5b2, int *oct_5c, int *oct_5d, int *oct_6, int *oct_7)
{
int opt[10];
int i,j;
enum {
octet_4a = 0,
octet_4b = 1,
octet_5 = 2,
octet_5a = 3,
octet_5b1 = 4,
octet_5b2 = 5,
octet_5c = 6,
octet_5d = 7,
octet_6 = 8,
octet_7 = 9
};
if (!l3m->bearer_capability || *l3m->bearer_capability < 2)
return -EINVAL;
_ASSIGN_PVAL(coding, (l3m->bearer_capability[1] & 0x60) >> 5);
_ASSIGN_PVAL(capability, l3m->bearer_capability[1] & 0x1f);
_ASSIGN_PVAL(mode, (l3m->bearer_capability[2] & 0x60) >> 5);
_ASSIGN_PVAL(rate, l3m->bearer_capability[2] & 0x1f);
/* Now the optional octets */
for (j = 0; j < 10; j++)
opt[j] = -1;
i = 2;
if (*l3m->bearer_capability <= i)
goto done;
if (!(l3m->bearer_capability[i] & 0x80)) {
i++;
j = octet_4a;
opt[j] = l3m->bearer_capability[i];
if (*l3m->bearer_capability <= i)
goto done;
j++; /* octet4b */
if (!(l3m->bearer_capability[i] & 0x80)) {
i++;
opt[j] = l3m->bearer_capability[i];
}
}
i++;
if (*l3m->bearer_capability < i)
goto done;
opt[octet_5] = l3m->bearer_capability[i];
if (*l3m->bearer_capability <= i)
goto done;
j = octet_5a;
while (j <= octet_5d && *l3m->bearer_capability > i) {
if (l3m->bearer_capability[i] & 0x80)
break;
i++;
opt[j] = l3m->bearer_capability[i];
j++;
}
i++;
if (*l3m->bearer_capability < i)
goto done;
opt[octet_6] = l3m->bearer_capability[i];
i++;
if (*l3m->bearer_capability < i)
goto done;
opt[octet_7] = l3m->bearer_capability[i];
done:
_ASSIGN_PVAL(oct_4a, opt[octet_4a]);
_ASSIGN_PVAL(oct_4b, opt[octet_4b]);
_ASSIGN_PVAL(oct_5, opt[octet_5]);
_ASSIGN_PVAL(oct_5a, opt[octet_5a]);
_ASSIGN_PVAL(oct_5b1, opt[octet_5b1]);
_ASSIGN_PVAL(oct_5b2, opt[octet_5b2]);
_ASSIGN_PVAL(oct_5c, opt[octet_5c]);
_ASSIGN_PVAL(oct_5d, opt[octet_5d]);
_ASSIGN_PVAL(oct_6, opt[octet_6]);
_ASSIGN_PVAL(oct_7, opt[octet_7]);
return 0;
};
int
mi_decode_cause(struct l3_msg *l3m, int *coding, int *loc, int *rec, int *val, int *dialen, unsigned char *dia)
{
int r = 0, l = 2, dl = 0;
if (l3m == NULL || !l3m->cause)
return 0;
if (*l3m->cause < 2)
return -EINVAL;
_ASSIGN_PVAL(coding, (l3m->cause[1] & 0x60) >> 5);
_ASSIGN_PVAL(loc, l3m->cause[1] & 0x0f);
if (!(l3m->cause[1] & 0x80)) {
r = l3m->cause[2] & 0x7f;
l++;
} else
r = 0;
_ASSIGN_PVAL(rec, r);
_ASSIGN_PVAL(val, l3m->cause[l] & 0x7f);
dl = *l3m->cause - l;
if (dl > 0 && dia)
memcpy(dia, &l3m->cause[l + 1], dl);
_ASSIGN_PVAL(dialen, dl);
return 0;
}
int
mi_decode_channel_id(struct l3_msg *l3m, struct misdn_channel_info *cip)
{
struct misdn_channel_info c = {MI_CHAN_NONE, 0, 0, 0};
if (l3m == NULL || !l3m->channel_id)
return 0;
if (*l3m->channel_id == 0)
return 0;
if (!cip)
return 0;
c.ctrl = cip->ctrl & (MI_CHAN_CTRL_ALLOCATED | MI_CHAN_CTRL_NEEDSEND | MI_CHAN_CTRL_SENT);
/* We ignore explicit interface settings */
c.flags = l3m->channel_id[1] & 0x2c;
switch (l3m->channel_id[1] & 3) {
case 0:
c.nr = MI_CHAN_NONE;
c.flags |= MI_CHAN_FLG_NONE;
break;
case 3:
c.nr = MI_CHAN_ANY;
c.flags |= MI_CHAN_FLG_ANY;
break;
default:
c.nr = l3m->channel_id[1] & 3;
}
if ((c.flags & MI_CHAN_FLG_OTHER_IF) == 0) { /* BRI */
if (c.flags & MI_CHAN_FLG_DCHANNEL) {
c.nr = MI_CHAN_DCHANNEL;
c.flags &= 0xfc; /* clear NONE,ANY */
c.type = MI_CHAN_TYP_D;
} else
c.type = MI_CHAN_TYP_B;
} else { /* PRI */
if (*l3m->channel_id < 2)
return -EINVAL;
/* We ignore coding so CCITT/ETSI is assumed, no support for multiple channels or channelmaps */
switch (l3m->channel_id[2] & 0x7f) {
default:
case 3:
c.type = MI_CHAN_TYP_B;
break;
case 6:
c.type = MI_CHAN_TYP_H0;
break;
case 8:
c.type = MI_CHAN_TYP_H11;
break;
case 9:
c.type = MI_CHAN_TYP_H12;
break;
}
if (*l3m->channel_id > 2 && ((c.flags & (MI_CHAN_FLG_ANY | MI_CHAN_FLG_NONE)) == 0))
c.nr = l3m->channel_id[3];
}
if (cip->nr != c.nr || cip->type != c.type || cip->flags != c.flags)
c.ctrl |= MI_CHAN_CTRL_UPDATED;
_ASSIGN_PVAL(cip, c);
return 0;
}
int
mi_decode_calling_nr(struct l3_msg *l3m, int *type, int *plan, int *pres, int *screen, char *nr)
{
int _pres = 0, _screen = 0, i = 2, l;
if (l3m == NULL || !l3m->calling_nr)
return 0;
if (*l3m->calling_nr < 2)
return -EINVAL;
if (*l3m->calling_nr > 32)
return -EINVAL;
_ASSIGN_PVAL(type, (l3m->calling_nr[1] & 0x70) >> 4);
_ASSIGN_PVAL(plan, l3m->calling_nr[1] & 0x0f);
if ((l3m->calling_nr[1] & 0x80) == 0 && *l3m->calling_nr >= 2) {
_pres = (l3m->calling_nr[2] & 0x60) >> 5;
_screen = l3m->calling_nr[2] & 0x03;
i++;
}
l = *l3m->calling_nr + 1 - i;
if (nr) {
memcpy(nr, &l3m->calling_nr[i], l);
nr[l] = 0;
}
_ASSIGN_PVAL(pres, _pres);
_ASSIGN_PVAL(screen, _screen);
return 0;
}
int
mi_decode_called_nr(struct l3_msg *l3m, int *type, int *plan, char *nr)
{
int l;
if (l3m == NULL || !l3m->called_nr)
return 0;
if (*l3m->called_nr < 1)
return -EINVAL;
if (*l3m->called_nr > 32)
return -EINVAL;
_ASSIGN_PVAL(type, (l3m->called_nr[1] & 0x70) >> 4);
_ASSIGN_PVAL(plan, l3m->called_nr[1] & 0x0f);
l = *l3m->called_nr - 1;
if (nr) {
memcpy(nr, &l3m->called_nr[2], l);
nr[l] = 0;
}
return 0;
}
int
mi_decode_display(struct l3_msg *l3m, char *display, int maxlen)
{
if (l3m == NULL || !l3m->display)
return 0;
if (!display)
return 0;
maxlen--;
if (*l3m->display < maxlen)
maxlen = *l3m->display;
memcpy(display, &l3m->display[1], maxlen);
display[maxlen] = 0;
return 0;
}
int
mi_decode_useruser(struct l3_msg *l3m, int *pd, int *uulen, char *uu, int maxlen)
{
int l;
if (l3m == NULL || !l3m->useruser)
return 0;
if (!uu)
return 0;
if (*l3m->useruser < 1)
return 0;
if (*l3m->useruser < maxlen)
l = *l3m->useruser - 1;
else
l = maxlen;
if (l > 0)
memcpy(uu, &l3m->useruser[2], l);
_ASSIGN_PVAL(uulen, l);
_ASSIGN_PVAL(pd, l3m->useruser[1]);
return 0;
}
const char *
mi_bearer2str(int cap)
{
static char *bearers[] = {
"Speech",
"Audio 3.1 kHz",
"Audio 7 kHz",
"Unrestricted Digital",
"Restricted Digital",
"Video",
"Unknown Bearer"
};
switch (cap) {
case Q931_CAP_SPEECH:
return bearers[0];
break;
case Q931_CAP_3KHZ_AUDIO:
return bearers[1];
break;
case Q931_CAP_7KHZ_AUDIO:
return bearers[2];
break;
case Q931_CAP_UNRES_DIGITAL:
return bearers[3];
break;
case Q931_CAP_RES_DIGITAL:
return bearers[4];
break;
case Q931_CAP_VIDEO:
return bearers[5];
break;
default:
return bearers[6];
break;
}
}
static const struct _cmdtab {
unsigned int cmd;
const char *name;
} cmdtab[] = {
{MT_ALERTING , "ALERTING"},
{MT_CALL_PROCEEDING , "CALL_PROCEEDING"},
{MT_CONNECT , "CONNECT"},
{MT_CONNECT_ACKNOWLEDGE , "CONNECT_ACKNOWLEDGE"},
{MT_PROGRESS , "PROGRESS"},
{MT_SETUP , "SETUP"},
{MT_SETUP_ACKNOWLEDGE , "SETUP_ACKNOWLEDGE"},
{MT_RESUME , "RESUME"},
{MT_RESUME_ACKNOWLEDGE , "RESUME_ACKNOWLEDGE"},
{MT_RESUME_REJECT , "RESUME_REJECT"},
{MT_SUSPEND , "SUSPEND"},
{MT_SUSPEND_ACKNOWLEDGE , "SUSPEND_ACKNOWLEDGE"},
{MT_SUSPEND_REJECT , "SUSPEND_REJECT"},
{MT_USER_INFORMATION , "USER_INFORMATION"},
{MT_DISCONNECT , "DISCONNECT"},
{MT_RELEASE , "RELEASE"},
{MT_RELEASE_COMPLETE , "RELEASE_COMPLETE"},
{MT_RESTART , "RESTART"},
{MT_RESTART_ACKNOWLEDGE , "RESTART_ACKNOWLEDGE"},
{MT_SEGMENT , "SEGMENT"},
{MT_CONGESTION_CONTROL , "CONGESTION_CONTROL"},
{MT_INFORMATION , "INFORMATION"},
{MT_FACILITY , "FACILITY"},
{MT_NOTIFY , "NOTIFY"},
{MT_STATUS , "STATUS"},
{MT_STATUS_ENQUIRY , "STATUS_ENQUIRY"},
{MT_HOLD , "HOLD"},
{MT_HOLD_ACKNOWLEDGE , "HOLD_ACKNOWLEDGE"},
{MT_HOLD_REJECT , "HOLD_REJECT"},
{MT_RETRIEVE , "RETRIEVE"},
{MT_RETRIEVE_ACKNOWLEDGE, "RETRIEVE_ACKNOWLEDGE"},
{MT_RETRIEVE_REJECT , "RETRIEVE_REJECT"},
{MT_REGISTER , "REGISTER"},
{MT_ASSIGN , "ASSIGN_PID"},
{MT_FREE , "FREE_PID"},
{MT_L2ESTABLISH , "L2ESTABLISH"},
{MT_L2RELEASE , "L2RELEASE"},
{MT_ERROR , "ERROR"},
{MT_TIMEOUT , "TIMEOUT"},
{MPH_ACTIVATE_IND , "MPH_ACTIVATE_IND"},
{MPH_DEACTIVATE_IND , "MPH_DEACTIVATE_IND"},
{MPH_INFORMATION_IND , "MPH_INFORMATION_IND"},
{0xFFFFFFFF , "UNKNOWN"}
};
const char *
mi_msg_type2str(unsigned int cmd)
{
struct _cmdtab *ct = cmdtab;
while (ct->cmd != 0xFFFFFFFF) {
if (ct->cmd == cmd)
break;
ct++;
}
if (ct->cmd == 0xFFFFFFFF)
return NULL;
else
return ct->name;
}