big rewrite of the CAPI 2.0 implementation
- hopefully easier to understand and follow the dataflow - no limitations in application count - clean shutdown on errors - use own kmem caches - reduce stack usage, use dynamic allocated cmsg
This commit is contained in:
parent
ffa91934b6
commit
85337c9851
|
@ -46,7 +46,7 @@ mISDN_core-objs := core.o stack.o udevice.o helper.o
|
|||
mISDN_l1-objs := layer1.o helper.o debug.o fsm.o
|
||||
mISDN_l2-objs := layer2.o tei.o helper.o debug.o fsm.o
|
||||
l3udss1-objs := layer3.o helper.o l3helper.o debug.o fsm.o l3_udss1.o
|
||||
mISDN_capi-objs := capi.o contr.o listen.o appl.o plci.o cplci.o ncci.o asn1.o \
|
||||
mISDN_capi-objs := capi.o contr.o listen.o appl.o plci.o app_plci.o ncci.o asn1.o \
|
||||
asn1_aoc.o asn1_comp.o asn1_generic.o asn1_diversion.o \
|
||||
asn1_basic_service.o asn1_address.o asn1_enc.o capi_enc.o \
|
||||
supp_serv.o helper.o l3helper.o debug.o fsm.o
|
||||
|
|
|
@ -46,7 +46,7 @@ mISDN_core-objs := core.o stack.o udevice.o helper.o
|
|||
mISDN_l1-objs := layer1.o helper.o debug.o fsm.o
|
||||
mISDN_l2-objs := layer2.o tei.o helper.o debug.o fsm.o
|
||||
l3udss1-objs := layer3.o helper.o l3helper.o debug.o fsm.o l3_udss1.o
|
||||
mISDN_capi-objs := capi.o contr.o listen.o appl.o plci.o cplci.o ncci.o asn1.o \
|
||||
mISDN_capi-objs := capi.o contr.o listen.o appl.o plci.o app_plci.o ncci.o asn1.o \
|
||||
asn1_aoc.o asn1_comp.o asn1_generic.o asn1_diversion.o \
|
||||
asn1_basic_service.o asn1_address.o asn1_enc.o capi_enc.o \
|
||||
supp_serv.o helper.o l3helper.o debug.o fsm.o
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,8 +1,14 @@
|
|||
/* $Id$
|
||||
*
|
||||
* Applications are owned by the controller and only
|
||||
* handle this controller, multiplexing multiple
|
||||
* controller with one application is done in the higher
|
||||
* driver independ CAPI driver. The application contain
|
||||
* the Listen state machine.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "capi.h"
|
||||
#include "m_capi.h"
|
||||
#include "helper.h"
|
||||
#include "debug.h"
|
||||
#include "mISDNManufacturer.h"
|
||||
|
@ -10,188 +16,370 @@
|
|||
#define applDebug(appl, lev, fmt, args...) \
|
||||
capidebug(lev, fmt, ## args)
|
||||
|
||||
void applConstr(Appl_t *appl, Contr_t *contr, __u16 ApplId, capi_register_params *rp)
|
||||
static struct list_head garbage_applications = LIST_HEAD_INIT(garbage_applications);
|
||||
|
||||
int
|
||||
ApplicationConstr(Controller_t *contr, __u16 ApplId, capi_register_params *rp)
|
||||
{
|
||||
memset(appl, 0, sizeof(Appl_t));
|
||||
Application_t *appl = kmalloc(sizeof(Application_t), GFP_KERNEL);
|
||||
|
||||
if (!appl) {
|
||||
return(-ENOMEM);
|
||||
}
|
||||
memset(appl, 0, sizeof(Application_t));
|
||||
INIT_LIST_HEAD(&appl->head);
|
||||
appl->contr = contr;
|
||||
appl->maxplci = contr->maxplci;
|
||||
appl->AppPlcis = kmalloc(appl->maxplci * sizeof(AppPlci_t *), GFP_KERNEL);
|
||||
if (!appl->AppPlcis) {
|
||||
kfree(appl);
|
||||
return(-ENOMEM);
|
||||
}
|
||||
memset(appl->AppPlcis, 0, appl->maxplci * sizeof(AppPlci_t *));
|
||||
appl->ApplId = ApplId;
|
||||
appl->MsgId = 1;
|
||||
appl->NotificationMask = 0;
|
||||
memcpy(&appl->rp, rp, sizeof(capi_register_params));
|
||||
listenConstr(&appl->listen, contr, ApplId);
|
||||
memcpy(&appl->reg_params, rp, sizeof(capi_register_params));
|
||||
listenConstr(appl);
|
||||
list_add(&appl->head, &contr->Applications);
|
||||
test_and_set_bit(APPL_STATE_ACTIV, &appl->state);
|
||||
return(0);
|
||||
}
|
||||
|
||||
void applDestr(Appl_t *appl)
|
||||
/*
|
||||
* Destroy the Application
|
||||
*
|
||||
* depending who initiate this we cannot release imediatly, if
|
||||
* any AppPlci is still in use.
|
||||
*
|
||||
* @who: 0 - a AppPlci is released in state APPL_STATE_RELEASE
|
||||
* 1 - Application is released from CAPI application
|
||||
* 2 - the controller is resetted
|
||||
* 3 - the controller is removed
|
||||
* 4 - the CAPI module will be unload
|
||||
*/
|
||||
int
|
||||
ApplicationDestr(Application_t *appl, int who)
|
||||
{
|
||||
int i;
|
||||
int i, used = 0;
|
||||
AppPlci_t **aplci_p = appl->AppPlcis;
|
||||
|
||||
listenDestr(&appl->listen);
|
||||
for (i = 0; i < CAPI_MAXPLCI; i++) {
|
||||
if (appl->cplcis[i]) {
|
||||
cplciDestr(appl->cplcis[i]);
|
||||
kfree(appl->cplcis[i]);
|
||||
appl->cplcis[i] = NULL;
|
||||
if (test_and_set_bit(APPL_STATE_DESTRUCTOR, &appl->state)) {
|
||||
// we are allready in this function
|
||||
return(-EBUSY);
|
||||
}
|
||||
test_and_set_bit(APPL_STATE_RELEASE, &appl->state);
|
||||
test_and_clear_bit(APPL_STATE_ACTIV, &appl->state);
|
||||
listenDestr(appl);
|
||||
if (who > 2) {
|
||||
appl->contr = NULL;
|
||||
}
|
||||
if (aplci_p) {
|
||||
for (i = 0; i < appl->maxplci; i++) {
|
||||
if (*aplci_p) {
|
||||
switch (who) {
|
||||
case 4:
|
||||
AppPlciDestr(*aplci_p);
|
||||
*aplci_p = NULL;
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
AppPlciRelease(*aplci_p);
|
||||
case 0:
|
||||
if ((volatile AppPlci_t *)(*aplci_p))
|
||||
used++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
aplci_p++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Cplci_t *applAdr2cplci(Appl_t *appl, __u32 adr)
|
||||
{
|
||||
int i = (adr >> 8) & 0xff;
|
||||
|
||||
if ((i < 1) || (i > CAPI_MAXPLCI)) {
|
||||
int_error();
|
||||
return 0;
|
||||
if (used) {
|
||||
if (who == 3) {
|
||||
list_del_init(&appl->head);
|
||||
list_add(&appl->head, &garbage_applications);
|
||||
}
|
||||
test_and_clear_bit(APPL_STATE_DESTRUCTOR, &appl->state);
|
||||
return(-EBUSY);
|
||||
}
|
||||
return appl->cplcis[i - 1];
|
||||
list_del_init(&appl->head);
|
||||
appl->maxplci = 0;
|
||||
kfree(appl->AppPlcis);
|
||||
appl->AppPlcis = NULL;
|
||||
kfree(appl);
|
||||
return(0);
|
||||
}
|
||||
|
||||
void applSendMessage(Appl_t *appl, struct sk_buff *skb)
|
||||
AppPlci_t *
|
||||
getAppPlci4addr(Application_t *appl, __u32 addr)
|
||||
{
|
||||
Plci_t *plci;
|
||||
Cplci_t *cplci;
|
||||
int plci_idx = (addr >> 8) & 0xff;
|
||||
|
||||
if ((plci_idx < 1) || (plci_idx >= appl->maxplci)) {
|
||||
int_error();
|
||||
return NULL;
|
||||
}
|
||||
return(appl->AppPlcis[plci_idx - 1]);
|
||||
}
|
||||
|
||||
static void
|
||||
FacilityReq(Application_t *appl, struct sk_buff *skb)
|
||||
{
|
||||
_cmsg *cmsg;
|
||||
AppPlci_t *aplci;
|
||||
|
||||
cmsg = cmsg_alloc();
|
||||
if (!cmsg) {
|
||||
int_error();
|
||||
dev_kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
capi_message2cmsg(cmsg, skb->data);
|
||||
switch (cmsg->FacilitySelector) {
|
||||
case 0x0000: // Handset
|
||||
case 0x0001: // DTMF
|
||||
aplci = getAppPlci4addr(appl, CAPIMSG_CONTROL(skb->data));
|
||||
if (aplci && aplci->ncci) {
|
||||
ncciGetCmsg(aplci->ncci, cmsg);
|
||||
break;
|
||||
}
|
||||
SendCmsgAnswer2Application(appl, cmsg, CapiIllContrPlciNcci);
|
||||
break;
|
||||
case 0x0003: // SupplementaryServices
|
||||
SupplementaryFacilityReq(appl, cmsg);
|
||||
break;
|
||||
default:
|
||||
int_error();
|
||||
SendCmsgAnswer2Application(appl, cmsg, CapiFacilityNotSupported);
|
||||
break;
|
||||
}
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
void
|
||||
ApplicationSendMessage(Application_t *appl, struct sk_buff *skb)
|
||||
{
|
||||
Plci_t *plci;
|
||||
AppPlci_t *aplci;
|
||||
|
||||
switch (CAPICMD(CAPIMSG_COMMAND(skb->data), CAPIMSG_SUBCOMMAND(skb->data))) {
|
||||
// for NCCI state machine
|
||||
case CAPI_DATA_B3_REQ:
|
||||
case CAPI_DATA_B3_RESP:
|
||||
case CAPI_CONNECT_B3_REQ:
|
||||
case CAPI_CONNECT_B3_RESP:
|
||||
case CAPI_CONNECT_B3_ACTIVE_RESP:
|
||||
case CAPI_DISCONNECT_B3_REQ:
|
||||
case CAPI_DISCONNECT_B3_RESP:
|
||||
aplci = getAppPlci4addr(appl, CAPIMSG_CONTROL(skb->data));
|
||||
if (!aplci) {
|
||||
AnswerMessage2Application(appl, skb, CapiIllContrPlciNcci);
|
||||
goto free;
|
||||
}
|
||||
if (!aplci->ncci) {
|
||||
int_error();
|
||||
AnswerMessage2Application(appl, skb, CapiIllContrPlciNcci);
|
||||
goto free;
|
||||
}
|
||||
ncciSendMessage(aplci->ncci, skb);
|
||||
break;
|
||||
// for PLCI state machine
|
||||
case CAPI_INFO_REQ:
|
||||
case CAPI_ALERT_REQ:
|
||||
case CAPI_CONNECT_RESP:
|
||||
case CAPI_CONNECT_ACTIVE_RESP:
|
||||
case CAPI_DISCONNECT_REQ:
|
||||
case CAPI_DISCONNECT_RESP:
|
||||
case CAPI_SELECT_B_PROTOCOL_REQ:
|
||||
aplci = getAppPlci4addr(appl, CAPIMSG_CONTROL(skb->data));
|
||||
if (!aplci) {
|
||||
AnswerMessage2Application(appl, skb, CapiIllContrPlciNcci);
|
||||
goto free;
|
||||
}
|
||||
AppPlciSendMessage(aplci, skb);
|
||||
break;
|
||||
case CAPI_CONNECT_REQ:
|
||||
if (ControllerNewPlci(appl->contr, &plci, MISDN_ID_ANY)) {
|
||||
AnswerMessage2Application(appl, skb, CapiNoPlciAvailable);
|
||||
goto free;
|
||||
}
|
||||
aplci = ApplicationNewAppPlci(appl, plci);
|
||||
if (!aplci) {
|
||||
AnswerMessage2Application(appl, skb, CapiNoPlciAvailable);
|
||||
goto free;
|
||||
}
|
||||
AppPlciSendMessage(aplci, skb);
|
||||
break;
|
||||
|
||||
// for NCCI state machine
|
||||
case CAPI_DATA_B3_REQ:
|
||||
case CAPI_DATA_B3_RESP:
|
||||
case CAPI_CONNECT_B3_REQ:
|
||||
case CAPI_CONNECT_B3_RESP:
|
||||
case CAPI_CONNECT_B3_ACTIVE_RESP:
|
||||
case CAPI_DISCONNECT_B3_REQ:
|
||||
case CAPI_DISCONNECT_B3_RESP:
|
||||
cplci = applAdr2cplci(appl, CAPIMSG_CONTROL(skb->data));
|
||||
if (!cplci) {
|
||||
contrAnswerMessage(appl->contr, skb, CapiIllContrPlciNcci);
|
||||
goto free;
|
||||
}
|
||||
if (!cplci->ncci) {
|
||||
int_error();
|
||||
contrAnswerMessage(appl->contr, skb, CapiIllContrPlciNcci);
|
||||
goto free;
|
||||
}
|
||||
ncciSendMessage(cplci->ncci, skb);
|
||||
break;
|
||||
// for PLCI state machine
|
||||
case CAPI_INFO_REQ:
|
||||
case CAPI_ALERT_REQ:
|
||||
case CAPI_CONNECT_RESP:
|
||||
case CAPI_CONNECT_ACTIVE_RESP:
|
||||
case CAPI_DISCONNECT_REQ:
|
||||
case CAPI_DISCONNECT_RESP:
|
||||
case CAPI_SELECT_B_PROTOCOL_REQ:
|
||||
cplci = applAdr2cplci(appl, CAPIMSG_CONTROL(skb->data));
|
||||
if (!cplci) {
|
||||
contrAnswerMessage(appl->contr, skb, CapiIllContrPlciNcci);
|
||||
goto free;
|
||||
}
|
||||
cplciSendMessage(cplci, skb);
|
||||
break;
|
||||
case CAPI_CONNECT_REQ:
|
||||
plci = contrNewPlci(appl->contr, MISDN_ID_ANY);
|
||||
if (!plci) {
|
||||
contrAnswerMessage(appl->contr, skb, CapiNoPlciAvailable);
|
||||
goto free;
|
||||
}
|
||||
cplci = applNewCplci(appl, plci);
|
||||
if (!cplci) {
|
||||
contrDelPlci(appl->contr, plci);
|
||||
contrAnswerMessage(appl->contr, skb, CapiNoPlciAvailable);
|
||||
goto free;
|
||||
}
|
||||
cplciSendMessage(cplci, skb);
|
||||
break;
|
||||
// for LISTEN state machine
|
||||
case CAPI_LISTEN_REQ:
|
||||
listenSendMessage(appl, skb);
|
||||
break;
|
||||
|
||||
// for LISTEN state machine
|
||||
case CAPI_LISTEN_REQ:
|
||||
listenSendMessage(&appl->listen, skb);
|
||||
break;
|
||||
|
||||
// other
|
||||
case CAPI_FACILITY_REQ:
|
||||
applFacilityReq(appl, skb);
|
||||
break;
|
||||
case CAPI_FACILITY_RESP:
|
||||
goto free;
|
||||
case CAPI_MANUFACTURER_REQ:
|
||||
applManufacturerReq(appl, skb);
|
||||
break;
|
||||
case CAPI_INFO_RESP:
|
||||
goto free;
|
||||
default:
|
||||
applDebug(appl, CAPI_DBG_WARN, "applSendMessage: %#x %#x not handled!",
|
||||
CAPIMSG_COMMAND(skb->data), CAPIMSG_SUBCOMMAND(skb->data));
|
||||
if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_REQ)
|
||||
contrAnswerMessage(appl->contr, skb,
|
||||
CapiMessageNotSupportedInCurrentState);
|
||||
goto free;
|
||||
// other
|
||||
case CAPI_FACILITY_REQ:
|
||||
FacilityReq(appl, skb);
|
||||
break;
|
||||
case CAPI_FACILITY_RESP:
|
||||
goto free;
|
||||
case CAPI_MANUFACTURER_REQ:
|
||||
applManufacturerReq(appl, skb);
|
||||
break;
|
||||
case CAPI_INFO_RESP:
|
||||
goto free;
|
||||
default:
|
||||
applDebug(appl, CAPI_DBG_WARN, "applSendMessage: %#x %#x not handled!",
|
||||
CAPIMSG_COMMAND(skb->data), CAPIMSG_SUBCOMMAND(skb->data));
|
||||
if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_REQ)
|
||||
AnswerMessage2Application(appl, skb,
|
||||
CapiMessageNotSupportedInCurrentState);
|
||||
goto free;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
free:
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
void applFacilityReq(Appl_t *appl, struct sk_buff *skb)
|
||||
AppPlci_t *
|
||||
ApplicationNewAppPlci(Application_t *appl, Plci_t *plci)
|
||||
{
|
||||
_cmsg cmsg;
|
||||
Cplci_t *cplci;
|
||||
AppPlci_t *aplci;
|
||||
int plci_idx = (plci->addr >> 8) & 0xff;
|
||||
|
||||
capi_message2cmsg(&cmsg, skb->data);
|
||||
switch (cmsg.FacilitySelector) {
|
||||
case 0x0000: // Handset
|
||||
case 0x0001: // DTMF
|
||||
cplci = applAdr2cplci(appl, CAPIMSG_CONTROL(skb->data));
|
||||
if (cplci && cplci->ncci) {
|
||||
ncciSendMessage(cplci->ncci, skb);
|
||||
return;
|
||||
}
|
||||
contrAnswerMessage(appl->contr, skb, CapiIllContrPlciNcci);
|
||||
break;
|
||||
case 0x0003: // SupplementaryServices
|
||||
applSuppFacilityReq(appl, &cmsg);
|
||||
break;
|
||||
default:
|
||||
int_error();
|
||||
contrAnswerMessage(appl->contr, skb, CapiFacilityNotSupported);
|
||||
break;
|
||||
}
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
Cplci_t *applNewCplci(Appl_t *appl, Plci_t *plci)
|
||||
{
|
||||
Cplci_t *cplci;
|
||||
int i = (plci->adrPLCI >> 8);
|
||||
|
||||
if (appl->cplcis[i - 1]) {
|
||||
if (test_bit(APPL_STATE_RELEASE, &appl->state))
|
||||
return(NULL);
|
||||
if ((plci_idx < 1) || (plci_idx >= appl->maxplci)) {
|
||||
int_error();
|
||||
return 0;
|
||||
return(NULL);
|
||||
}
|
||||
cplci = kmalloc(sizeof(Cplci_t), GFP_ATOMIC);
|
||||
cplciConstr(cplci, appl, plci);
|
||||
appl->cplcis[i - 1] = cplci;
|
||||
plciAttachCplci(plci, cplci);
|
||||
return cplci;
|
||||
if (appl->AppPlcis[plci_idx - 1]) {
|
||||
int_error();
|
||||
return(NULL);
|
||||
}
|
||||
if (AppPlciConstr(&aplci, appl, plci)) {
|
||||
int_error();
|
||||
return(NULL);
|
||||
}
|
||||
applDebug(appl, CAPI_DBG_APPL_INFO, "ApplicationNewAppPlci: idx(%d) aplci(%p) appl(%p) plci(%p)",
|
||||
plci_idx, aplci, appl, plci);
|
||||
appl->AppPlcis[plci_idx - 1] = aplci;
|
||||
plciAttachAppPlci(plci, aplci);
|
||||
return(aplci);
|
||||
}
|
||||
|
||||
void applDelCplci(Appl_t *appl, Cplci_t *cplci)
|
||||
void
|
||||
ApplicationDelAppPlci(Application_t *appl, AppPlci_t *aplci)
|
||||
{
|
||||
int i = cplci->adrPLCI >> 8;
|
||||
int plci_idx = (aplci->addr >> 8) & 0xff;
|
||||
|
||||
if ((i < 1) || (i > CAPI_MAXPLCI)) {
|
||||
if ((plci_idx < 1) || (plci_idx >= appl->maxplci)) {
|
||||
int_error();
|
||||
return;
|
||||
}
|
||||
if (appl->cplcis[i-1] != cplci) {
|
||||
if (appl->AppPlcis[plci_idx - 1] != aplci) {
|
||||
int_error();
|
||||
return;
|
||||
}
|
||||
cplciDestr(cplci);
|
||||
kfree(cplci);
|
||||
appl->cplcis[i-1] = NULL;
|
||||
appl->AppPlcis[plci_idx - 1] = NULL;
|
||||
if (test_bit(APPL_STATE_RELEASE, &appl->state) &&
|
||||
!test_bit(APPL_STATE_DESTRUCTOR, &appl->state))
|
||||
ApplicationDestr(appl, 0);
|
||||
}
|
||||
|
||||
void
|
||||
SendCmsg2Application(Application_t *appl, _cmsg *cmsg)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (test_bit(APPL_STATE_RELEASE, &appl->state)) {
|
||||
/* Application is released and cannot receive messages
|
||||
* anymore. To avoid stalls in the state machines we
|
||||
* must answer INDICATIONS.
|
||||
*/
|
||||
AppPlci_t *aplci;
|
||||
|
||||
if (CAPI_IND != cmsg->Subcommand)
|
||||
goto free;
|
||||
switch(cmsg->Command) {
|
||||
// for NCCI state machine
|
||||
case CAPI_CONNECT_B3:
|
||||
cmsg->Reject = 2;
|
||||
case CAPI_CONNECT_B3_ACTIVE:
|
||||
case CAPI_DISCONNECT_B3:
|
||||
aplci = getAppPlci4addr(appl, (cmsg->adr.adrNCCI & 0xffff));
|
||||
if (!aplci)
|
||||
goto free;
|
||||
if (!aplci->ncci) {
|
||||
int_error();
|
||||
goto free;
|
||||
}
|
||||
capi_cmsg_answer(cmsg);
|
||||
ncciGetCmsg(aplci->ncci, cmsg);
|
||||
break;
|
||||
// for PLCI state machine
|
||||
case CAPI_CONNECT:
|
||||
cmsg->Reject = 2;
|
||||
case CAPI_CONNECT_ACTIVE:
|
||||
case CAPI_DISCONNECT:
|
||||
aplci = getAppPlci4addr(appl, (cmsg->adr.adrPLCI & 0xffff));
|
||||
if (!aplci)
|
||||
goto free;
|
||||
capi_cmsg_answer(cmsg);
|
||||
AppPlciGetCmsg(aplci, cmsg);
|
||||
break;
|
||||
case CAPI_FACILITY:
|
||||
case CAPI_MANUFACTURER:
|
||||
case CAPI_INFO:
|
||||
goto free;
|
||||
default:
|
||||
int_error();
|
||||
goto free;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!(skb = alloc_skb(CAPI_MSG_DEFAULT_LEN, GFP_ATOMIC))) {
|
||||
printk(KERN_WARNING "%s: no mem for %d bytes\n", __FUNCTION__, CAPI_MSG_DEFAULT_LEN);
|
||||
int_error();
|
||||
goto free;
|
||||
}
|
||||
capi_cmsg2message(cmsg, skb->data);
|
||||
applDebug(appl, CAPI_DBG_APPL_MSG, "%s: len(%d) applid(%x) %s msgnr(%d) addr(%08x)",
|
||||
__FUNCTION__, CAPIMSG_LEN(skb->data), cmsg->ApplId, capi_cmd2str(cmsg->Command, cmsg->Subcommand),
|
||||
cmsg->Messagenumber, cmsg->adr.adrController);
|
||||
if (CAPI_MSG_DEFAULT_LEN < CAPIMSG_LEN(skb->data)) {
|
||||
printk(KERN_ERR "%s: CAPI_MSG_DEFAULT_LEN overrun (%d/%d)\n", __FUNCTION__,
|
||||
CAPIMSG_LEN(skb->data), CAPI_MSG_DEFAULT_LEN);
|
||||
int_error();
|
||||
dev_kfree_skb(skb);
|
||||
goto free;
|
||||
}
|
||||
skb_put(skb, CAPIMSG_LEN(skb->data));
|
||||
#ifdef OLDCAPI_DRIVER_INTERFACE
|
||||
appl->contr->ctrl->handle_capimsg(appl->contr->ctrl, cmsg->ApplId, skb);
|
||||
#else
|
||||
capi_ctr_handle_message(appl->contr->ctrl, cmsg->ApplId, skb);
|
||||
#endif
|
||||
free:
|
||||
cmsg_free(cmsg);
|
||||
}
|
||||
|
||||
void
|
||||
SendCmsgAnswer2Application(Application_t *appl, _cmsg *cmsg, __u16 Info)
|
||||
{
|
||||
capi_cmsg_answer(cmsg);
|
||||
cmsg->Info = Info;
|
||||
SendCmsg2Application(appl, cmsg);
|
||||
}
|
||||
|
||||
void
|
||||
AnswerMessage2Application(Application_t *appl, struct sk_buff *skb, __u16 Info)
|
||||
{
|
||||
_cmsg *cmsg;
|
||||
|
||||
CMSG_ALLOC(cmsg);
|
||||
capi_message2cmsg(cmsg, skb->data);
|
||||
SendCmsgAnswer2Application(appl, cmsg, Info);
|
||||
}
|
||||
|
||||
#define AVM_MANUFACTURER_ID 0x214D5641 /* "AVM!" */
|
||||
|
@ -203,12 +391,13 @@ struct AVMD2Trace {
|
|||
__u8 data[4];
|
||||
};
|
||||
|
||||
void applManufacturerReqAVM(Appl_t *appl, _cmsg *cmsg, struct sk_buff *skb)
|
||||
void applManufacturerReqAVM(Application_t *appl, _cmsg *cmsg, struct sk_buff *skb)
|
||||
{
|
||||
struct AVMD2Trace *at;
|
||||
|
||||
if (cmsg->Class != CLASS_AVM) {
|
||||
applDebug(appl, CAPI_DBG_APPL_INFO, "CAPI: unknown class %#x\n", cmsg->Class);
|
||||
cmsg_free(cmsg);
|
||||
dev_kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
@ -220,9 +409,9 @@ void applManufacturerReqAVM(Appl_t *appl, _cmsg *cmsg, struct sk_buff *skb)
|
|||
break;
|
||||
}
|
||||
if (memcmp(at->data, "\200\014\000\000", 4) == 0) {
|
||||
test_and_set_bit(APPL_FLAG_D2TRACE, &appl->flags);
|
||||
test_and_set_bit(APPL_STATE_D2TRACE, &appl->state);
|
||||
} else if (memcmp(at->data, "\000\000\000\000", 4) == 0) {
|
||||
test_and_clear_bit(APPL_FLAG_D2TRACE, &appl->flags);
|
||||
test_and_clear_bit(APPL_STATE_D2TRACE, &appl->state);
|
||||
} else {
|
||||
int_error();
|
||||
}
|
||||
|
@ -230,73 +419,101 @@ void applManufacturerReqAVM(Appl_t *appl, _cmsg *cmsg, struct sk_buff *skb)
|
|||
default:
|
||||
applDebug(appl, CAPI_DBG_APPL_INFO, "CAPI: unknown function %#x\n", cmsg->Function);
|
||||
}
|
||||
cmsg_free(cmsg);
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
void applManufacturerReqmISDN(Appl_t *appl, _cmsg *cmsg, struct sk_buff *skb)
|
||||
void applManufacturerReqmISDN(Application_t *appl, _cmsg *cmsg, struct sk_buff *skb)
|
||||
{
|
||||
Cplci_t *cplci;
|
||||
AppPlci_t *aplci;
|
||||
|
||||
switch (cmsg->Class) {
|
||||
case mISDN_MF_CLASS_HANDSET:
|
||||
/* Note normally MANUFATURER messages are only defined for
|
||||
* controller address we extent it here to PLCI/NCCI
|
||||
*/
|
||||
cplci = applAdr2cplci(appl, CAPIMSG_CONTROL(skb->data));
|
||||
if (cplci && cplci->ncci) {
|
||||
ncciSendMessage(cplci->ncci, skb);
|
||||
aplci = getAppPlci4addr(appl, CAPIMSG_CONTROL(skb->data));
|
||||
if (aplci && aplci->ncci) {
|
||||
cmsg_free(cmsg);
|
||||
ncciSendMessage(aplci->ncci, skb);
|
||||
return;
|
||||
}
|
||||
contrAnswerMessage(appl->contr, skb, CapiIllContrPlciNcci);
|
||||
SendCmsgAnswer2Application(appl, cmsg, CapiIllContrPlciNcci);
|
||||
break;
|
||||
default:
|
||||
dev_kfree_skb(skb);
|
||||
cmsg_free(cmsg);
|
||||
break;
|
||||
}
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
void applManufacturerReq(Appl_t *appl, struct sk_buff *skb)
|
||||
void
|
||||
applManufacturerReq(Application_t *appl, struct sk_buff *skb)
|
||||
{
|
||||
_cmsg cmsg;
|
||||
_cmsg *cmsg;
|
||||
|
||||
if (skb->len < 16 + 8) {
|
||||
dev_kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
capi_message2cmsg(&cmsg, skb->data);
|
||||
switch (cmsg.ManuID) {
|
||||
cmsg = cmsg_alloc();
|
||||
if (!cmsg) {
|
||||
int_error();
|
||||
dev_kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
capi_message2cmsg(cmsg, skb->data);
|
||||
switch (cmsg->ManuID) {
|
||||
case mISDN_MANUFACTURER_ID:
|
||||
applManufacturerReqmISDN(appl, &cmsg, skb);
|
||||
applManufacturerReqmISDN(appl, cmsg, skb);
|
||||
break;
|
||||
case AVM_MANUFACTURER_ID:
|
||||
applManufacturerReqAVM(appl, &cmsg, skb);
|
||||
applManufacturerReqAVM(appl, cmsg, skb);
|
||||
break;
|
||||
default:
|
||||
applDebug(appl, CAPI_DBG_APPL_INFO, "CAPI: unknown ManuID %#x\n", cmsg.ManuID);
|
||||
applDebug(appl, CAPI_DBG_APPL_INFO, "CAPI: unknown ManuID %#x\n", cmsg->ManuID);
|
||||
cmsg_free(cmsg);
|
||||
dev_kfree_skb(skb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void applD2Trace(Appl_t *appl, u_char *buf, int len)
|
||||
void applD2Trace(Application_t *appl, u_char *buf, int len)
|
||||
{
|
||||
_cmsg cmsg;
|
||||
__u8 manuData[255];
|
||||
_cmsg *cmsg;
|
||||
__u8 manuData[255];
|
||||
|
||||
if (!test_bit(APPL_FLAG_D2TRACE, &appl->flags))
|
||||
if (!test_bit(APPL_STATE_D2TRACE, &appl->state))
|
||||
return;
|
||||
|
||||
memset(&cmsg, 0, sizeof(_cmsg));
|
||||
capi_cmsg_header(&cmsg, appl->ApplId, CAPI_MANUFACTURER, CAPI_IND,
|
||||
appl->MsgId++, appl->contr->adrController);
|
||||
cmsg.ManuID = AVM_MANUFACTURER_ID;
|
||||
cmsg.Class = CLASS_AVM;
|
||||
cmsg.Function = FUNCTION_AVM_D2_TRACE;
|
||||
cmsg.ManuData = (_cstruct) &manuData;
|
||||
CMSG_ALLOC(cmsg);
|
||||
capi_cmsg_header(cmsg, appl->ApplId, CAPI_MANUFACTURER, CAPI_IND,
|
||||
appl->MsgId++, appl->contr->addr);
|
||||
cmsg->ManuID = AVM_MANUFACTURER_ID;
|
||||
cmsg->Class = CLASS_AVM;
|
||||
cmsg->Function = FUNCTION_AVM_D2_TRACE;
|
||||
cmsg->ManuData = (_cstruct) &manuData;
|
||||
manuData[0] = 2 + len; // length
|
||||
manuData[1] = 0x80;
|
||||
manuData[2] = 0x0f;
|
||||
memcpy(&manuData[3], buf, len);
|
||||
|
||||
contrRecvCmsg(appl->contr, &cmsg);
|
||||
SendCmsg2Application(appl, cmsg);
|
||||
}
|
||||
|
||||
void
|
||||
free_Application(void)
|
||||
{
|
||||
struct list_head *item, *next;
|
||||
int n = 0;
|
||||
|
||||
if (list_empty(&garbage_applications)) {
|
||||
printk(KERN_DEBUG "%s: no garbage\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
list_for_each_safe(item, next, &garbage_applications) {
|
||||
ApplicationDestr((Application_t *)item, 4);
|
||||
n++;
|
||||
}
|
||||
printk(KERN_WARNING"%s: %d garbage items\n", __FUNCTION__, n);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "capi.h"
|
||||
#include "m_capi.h"
|
||||
#include "helper.h"
|
||||
#include "asn1_enc.h"
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include "capi.h"
|
||||
#include "m_capi.h"
|
||||
#include "helper.h"
|
||||
#include "debug.h"
|
||||
|
||||
|
@ -40,17 +40,267 @@ void capidebug(int level, char *fmt, ...)
|
|||
struct capi_driver_interface *cdrv_if;
|
||||
#endif
|
||||
|
||||
int CapiNew(void)
|
||||
kmem_cache_t *mISDN_cmsg_cp;
|
||||
kmem_cache_t *mISDN_AppPlci_cp;
|
||||
kmem_cache_t *mISDN_ncci_cp;
|
||||
kmem_cache_t *mISDN_sspc_cp;
|
||||
|
||||
#ifdef MISDN_KMEM_DEBUG
|
||||
static struct list_head mISDN_kmem_garbage = LIST_HEAD_INIT(mISDN_kmem_garbage);
|
||||
|
||||
_cmsg *
|
||||
_kd_cmsg_alloc(char *fn, int line)
|
||||
{
|
||||
_kd_cmsg_t *ki = kmem_cache_alloc(mISDN_cmsg_cp, GFP_ATOMIC);
|
||||
|
||||
if (!ki)
|
||||
return(NULL);
|
||||
ki->kdi.typ = KM_DBG_TYP_CM;
|
||||
INIT_LIST_HEAD(&ki->kdi.head);
|
||||
ki->kdi.line = line;
|
||||
ki->kdi.file = fn;
|
||||
list_add_tail(&ki->kdi.head, &mISDN_kmem_garbage);
|
||||
return(&ki->cm);
|
||||
}
|
||||
|
||||
void
|
||||
cmsg_free(_cmsg *cm)
|
||||
{
|
||||
km_dbg_item_t *kdi;
|
||||
|
||||
if (!cm) {
|
||||
int_errtxt("zero pointer free at %p", __builtin_return_address(0));
|
||||
return;
|
||||
}
|
||||
kdi = KDB_GET_KDI(cm);
|
||||
list_del(&kdi->head);
|
||||
kmem_cache_free(mISDN_cmsg_cp, kdi);
|
||||
}
|
||||
|
||||
AppPlci_t *
|
||||
_kd_AppPlci_alloc(char *fn, int line)
|
||||
{
|
||||
_kd_AppPlci_t *ki = kmem_cache_alloc(mISDN_AppPlci_cp, GFP_ATOMIC);
|
||||
|
||||
if (!ki)
|
||||
return(NULL);
|
||||
ki->kdi.typ = KM_DBG_TYP_AP;
|
||||
INIT_LIST_HEAD(&ki->kdi.head);
|
||||
ki->kdi.line = line;
|
||||
ki->kdi.file = fn;
|
||||
list_add_tail(&ki->kdi.head, &mISDN_kmem_garbage);
|
||||
return(&ki->ap);
|
||||
}
|
||||
|
||||
void
|
||||
AppPlci_free(AppPlci_t *ap)
|
||||
{
|
||||
km_dbg_item_t *kdi;
|
||||
|
||||
if (!ap) {
|
||||
int_errtxt("zero pointer free at %p", __builtin_return_address(0));
|
||||
return;
|
||||
}
|
||||
kdi = KDB_GET_KDI(ap);
|
||||
list_del(&kdi->head);
|
||||
kmem_cache_free(mISDN_AppPlci_cp, kdi);
|
||||
}
|
||||
|
||||
Ncci_t *
|
||||
_kd_ncci_alloc(char *fn, int line)
|
||||
{
|
||||
_kd_Ncci_t *ki = kmem_cache_alloc(mISDN_ncci_cp, GFP_ATOMIC);
|
||||
|
||||
if (!ki)
|
||||
return(NULL);
|
||||
ki->kdi.typ = KM_DBG_TYP_NI;
|
||||
INIT_LIST_HEAD(&ki->kdi.head);
|
||||
ki->kdi.line = line;
|
||||
ki->kdi.file = fn;
|
||||
list_add_tail(&ki->kdi.head, &mISDN_kmem_garbage);
|
||||
return(&ki->ni);
|
||||
}
|
||||
|
||||
void
|
||||
ncci_free(Ncci_t *ni)
|
||||
{
|
||||
km_dbg_item_t *kdi;
|
||||
|
||||
if (!ni) {
|
||||
int_errtxt("zero pointer free at %p", __builtin_return_address(0));
|
||||
return;
|
||||
}
|
||||
kdi = KDB_GET_KDI(ni);
|
||||
list_del(&kdi->head);
|
||||
kmem_cache_free(mISDN_ncci_cp, kdi);
|
||||
}
|
||||
|
||||
SSProcess_t *
|
||||
_kd_SSProcess_alloc(char *fn, int line)
|
||||
{
|
||||
_kd_SSProcess_t *ki = kmem_cache_alloc(mISDN_sspc_cp, GFP_ATOMIC);
|
||||
|
||||
if (!ki)
|
||||
return(NULL);
|
||||
ki->kdi.typ = KM_DBG_TYP_SP;
|
||||
INIT_LIST_HEAD(&ki->kdi.head);
|
||||
ki->kdi.line = line;
|
||||
ki->kdi.file = fn;
|
||||
list_add_tail(&ki->kdi.head, &mISDN_kmem_garbage);
|
||||
return(&ki->sp);
|
||||
}
|
||||
|
||||
void
|
||||
SSProcess_free(SSProcess_t *sp)
|
||||
{
|
||||
km_dbg_item_t *kdi;
|
||||
|
||||
if (!sp) {
|
||||
int_errtxt("zero pointer free at %p", __builtin_return_address(0));
|
||||
return;
|
||||
}
|
||||
kdi = KDB_GET_KDI(sp);
|
||||
list_del(&kdi->head);
|
||||
kmem_cache_free(mISDN_sspc_cp, kdi);
|
||||
}
|
||||
|
||||
static void
|
||||
free_garbage(void)
|
||||
{
|
||||
struct list_head *item, *next;
|
||||
_kd_all_t *kda;
|
||||
|
||||
list_for_each_safe(item, next, &mISDN_kmem_garbage) {
|
||||
kda = (_kd_all_t *)item;
|
||||
printk(KERN_DEBUG "garbage item found (%p <- %p -> %p) type%ld allocated at %s:%d\n",
|
||||
kda->kdi.head.prev, item, kda->kdi.head.next, kda->kdi.typ, kda->kdi.file, kda->kdi.line);
|
||||
list_del(item);
|
||||
switch(kda->kdi.typ) {
|
||||
case KM_DBG_TYP_CM:
|
||||
printk(KERN_DEBUG "cmsg cmd(%x,%x) appl(%x) addr(%x) nr(%d)\n",
|
||||
kda->a.cm.Command,
|
||||
kda->a.cm.Subcommand,
|
||||
kda->a.cm.ApplId,
|
||||
kda->a.cm.adr.adrController,
|
||||
kda->a.cm.Messagenumber);
|
||||
kmem_cache_free(mISDN_cmsg_cp, item);
|
||||
break;
|
||||
case KM_DBG_TYP_AP:
|
||||
printk(KERN_DEBUG "AppPlci: PLCI(%x) m.state(%x) appl(%p)\n",
|
||||
kda->a.ap.addr,
|
||||
kda->a.ap.plci_m.state,
|
||||
kda->a.ap.appl);
|
||||
kmem_cache_free(mISDN_AppPlci_cp, item);
|
||||
break;
|
||||
case KM_DBG_TYP_NI:
|
||||
printk(KERN_DEBUG "Ncci: NCCI(%x) state(%x) m.state(%x) aplci(%p)\n",
|
||||
kda->a.ni.addr,
|
||||
kda->a.ni.state,
|
||||
kda->a.ni.ncci_m.state,
|
||||
kda->a.ni.AppPlci);
|
||||
kmem_cache_free(mISDN_ncci_cp, item);
|
||||
break;
|
||||
case KM_DBG_TYP_SP:
|
||||
printk(KERN_DEBUG "SSPc: addr(%x) id(%x) apid(%x) func(%x)\n",
|
||||
kda->a.sp.addr,
|
||||
kda->a.sp.invokeId,
|
||||
kda->a.sp.ApplId,
|
||||
kda->a.sp.Function);
|
||||
kmem_cache_free(mISDN_sspc_cp, item);
|
||||
break;
|
||||
default:
|
||||
printk(KERN_DEBUG "unknown garbage item(%p) type %ld\n",
|
||||
item, kda->kdi.typ);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void CapiCachesFree(void)
|
||||
{
|
||||
#ifdef MISDN_KMEM_DEBUG
|
||||
free_garbage();
|
||||
#endif
|
||||
if (mISDN_cmsg_cp) {
|
||||
kmem_cache_destroy(mISDN_cmsg_cp);
|
||||
mISDN_cmsg_cp = NULL;
|
||||
}
|
||||
if (mISDN_AppPlci_cp) {
|
||||
kmem_cache_destroy(mISDN_AppPlci_cp);
|
||||
mISDN_AppPlci_cp = NULL;
|
||||
}
|
||||
if (mISDN_ncci_cp) {
|
||||
kmem_cache_destroy(mISDN_ncci_cp);
|
||||
mISDN_ncci_cp = NULL;
|
||||
}
|
||||
if (mISDN_sspc_cp) {
|
||||
kmem_cache_destroy(mISDN_sspc_cp);
|
||||
mISDN_sspc_cp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int CapiNew(void)
|
||||
{
|
||||
mISDN_cmsg_cp = NULL;
|
||||
mISDN_AppPlci_cp = NULL;
|
||||
mISDN_ncci_cp = NULL;
|
||||
mISDN_sspc_cp = NULL;
|
||||
mISDN_cmsg_cp = kmem_cache_create("mISDN_cmesg",
|
||||
#ifdef MISDN_KMEM_DEBUG
|
||||
sizeof(_kd_cmsg_t),
|
||||
#else
|
||||
sizeof(_cmsg),
|
||||
#endif
|
||||
0, 0, NULL, NULL);
|
||||
if (!mISDN_cmsg_cp) {
|
||||
CapiCachesFree();
|
||||
return(-ENOMEM);
|
||||
}
|
||||
mISDN_AppPlci_cp = kmem_cache_create("mISDN_AppPlci",
|
||||
#ifdef MISDN_KMEM_DEBUG
|
||||
sizeof(_kd_AppPlci_t),
|
||||
#else
|
||||
sizeof(AppPlci_t),
|
||||
#endif
|
||||
0, 0, NULL, NULL);
|
||||
if (!mISDN_AppPlci_cp) {
|
||||
CapiCachesFree();
|
||||
return(-ENOMEM);
|
||||
}
|
||||
mISDN_ncci_cp = kmem_cache_create("mISDN_Ncci",
|
||||
#ifdef MISDN_KMEM_DEBUG
|
||||
sizeof(_kd_Ncci_t),
|
||||
#else
|
||||
sizeof(Ncci_t),
|
||||
#endif
|
||||
0, 0, NULL, NULL);
|
||||
if (!mISDN_ncci_cp) {
|
||||
CapiCachesFree();
|
||||
return(-ENOMEM);
|
||||
}
|
||||
mISDN_sspc_cp = kmem_cache_create("mISDN_SSProc",
|
||||
#ifdef MISDN_KMEM_DEBUG
|
||||
sizeof(_kd_SSProcess_t),
|
||||
#else
|
||||
sizeof(SSProcess_t),
|
||||
#endif
|
||||
0, 0, NULL, NULL);
|
||||
if (!mISDN_sspc_cp) {
|
||||
CapiCachesFree();
|
||||
return(-ENOMEM);
|
||||
}
|
||||
#ifdef OLDCAPI_DRIVER_INTERFACE
|
||||
cdrv_if = attach_capi_driver(&mISDN_driver);
|
||||
if (!cdrv_if) {
|
||||
CapiCachesFree();
|
||||
printk(KERN_ERR "mISDN: failed to attach capi_driver\n");
|
||||
return -EIO;
|
||||
}
|
||||
#endif
|
||||
init_listen();
|
||||
init_cplci();
|
||||
init_AppPlci();
|
||||
init_ncci();
|
||||
return 0;
|
||||
}
|
||||
|
@ -60,7 +310,7 @@ capi20_manager(void *data, u_int prim, void *arg) {
|
|||
mISDNinstance_t *inst = data;
|
||||
int found=0;
|
||||
BInst_t *binst = NULL;
|
||||
Contr_t *ctrl = (Contr_t *)capi_obj.ilist;
|
||||
Controller_t *ctrl = (Controller_t *)capi_obj.ilist;
|
||||
|
||||
if (CAPI_DBG_INFO & debug)
|
||||
printk(KERN_DEBUG "capi20_manager data:%p prim:%x arg:%p\n", data, prim, arg);
|
||||
|
@ -85,11 +335,10 @@ capi20_manager(void *data, u_int prim, void *arg) {
|
|||
ctrl = ctrl->next;
|
||||
}
|
||||
if (prim == (MGR_NEWLAYER | REQUEST)) {
|
||||
ctrl = newContr(&capi_obj, data, arg);
|
||||
if (!ctrl)
|
||||
return(-EINVAL);
|
||||
ctrl->debug = debug;
|
||||
return(0);
|
||||
int ret = ControllerConstr(&ctrl, data, arg, &capi_obj);
|
||||
if (!ret)
|
||||
ctrl->debug = debug;
|
||||
return(ret);
|
||||
}
|
||||
if (!ctrl) {
|
||||
if (CAPI_DBG_WARN & debug)
|
||||
|
@ -105,7 +354,7 @@ capi20_manager(void *data, u_int prim, void *arg) {
|
|||
case MGR_SETIF | INDICATION:
|
||||
case MGR_SETIF | REQUEST:
|
||||
if (&ctrl->inst == inst)
|
||||
return(SetIF(inst, arg, prim, NULL, contrL3L4, ctrl));
|
||||
return(SetIF(inst, arg, prim, NULL, ControllerL3L4, ctrl));
|
||||
else
|
||||
return(SetIF(inst, arg, prim, NULL, ncci_l3l4, inst->data));
|
||||
case MGR_DISCONNECT | REQUEST:
|
||||
|
@ -114,8 +363,7 @@ capi20_manager(void *data, u_int prim, void *arg) {
|
|||
case MGR_RELEASE | INDICATION:
|
||||
if (CAPI_DBG_INFO & debug)
|
||||
printk(KERN_DEBUG "release_capi20 id %x\n", ctrl->inst.st->id);
|
||||
contrDestr(ctrl);
|
||||
kfree(ctrl);
|
||||
ControllerDestr(ctrl);
|
||||
break;
|
||||
case MGR_UNREGLAYER | REQUEST:
|
||||
if (binst) {
|
||||
|
@ -127,7 +375,7 @@ capi20_manager(void *data, u_int prim, void *arg) {
|
|||
case MGR_CTRLREADY | INDICATION:
|
||||
if (CAPI_DBG_INFO & debug)
|
||||
printk(KERN_DEBUG "ctrl %x ready\n", ctrl->inst.st->id);
|
||||
contrRun(ctrl);
|
||||
ControllerRun(ctrl);
|
||||
break;
|
||||
default:
|
||||
if (CAPI_DBG_WARN & debug)
|
||||
|
@ -158,9 +406,11 @@ int Capi20Init(void)
|
|||
#ifdef OLDCAPI_DRIVER_INTERFACE
|
||||
detach_capi_driver(&mISDN_driver);
|
||||
#endif
|
||||
CapiCachesFree();
|
||||
free_listen();
|
||||
free_cplci();
|
||||
free_AppPlci();
|
||||
free_ncci();
|
||||
free_Application();
|
||||
}
|
||||
return(err);
|
||||
}
|
||||
|
@ -168,24 +418,24 @@ int Capi20Init(void)
|
|||
#ifdef MODULE
|
||||
static void Capi20cleanup(void)
|
||||
{
|
||||
int err;
|
||||
Contr_t *contr;
|
||||
int err;
|
||||
Controller_t *contr;
|
||||
|
||||
if ((err = mISDN_unregister(&capi_obj))) {
|
||||
printk(KERN_ERR "Can't unregister User DSS1 error(%d)\n", err);
|
||||
printk(KERN_ERR "Can't unregister CAPI20 error(%d)\n", err);
|
||||
}
|
||||
if (capi_obj.ilist) {
|
||||
printk(KERN_WARNING "mISDNl3 contrlist not empty\n");
|
||||
while((contr = capi_obj.ilist)) {
|
||||
contrDestr(contr);
|
||||
kfree(contr);
|
||||
}
|
||||
printk(KERN_WARNING "mISDN controller list not empty\n");
|
||||
while((contr = capi_obj.ilist))
|
||||
ControllerDestr(contr);
|
||||
}
|
||||
#ifdef OLDCAPI_DRIVER_INTERFACE
|
||||
detach_capi_driver(&mISDN_driver);
|
||||
#endif
|
||||
free_Application();
|
||||
CapiCachesFree();
|
||||
free_listen();
|
||||
free_cplci();
|
||||
free_AppPlci();
|
||||
free_ncci();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,393 +0,0 @@
|
|||
/* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __mISDN_CAPI_H__
|
||||
#define __mISDN_CAPI_H__
|
||||
|
||||
#include <linux/mISDNif.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/capi.h>
|
||||
#include <linux/kernelcapi.h>
|
||||
#ifdef OLDCAPI_DRIVER_INTERFACE
|
||||
#include "../avmb1/capiutil.h"
|
||||
#include "../avmb1/capicmd.h"
|
||||
#include "../avmb1/capilli.h"
|
||||
#else
|
||||
#include <linux/list.h>
|
||||
#include <linux/isdn/capiutil.h>
|
||||
#include <linux/isdn/capicmd.h>
|
||||
#include <linux/isdn/capilli.h>
|
||||
#endif
|
||||
#include "asn1.h"
|
||||
#include "fsm.h"
|
||||
#ifdef MEMDBG
|
||||
#include "memdbg.h"
|
||||
#endif
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// common stuff
|
||||
|
||||
#define CAPI_DBG_WARN 0x00000001
|
||||
#define CAPI_DBG_INFO 0x00000004
|
||||
#define CAPI_DBG_APPL 0x00000010
|
||||
#define CAPI_DBG_APPL_INFO 0x00000040
|
||||
#define CAPI_DBG_LISTEN 0x00000100
|
||||
#define CAPI_DBG_LISTEN_STATE 0x00000200
|
||||
#define CAPI_DBG_LISTEN_INFO 0x00000400
|
||||
#define CAPI_DBG_CONTR 0x00010000
|
||||
#define CAPI_DBG_CONTR_INFO 0x00040000
|
||||
#define CAPI_DBG_CONTR_MSG 0x00080000
|
||||
#define CAPI_DBG_PLCI 0x00100000
|
||||
#define CAPI_DBG_PLCI_STATE 0x00200000
|
||||
#define CAPI_DBG_PLCI_INFO 0x00400000
|
||||
#define CAPI_DBG_PLCI_L3 0x00800000
|
||||
#define CAPI_DBG_NCCI 0x01000000
|
||||
#define CAPI_DBG_NCCI_STATE 0x02000000
|
||||
#define CAPI_DBG_NCCI_INFO 0x04000000
|
||||
#define CAPI_DBG_NCCI_L3 0x08000000
|
||||
|
||||
#ifdef OLDCAPI_DRIVER_INTERFACE
|
||||
extern struct capi_driver_interface *cdrv_if;
|
||||
extern struct capi_driver mISDN_driver;
|
||||
#endif
|
||||
|
||||
void init_listen(void);
|
||||
void init_cplci(void);
|
||||
void init_ncci(void);
|
||||
void free_listen(void);
|
||||
void free_cplci(void);
|
||||
void free_ncci(void);
|
||||
void capidebug(int, char *, ...);
|
||||
|
||||
/* we implement 64 bit extentions */
|
||||
#define CAPI_B3_DATA_IND_HEADER_SIZE 30
|
||||
|
||||
#define SuppServiceCF 0x00000010
|
||||
#define SuppServiceTP 0x00000002
|
||||
#define mISDNSupportedServices (SuppServiceCF | SuppServiceTP)
|
||||
|
||||
#define CAPIMSG_REQ_DATAHANDLE(m) (m[18] | (m[19]<<8))
|
||||
#define CAPIMSG_RESP_DATAHANDLE(m) (m[12] | (m[13]<<8))
|
||||
|
||||
#define CMSGCMD(cmsg) CAPICMD((cmsg)->Command, (cmsg)->Subcommand)
|
||||
|
||||
#define CAPI_MAXPLCI 5
|
||||
#define CAPI_MAXDUMMYPCS 16
|
||||
|
||||
struct Bprotocol {
|
||||
__u16 B1protocol;
|
||||
__u16 B2protocol;
|
||||
__u16 B3protocol;
|
||||
};
|
||||
|
||||
__u16 q931CIPValue(Q931_info_t *);
|
||||
|
||||
typedef struct _DummyProcess {
|
||||
__u16 invokeId;
|
||||
__u16 Function;
|
||||
__u32 Handle;
|
||||
__u32 adrDummy;
|
||||
__u16 ApplId;
|
||||
struct _Contr *contr;
|
||||
struct timer_list tl;
|
||||
__u8 buf[128];
|
||||
} DummyProcess_t;
|
||||
|
||||
void dummyPcConstr(DummyProcess_t *dummy_pc, struct _Contr *contr, __u16 invokeId);
|
||||
void dummyPcDestr(DummyProcess_t *dummy_pc);
|
||||
void dummyPcAddTimer(DummyProcess_t *dummy_pc, int msec);
|
||||
|
||||
int capiEncodeFacIndSuspend(__u8 *dest, __u16 SupplementaryServiceReason);
|
||||
|
||||
struct FacReqListen {
|
||||
__u32 NotificationMask;
|
||||
};
|
||||
|
||||
struct FacReqSuspend {
|
||||
__u8 *CallIdentity;
|
||||
};
|
||||
|
||||
struct FacReqResume {
|
||||
__u8 *CallIdentity;
|
||||
};
|
||||
|
||||
struct FacReqCFActivate {
|
||||
__u32 Handle;
|
||||
__u16 Procedure;
|
||||
__u16 BasicService;
|
||||
__u8 *ServedUserNumber;
|
||||
__u8 *ForwardedToNumber;
|
||||
__u8 *ForwardedToSubaddress;
|
||||
};
|
||||
|
||||
struct FacReqCFDeactivate {
|
||||
__u32 Handle;
|
||||
__u16 Procedure;
|
||||
__u16 BasicService;
|
||||
__u8 *ServedUserNumber;
|
||||
};
|
||||
|
||||
#define FacReqCFInterrogateParameters FacReqCFDeactivate
|
||||
|
||||
struct FacReqCFInterrogateNumbers {
|
||||
__u32 Handle;
|
||||
};
|
||||
|
||||
struct FacReqParm {
|
||||
__u16 Function;
|
||||
union {
|
||||
struct FacReqListen Listen;
|
||||
struct FacReqSuspend Suspend;
|
||||
struct FacReqResume Resume;
|
||||
struct FacReqCFActivate CFActivate;
|
||||
struct FacReqCFDeactivate CFDeactivate;
|
||||
struct FacReqCFInterrogateParameters CFInterrogateParameters;
|
||||
struct FacReqCFInterrogateNumbers CFInterrogateNumbers;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct FacConfGetSupportedServices {
|
||||
__u16 SupplementaryServiceInfo;
|
||||
__u32 SupportedServices;
|
||||
};
|
||||
|
||||
struct FacConfInfo {
|
||||
__u16 SupplementaryServiceInfo;
|
||||
};
|
||||
|
||||
struct FacConfParm {
|
||||
__u16 Function;
|
||||
union {
|
||||
struct FacConfGetSupportedServices GetSupportedServices;
|
||||
struct FacConfInfo Info;
|
||||
} u;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// struct Contr
|
||||
|
||||
typedef struct _BInst {
|
||||
struct _BInst *prev;
|
||||
struct _BInst *next;
|
||||
mISDNstack_t *bst;
|
||||
mISDNinstance_t inst;
|
||||
} BInst_t;
|
||||
|
||||
typedef struct _Contr {
|
||||
struct _Contr *prev;
|
||||
struct _Contr *next;
|
||||
mISDNinstance_t inst;
|
||||
BInst_t *binst;
|
||||
struct capi_ctr *ctrl;
|
||||
__u32 adrController;
|
||||
int b3_mode;
|
||||
int entity;
|
||||
u_int debug;
|
||||
char infobuf[128];
|
||||
char msgbuf[128];
|
||||
struct _Plci *plcis[CAPI_MAXPLCI];
|
||||
struct _Appl *appls[CAPI_MAXAPPL];
|
||||
DummyProcess_t *dummy_pcs[CAPI_MAXDUMMYPCS];
|
||||
__u16 lastInvokeId;
|
||||
} Contr_t;
|
||||
|
||||
Contr_t *newContr(mISDNobject_t *, mISDNstack_t *, mISDN_pid_t *);
|
||||
void contrDestr(Contr_t *);
|
||||
void contrRun(Contr_t *);
|
||||
void contrDebug(Contr_t *, __u32, char *, ...);
|
||||
void contrRecvCmsg(Contr_t *, _cmsg *);
|
||||
void contrAnswerCmsg(Contr_t *, _cmsg *, __u16);
|
||||
void contrAnswerMessage(Contr_t *, struct sk_buff *, __u16);
|
||||
struct _Plci *contrNewPlci(Contr_t *, u_int);
|
||||
struct _Appl *contrId2appl(Contr_t *, __u16);
|
||||
struct _Plci *contrAdr2plci(Contr_t *, __u32);
|
||||
void contrDelPlci(Contr_t *, struct _Plci *);
|
||||
int contrDummyInd(Contr_t *, __u32, struct sk_buff *);
|
||||
DummyProcess_t *contrNewDummyPc(Contr_t *);
|
||||
DummyProcess_t *contrId2DummyPc(Contr_t *, __u16);
|
||||
int contrL4L3(Contr_t *, u_int, int, struct sk_buff *);
|
||||
int contrL3L4(mISDNif_t *, struct sk_buff *);
|
||||
BInst_t *contrSelChannel(Contr_t *, u_int);
|
||||
// ---------------------------------------------------------------------------
|
||||
// struct Listen
|
||||
|
||||
#define CAPI_INFOMASK_CAUSE (0x0001)
|
||||
#define CAPI_INFOMASK_DATETIME (0x0002)
|
||||
#define CAPI_INFOMASK_DISPLAY (0x0004)
|
||||
#define CAPI_INFOMASK_USERUSER (0x0008)
|
||||
#define CAPI_INFOMASK_PROGRESS (0x0010)
|
||||
#define CAPI_INFOMASK_FACILITY (0x0020)
|
||||
//#define CAPI_INFOMASK_CHARGE (0x0040)
|
||||
//#define CAPI_INFOMASK_CALLEDPN (0x0080)
|
||||
#define CAPI_INFOMASK_CHANNELID (0x0100)
|
||||
#define CAPI_INFOMASK_EARLYB3 (0x0200)
|
||||
//#define CAPI_INFOMASK_REDIRECT (0x0400)
|
||||
|
||||
typedef struct _Listen {
|
||||
Contr_t *contr;
|
||||
__u16 ApplId;
|
||||
__u32 InfoMask;
|
||||
__u32 CIPmask;
|
||||
__u32 CIPmask2;
|
||||
struct FsmInst listen_m;
|
||||
} Listen_t;
|
||||
|
||||
void listenConstr(Listen_t *listen, Contr_t *contr, __u16 ApplId);
|
||||
void listenDestr(Listen_t *listen);
|
||||
void listenDebug(Listen_t *listen, __u32 level, char *fmt, ...);
|
||||
void listenSendMessage(Listen_t *listen, struct sk_buff *skb);
|
||||
int listenHandle(Listen_t *listen, __u16 CIPValue);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// struct Appl
|
||||
|
||||
#define APPL_FLAG_D2TRACE 1
|
||||
|
||||
typedef struct _Appl {
|
||||
Contr_t *contr;
|
||||
__u16 ApplId;
|
||||
__u16 MsgId;
|
||||
Listen_t listen;
|
||||
struct _Cplci *cplcis[CAPI_MAXPLCI];
|
||||
__u32 NotificationMask;
|
||||
u_long flags;
|
||||
capi_register_params rp;
|
||||
} Appl_t;
|
||||
|
||||
void applConstr(Appl_t *appl, Contr_t *contr, __u16 ApplId, capi_register_params *rp);
|
||||
void applDestr(Appl_t *appl);
|
||||
void applDebug(Appl_t *appl, __u32 level, char *fmt, ...);
|
||||
void applSendMessage(Appl_t *appl, struct sk_buff *skb);
|
||||
void applFacilityReq(Appl_t *appl, struct sk_buff *skb);
|
||||
void applSuppFacilityReq(Appl_t *appl, _cmsg *cmsg);
|
||||
int applGetSupportedServices(Appl_t *appl, struct FacReqParm *facReqParm,
|
||||
struct FacConfParm *facConfParm);
|
||||
int applFacListen(Appl_t *appl, struct FacReqParm *facReqParm,
|
||||
struct FacConfParm *facConfParm);
|
||||
int applFacCFActivate(Appl_t *appl, struct FacReqParm *facReqParm,
|
||||
struct FacConfParm *facConfParm);
|
||||
int applFacCFDeactivate(Appl_t *appl, struct FacReqParm *facReqParm,
|
||||
struct FacConfParm *facConfParm);
|
||||
int applFacCFInterrogateNumbers(Appl_t *appl, struct FacReqParm *facReqParm,
|
||||
struct FacConfParm *facConfParm);
|
||||
int applFacCFInterrogateParameters(Appl_t *appl, struct FacReqParm *facReqParm,
|
||||
struct FacConfParm *facConfParm);
|
||||
void applManufacturerReq(Appl_t *appl, struct sk_buff *skb);
|
||||
void applD2Trace(Appl_t *appl, u_char *buf, int len);
|
||||
DummyProcess_t *applNewDummyPc(Appl_t *appl, __u16 Function, __u32 Handle);
|
||||
struct _Cplci *applNewCplci(Appl_t *appl, struct _Plci *plci);
|
||||
struct _Cplci *applAdr2cplci(Appl_t *appl, __u32 adr);
|
||||
void applDelCplci(Appl_t *appl, struct _Cplci *cplci);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// struct Plci
|
||||
|
||||
#define PLCI_FLAG_ALERTING 1
|
||||
#define PLCI_FLAG_OUTGOING 2
|
||||
|
||||
typedef struct _Plci {
|
||||
Contr_t *contr;
|
||||
__u32 adrPLCI;
|
||||
u_int id;
|
||||
u_long flags;
|
||||
int nAppl;
|
||||
struct _Cplci *cplcis[CAPI_MAXAPPL];
|
||||
} Plci_t;
|
||||
|
||||
void plciConstr(Plci_t *plci, Contr_t *contr, __u32 adrPLCI, u_int id);
|
||||
void plciDestr(Plci_t *plci);
|
||||
void plciDebug(Plci_t *plci, __u32 level, char *fmt, ...);
|
||||
int plci_l3l4(Plci_t *, int, struct sk_buff *);
|
||||
void plciAttachCplci(Plci_t *plci, struct _Cplci *cplci);
|
||||
void plciDetachCplci(Plci_t *plci, struct _Cplci *cplci);
|
||||
void plciNewCrInd(Plci_t *plci, void *);
|
||||
void plciNewCrReq(Plci_t *plci);
|
||||
int plciL4L3(Plci_t *, __u32, struct sk_buff *);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// struct Cplci
|
||||
|
||||
typedef struct _Cplci {
|
||||
__u32 adrPLCI;
|
||||
Plci_t *plci;
|
||||
Appl_t *appl;
|
||||
struct _Ncci *ncci;
|
||||
Contr_t *contr;
|
||||
struct FsmInst plci_m;
|
||||
u_char cause[4]; // we may get a cause from l3 DISCONNECT message
|
||||
// which we'll need send in DISCONNECT_IND caused by
|
||||
// l3 RELEASE message
|
||||
int bchannel;
|
||||
struct Bprotocol Bprotocol;
|
||||
} Cplci_t;
|
||||
|
||||
void cplciConstr(Cplci_t *cplci, Appl_t *appl, Plci_t *plci);
|
||||
void cplciDestr(Cplci_t *cplci);
|
||||
void cplciDebug(Cplci_t *cplci, __u32 level, char *fmt, ...);
|
||||
void cplci_l3l4(Cplci_t *cplci, int pr, void *arg);
|
||||
void cplciSendMessage(Cplci_t *cplci, struct sk_buff *skb);
|
||||
void cplciClearOtherApps(Cplci_t *cplci);
|
||||
void cplciInfoIndMsg(Cplci_t *, __u32, unsigned char);
|
||||
void cplciInfoIndIE(Cplci_t *, unsigned char, __u32, Q931_info_t *);
|
||||
void cplciRecvCmsg(Cplci_t *cplci, _cmsg *cmsg);
|
||||
void cplciCmsgHeader(Cplci_t *cplci, _cmsg *cmsg, __u8 cmd, __u8 subcmd);
|
||||
void cplciLinkUp(Cplci_t *cplci);
|
||||
void cplciLinkDown(Cplci_t *cplci);
|
||||
int cplciFacSuspendReq(Cplci_t *cplci, struct FacReqParm *facReqParm,
|
||||
struct FacConfParm *facConfParm);
|
||||
int cplciFacResumeReq(Cplci_t *cplci, struct FacReqParm *facReqParm,
|
||||
struct FacConfParm *facConfParm);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Ncci_t
|
||||
|
||||
typedef struct _Ncci {
|
||||
BInst_t *binst;
|
||||
__u32 adrNCCI;
|
||||
Contr_t *contr;
|
||||
Cplci_t *cplci;
|
||||
Appl_t *appl;
|
||||
struct FsmInst ncci_m;
|
||||
int window;
|
||||
u_long Flags;
|
||||
struct {
|
||||
struct sk_buff *skb;
|
||||
__u16 DataHandle;
|
||||
__u16 MsgId;
|
||||
} xmit_skb_handles[CAPI_MAXDATAWINDOW];
|
||||
struct sk_buff *recv_skb_handles[CAPI_MAXDATAWINDOW];
|
||||
struct sk_buff_head squeue;
|
||||
_cmsg tmpmsg;
|
||||
} Ncci_t;
|
||||
|
||||
#define NCCI_FLG_FCTRL 1
|
||||
#define NCCI_FLG_BUSY 2
|
||||
|
||||
void ncciConstr(Ncci_t *ncci, Cplci_t *cplci);
|
||||
void ncciDestr(Ncci_t *ncci);
|
||||
void ncciSendMessage(Ncci_t *, struct sk_buff *);
|
||||
int ncci_l3l4(mISDNif_t *, struct sk_buff *);
|
||||
void ncciLinkUp(Ncci_t *ncci);
|
||||
void ncciLinkDown(Ncci_t *ncci);
|
||||
void ncciInitSt(Ncci_t *ncci);
|
||||
void ncciReleaseSt(Ncci_t *ncci);
|
||||
__u16 ncciSelectBprotocol(Ncci_t *ncci);
|
||||
void ncciRecvCmsg(Ncci_t *ncci, _cmsg *cmsg);
|
||||
void ncciCmsgHeader(Ncci_t *ncci, _cmsg *cmsg, __u8 cmd, __u8 subcmd);
|
||||
|
||||
|
||||
int capiEncodeWord(__u8 *dest, __u16 i);
|
||||
int capiEncodeDWord(__u8 *dest, __u32 i);
|
||||
int capiEncodeFacIndCFact(__u8 *dest, __u16 SupplementaryServiceReason, __u32 Handle);
|
||||
int capiEncodeFacIndCFdeact(__u8 *dest, __u16 SupplementaryServiceReason, __u32 Handle);
|
||||
int capiEncodeFacIndCFNotAct(__u8 *dest, struct ActDivNotification *actNot);
|
||||
int capiEncodeFacIndCFNotDeact(__u8 *dest, struct DeactDivNotification *deactNot);
|
||||
int capiEncodeFacIndCFinterParameters(__u8 *dest, __u16 SupplementaryServiceReason, __u32 Handle,
|
||||
struct IntResultList *intResultList);
|
||||
int capiEncodeFacIndCFinterNumbers(__u8 *dest, __u16 SupplementaryServiceReason, __u32 Handle,
|
||||
struct ServedUserNumberList *list);
|
||||
int capiEncodeFacConfParm(__u8 *dest, struct FacConfParm *facConfParm);
|
||||
|
||||
#endif
|
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "capi.h"
|
||||
#include "m_capi.h"
|
||||
#include "asn1.h"
|
||||
|
||||
int capiEncodeWord(__u8 *p, __u16 i)
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include <linux/vmalloc.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include "capi.h"
|
||||
#include "m_capi.h"
|
||||
#include "helper.h"
|
||||
#include "debug.h"
|
||||
|
||||
|
@ -12,45 +12,52 @@
|
|||
if (contr->debug & lev) capidebug(lev, fmt, ## args)
|
||||
|
||||
void
|
||||
contrDestr(Contr_t *contr)
|
||||
ControllerDestr(Controller_t *contr)
|
||||
{
|
||||
int i;
|
||||
mISDNinstance_t *inst = &contr->inst;
|
||||
mISDNinstance_t *inst = &contr->inst;
|
||||
struct list_head *item, *next;
|
||||
u_long flags;
|
||||
|
||||
for (i = 0; i < CAPI_MAXAPPL; i++) {
|
||||
if (contr->appls[i]) {
|
||||
applDestr(contr->appls[i]);
|
||||
kfree(contr->appls[i]);
|
||||
contr->appls[i] = NULL;
|
||||
}
|
||||
spin_lock_irqsave(&contr->list_lock, flags);
|
||||
list_for_each_safe(item, next, &contr->Applications) {
|
||||
ApplicationDestr((Application_t *)item, 3);
|
||||
}
|
||||
for (i = 0; i < CAPI_MAXPLCI; i++) {
|
||||
if (contr->plcis[i]) {
|
||||
plciDestr(contr->plcis[i]);
|
||||
kfree(contr->plcis[i]);
|
||||
contr->plcis[i] = NULL;
|
||||
if (contr->plcis) {
|
||||
Plci_t *plci = contr->plcis;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < contr->maxplci; i++) {
|
||||
AppPlci_t *aplci;
|
||||
if (test_bit(PLCI_STATE_ACTIV, &plci->state)) {
|
||||
if (plci->nAppl) {
|
||||
printk(KERN_ERR "%s: PLCI(%x) still busy (%d)\n",
|
||||
__FUNCTION__, plci->addr, plci->nAppl);
|
||||
list_for_each_safe(item, next, &plci->AppPlcis) {
|
||||
aplci = (AppPlci_t *)item;
|
||||
aplci->contr = NULL;
|
||||
plciDetachAppPlci(plci, aplci);
|
||||
AppPlciDestr(aplci);
|
||||
}
|
||||
}
|
||||
}
|
||||
plci++;
|
||||
}
|
||||
kfree(contr->plcis);
|
||||
contr->plcis = NULL;
|
||||
}
|
||||
for (i = 0; i < CAPI_MAXDUMMYPCS; i++) {
|
||||
if (contr->dummy_pcs[i]) {
|
||||
dummyPcDestr(contr->dummy_pcs[i]);
|
||||
kfree(contr->dummy_pcs[i]);
|
||||
contr->dummy_pcs[i] = NULL;
|
||||
}
|
||||
list_for_each_safe(item, next, &contr->SSProcesse) {
|
||||
SSProcessDestr((SSProcess_t *)item);
|
||||
}
|
||||
#ifdef OLDCAPI_DRIVER_INTERFACE
|
||||
if (contr->ctrl)
|
||||
cdrv_if->detach_ctr(contr->ctrl);
|
||||
#else
|
||||
detach_capi_ctr(contr->ctrl);
|
||||
kfree(contr->ctrl);
|
||||
contr->ctrl = NULL;
|
||||
#endif
|
||||
while (contr->binst) {
|
||||
BInst_t *binst = contr->binst;
|
||||
REMOVE_FROM_LISTBASE(binst, contr->binst);
|
||||
kfree(binst);
|
||||
if (contr->ctrl) {
|
||||
detach_capi_ctr(contr->ctrl);
|
||||
kfree(contr->ctrl);
|
||||
}
|
||||
#endif
|
||||
contr->ctrl = NULL;
|
||||
if (inst->up.peer) {
|
||||
inst->up.peer->obj->ctrl(inst->up.peer,
|
||||
MGR_DISCONNECT | REQUEST, &inst->up);
|
||||
|
@ -59,24 +66,25 @@ contrDestr(Contr_t *contr)
|
|||
inst->down.peer->obj->ctrl(inst->down.peer,
|
||||
MGR_DISCONNECT | REQUEST, &inst->down);
|
||||
}
|
||||
inst->obj->ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
|
||||
REMOVE_FROM_LISTBASE(contr, ((Contr_t *)inst->obj->ilist));
|
||||
while (contr->binst) {
|
||||
BInst_t *binst = contr->binst;
|
||||
REMOVE_FROM_LISTBASE(binst, contr->binst);
|
||||
kfree(binst);
|
||||
}
|
||||
if (contr->entity != MISDN_ENTITY_NONE)
|
||||
inst->obj->ctrl(inst, MGR_DELENTITY | REQUEST, (void *)contr->entity);
|
||||
inst->obj->ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
|
||||
REMOVE_FROM_LISTBASE(contr, ((Controller_t *)inst->obj->ilist));
|
||||
spin_unlock_irqrestore(&contr->list_lock, flags);
|
||||
kfree(contr);
|
||||
}
|
||||
|
||||
void
|
||||
contrRun(Contr_t *contr)
|
||||
ControllerRun(Controller_t *contr)
|
||||
{
|
||||
BInst_t *binst;
|
||||
int nb, ret;
|
||||
int ret;
|
||||
|
||||
nb = 0;
|
||||
binst = contr->binst;
|
||||
while(binst) {
|
||||
nb++;
|
||||
binst = binst->next;
|
||||
}
|
||||
if (contr->inst.st && contr->inst.st->mgr)
|
||||
sprintf(contr->ctrl->manu, "mISDN CAPI controller %s", contr->inst.st->mgr->name);
|
||||
else
|
||||
|
@ -88,7 +96,7 @@ contrRun(Contr_t *contr)
|
|||
contr->ctrl->version.minormanuversion = 0;
|
||||
memset(&contr->ctrl->profile, 0, sizeof(struct capi_profile));
|
||||
contr->ctrl->profile.ncontroller = 1;
|
||||
contr->ctrl->profile.nbchannel = nb;
|
||||
contr->ctrl->profile.nbchannel = contr->nr_bc;
|
||||
contrDebug(contr, CAPI_DBG_INFO, "%s: %s version(%s)",
|
||||
__FUNCTION__, contr->ctrl->manu, contr->ctrl->serial);
|
||||
// FIXME
|
||||
|
@ -101,7 +109,7 @@ contrRun(Contr_t *contr)
|
|||
contr->ctrl->profile.goptions |= GLOBALOPT_DTMF |
|
||||
GLOBALOPT_SUPPLEMENTARY_SERVICE;
|
||||
|
||||
if (nb) {
|
||||
if (contr->nr_bc) {
|
||||
mISDN_pid_t pidmask;
|
||||
|
||||
memset(&pidmask, 0, sizeof(mISDN_pid_t));
|
||||
|
@ -132,67 +140,76 @@ contrRun(Contr_t *contr)
|
|||
#endif
|
||||
}
|
||||
|
||||
Appl_t
|
||||
*contrId2appl(Contr_t *contr, __u16 ApplId)
|
||||
Application_t
|
||||
*getApplication4Id(Controller_t *contr, __u16 ApplId)
|
||||
{
|
||||
if ((ApplId < 1) || (ApplId > CAPI_MAXAPPL)) {
|
||||
int_error();
|
||||
return 0;
|
||||
struct list_head *item;
|
||||
Application_t *ap = NULL;
|
||||
|
||||
list_for_each(item, &contr->Applications) {
|
||||
ap = (Application_t *)item;
|
||||
if (ap->ApplId == ApplId)
|
||||
break;
|
||||
ap = NULL;
|
||||
}
|
||||
return contr->appls[ApplId - 1];
|
||||
return(ap);
|
||||
}
|
||||
|
||||
Plci_t
|
||||
*contrAdr2plci(Contr_t *contr, __u32 adr)
|
||||
*getPlci4Addr(Controller_t *contr, __u32 addr)
|
||||
{
|
||||
int i = (adr >> 8);
|
||||
int i = (addr >> 8) & 0xff;
|
||||
|
||||
if ((i < 1) || (i > CAPI_MAXPLCI)) {
|
||||
if ((i < 1) || (i > contr->maxplci)) {
|
||||
int_error();
|
||||
return 0;
|
||||
return(NULL);
|
||||
}
|
||||
return contr->plcis[i - 1];
|
||||
return(&contr->plcis[i - 1]);
|
||||
}
|
||||
|
||||
static void
|
||||
RegisterAppl(struct capi_ctr *ctrl, __u16 ApplId, capi_register_params *rp)
|
||||
RegisterApplication(struct capi_ctr *ctrl, __u16 ApplId, capi_register_params *rp)
|
||||
{
|
||||
Contr_t *contr = ctrl->driverdata;
|
||||
Appl_t *appl;
|
||||
Controller_t *contr = ctrl->driverdata;
|
||||
Application_t *appl;
|
||||
u_long flags;
|
||||
int ret;
|
||||
|
||||
contrDebug(contr, CAPI_DBG_APPL, "%s: ApplId(%x)", __FUNCTION__, ApplId);
|
||||
appl = contrId2appl(contr, ApplId);
|
||||
appl = getApplication4Id(contr, ApplId);
|
||||
if (appl) {
|
||||
int_error();
|
||||
return;
|
||||
}
|
||||
appl = kmalloc(sizeof(Appl_t), GFP_ATOMIC);
|
||||
if (!appl) {
|
||||
spin_lock_irqsave(&contr->list_lock, flags);
|
||||
ret = ApplicationConstr(contr, ApplId, rp);
|
||||
spin_unlock_irqrestore(&contr->list_lock, flags);
|
||||
if (ret) {
|
||||
int_error();
|
||||
return;
|
||||
}
|
||||
contr->appls[ApplId - 1] = appl;
|
||||
applConstr(appl, contr, ApplId, rp);
|
||||
#ifdef OLDCAPI_DRIVER_INTERFACE
|
||||
contr->ctrl->appl_registered(contr->ctrl, ApplId);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
ReleaseAppl(struct capi_ctr *ctrl, __u16 ApplId)
|
||||
ReleaseApplication(struct capi_ctr *ctrl, __u16 ApplId)
|
||||
{
|
||||
Contr_t *contr = ctrl->driverdata;
|
||||
Appl_t *appl;
|
||||
Controller_t *contr = ctrl->driverdata;
|
||||
Application_t *appl;
|
||||
u_long flags;
|
||||
|
||||
contrDebug(contr, CAPI_DBG_APPL, "%s: ApplId(%x) caller:%lx", __FUNCTION__, ApplId, __builtin_return_address(0));
|
||||
appl = contrId2appl(contr, ApplId);
|
||||
spin_lock_irqsave(&contr->list_lock, flags);
|
||||
appl = getApplication4Id(contr, ApplId);
|
||||
if (!appl) {
|
||||
spin_unlock_irqrestore(&contr->list_lock, flags);
|
||||
int_error();
|
||||
return;
|
||||
}
|
||||
applDestr(appl);
|
||||
kfree(appl);
|
||||
contr->appls[ApplId - 1] = NULL;
|
||||
ApplicationDestr(appl, 1);
|
||||
spin_unlock_irqrestore(&contr->list_lock, flags);
|
||||
#ifdef OLDCAPI_DRIVER_INTERFACE
|
||||
contr->ctrl->appl_released(contr->ctrl, ApplId);
|
||||
#endif
|
||||
|
@ -205,18 +222,18 @@ static u16
|
|||
#endif
|
||||
SendMessage(struct capi_ctr *ctrl, struct sk_buff *skb)
|
||||
{
|
||||
Contr_t *contr = ctrl->driverdata;
|
||||
Appl_t *appl;
|
||||
int ApplId;
|
||||
int err = CAPI_NOERROR;
|
||||
Controller_t *contr = ctrl->driverdata;
|
||||
Application_t *appl;
|
||||
int ApplId;
|
||||
int err = CAPI_NOERROR;
|
||||
|
||||
ApplId = CAPIMSG_APPID(skb->data);
|
||||
appl = contrId2appl(contr, ApplId);
|
||||
appl = getApplication4Id(contr, ApplId);
|
||||
if (!appl) {
|
||||
int_error();
|
||||
err = CAPI_ILLAPPNR;
|
||||
} else
|
||||
applSendMessage(appl, skb);
|
||||
ApplicationSendMessage(appl, skb);
|
||||
#ifndef OLDCAPI_DRIVER_INTERFACE
|
||||
return(err);
|
||||
#endif
|
||||
|
@ -225,7 +242,7 @@ SendMessage(struct capi_ctr *ctrl, struct sk_buff *skb)
|
|||
static int
|
||||
LoadFirmware(struct capi_ctr *ctrl, capiloaddata *data)
|
||||
{
|
||||
Contr_t *contr = ctrl->driverdata;
|
||||
Controller_t *contr = ctrl->driverdata;
|
||||
struct firm {
|
||||
int len;
|
||||
void *data;
|
||||
|
@ -253,7 +270,7 @@ LoadFirmware(struct capi_ctr *ctrl, capiloaddata *data)
|
|||
static char *
|
||||
procinfo(struct capi_ctr *ctrl)
|
||||
{
|
||||
Contr_t *contr = ctrl->driverdata;
|
||||
Controller_t *contr = ctrl->driverdata;
|
||||
|
||||
if (CAPI_DBG_INFO & contr->debug)
|
||||
printk(KERN_DEBUG "%s\n", __FUNCTION__);
|
||||
|
@ -279,20 +296,20 @@ read_proc(char *page, char **start, off_t off, int count, int *eof, struct capi_
|
|||
|
||||
|
||||
static void
|
||||
ResetContr(struct capi_ctr *ctrl)
|
||||
ResetController(struct capi_ctr *ctrl)
|
||||
{
|
||||
Contr_t *contr = ctrl->driverdata;
|
||||
int ApplId;
|
||||
Appl_t *appl;
|
||||
Controller_t *contr = ctrl->driverdata;
|
||||
struct list_head *item, *next;
|
||||
u_long flags;
|
||||
|
||||
for (ApplId = 1; ApplId <= CAPI_MAXAPPL; ApplId++) {
|
||||
appl = contrId2appl(contr, ApplId);
|
||||
if (appl) {
|
||||
applDestr(appl);
|
||||
kfree(appl);
|
||||
}
|
||||
contr->appls[ApplId - 1] = NULL;
|
||||
spin_lock_irqsave(&contr->list_lock, flags);
|
||||
list_for_each_safe(item, next, &contr->Applications) {
|
||||
ApplicationDestr((Application_t *)item, 2);
|
||||
}
|
||||
list_for_each_safe(item, next, &contr->SSProcesse) {
|
||||
SSProcessDestr((SSProcess_t *)item);
|
||||
}
|
||||
spin_unlock_irqrestore(&contr->list_lock, flags);
|
||||
#ifdef OLDCAPI_DRIVER_INTERFACE
|
||||
contr->ctrl->reseted(contr->ctrl);
|
||||
#else
|
||||
|
@ -302,9 +319,9 @@ ResetContr(struct capi_ctr *ctrl)
|
|||
|
||||
#ifdef OLDCAPI_DRIVER_INTERFACE
|
||||
static void
|
||||
Remove_Contr(struct capi_ctr *ctrl)
|
||||
Remove_Controller(struct capi_ctr *ctrl)
|
||||
{
|
||||
Contr_t *contr = ctrl->driverdata;
|
||||
Controller_t *contr = ctrl->driverdata;
|
||||
|
||||
if (CAPI_DBG_INFO & contr->debug)
|
||||
printk(KERN_DEBUG "%s\n", __FUNCTION__);
|
||||
|
@ -314,10 +331,10 @@ struct capi_driver mISDN_driver = {
|
|||
"mISDN",
|
||||
"0.01",
|
||||
LoadFirmware,
|
||||
ResetContr,
|
||||
Remove_Contr,
|
||||
RegisterAppl,
|
||||
ReleaseAppl,
|
||||
ResetController,
|
||||
Remove_Controller,
|
||||
RegisterApplication,
|
||||
ReleaseApplication,
|
||||
SendMessage,
|
||||
procinfo,
|
||||
read_proc,
|
||||
|
@ -327,136 +344,129 @@ struct capi_driver mISDN_driver = {
|
|||
#endif
|
||||
|
||||
void
|
||||
contrD2Trace(Contr_t *contr, u_char *buf, int len)
|
||||
ControllerD2Trace(Controller_t *contr, u_char *buf, int len)
|
||||
{
|
||||
Appl_t *appl;
|
||||
__u16 applId;
|
||||
struct list_head *item;
|
||||
|
||||
for (applId = 1; applId <= CAPI_MAXAPPL; applId++) {
|
||||
appl = contrId2appl(contr, applId);
|
||||
if (appl) {
|
||||
applD2Trace(appl, buf, len);
|
||||
}
|
||||
list_for_each(item, &contr->Applications) {
|
||||
applD2Trace((Application_t *)item, buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
contrRecvCmsg(Contr_t *contr, _cmsg *cmsg)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
int len;
|
||||
|
||||
capi_cmsg2message(cmsg, contr->msgbuf);
|
||||
len = CAPIMSG_LEN(contr->msgbuf);
|
||||
contrDebug(contr, CAPI_DBG_CONTR_MSG, "%s: len(%d) applid(%x) %s msgnr(%d) addr(%08x)",
|
||||
__FUNCTION__, len, cmsg->ApplId, capi_cmd2str(cmsg->Command, cmsg->Subcommand),
|
||||
cmsg->Messagenumber, cmsg->adr.adrController);
|
||||
if (!(skb = alloc_skb(len, GFP_ATOMIC))) {
|
||||
printk(KERN_ERR "%s: no mem for %d bytes\n", __FUNCTION__, len);
|
||||
int_error();
|
||||
return;
|
||||
}
|
||||
memcpy(skb_put(skb, len), contr->msgbuf, len);
|
||||
#ifdef OLDCAPI_DRIVER_INTERFACE
|
||||
contr->ctrl->handle_capimsg(contr->ctrl, cmsg->ApplId, skb);
|
||||
#else
|
||||
capi_ctr_handle_message(contr->ctrl, cmsg->ApplId, skb);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
contrAnswerCmsg(Contr_t *contr, _cmsg *cmsg, __u16 Info)
|
||||
{
|
||||
capi_cmsg_answer(cmsg);
|
||||
cmsg->Info = Info;
|
||||
contrRecvCmsg(contr, cmsg);
|
||||
}
|
||||
|
||||
void
|
||||
contrAnswerMessage(Contr_t *contr, struct sk_buff *skb, __u16 Info)
|
||||
{
|
||||
_cmsg cmsg;
|
||||
|
||||
capi_message2cmsg(&cmsg, skb->data);
|
||||
contrAnswerCmsg(contr, &cmsg, Info);
|
||||
}
|
||||
|
||||
static Plci_t *
|
||||
contrGetPLCI4ID(Contr_t *contr, u_int id)
|
||||
static __inline__ Plci_t *
|
||||
getPlci4L3id(Controller_t *contr, u_int l3id)
|
||||
{
|
||||
Plci_t *plci = contr->plcis;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CAPI_MAXPLCI; i++) {
|
||||
if (!contr->plcis[i])
|
||||
continue;
|
||||
if (contr->plcis[i]->id == id)
|
||||
return(contr->plcis[i]);
|
||||
for (i = 0; i < contr->maxplci; i++) {
|
||||
if (test_bit(PLCI_STATE_ACTIV, &plci->state) &&
|
||||
(plci->l3id == l3id))
|
||||
return(plci);
|
||||
plci++;
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
Plci_t *
|
||||
contrNewPlci(Contr_t *contr, u_int id)
|
||||
int
|
||||
ControllerNewPlci(Controller_t *contr, Plci_t **plci_p, u_int l3id)
|
||||
{
|
||||
Plci_t *plci;
|
||||
int i;
|
||||
Plci_t *plci = contr->plcis;
|
||||
|
||||
for (i = 0; i < CAPI_MAXPLCI; i++) {
|
||||
if (!contr->plcis[i])
|
||||
for (i = 0; i < contr->maxplci; i++) {
|
||||
if (!test_and_set_bit(PLCI_STATE_ACTIV, &plci->state))
|
||||
break;
|
||||
plci++;
|
||||
}
|
||||
if (i == CAPI_MAXPLCI) {
|
||||
return 0;
|
||||
if (i == contr->maxplci) {
|
||||
contrDebug(contr, CAPI_DBG_PLCI, "%s: no free PLCI",
|
||||
__FUNCTION__);
|
||||
return(-EBUSY); //FIXME
|
||||
}
|
||||
if (id == MISDN_ID_ANY) {
|
||||
*plci_p = plci;
|
||||
if (l3id == MISDN_ID_ANY) {
|
||||
if (contr->entity == MISDN_ENTITY_NONE) {
|
||||
printk(KERN_ERR "mISDN %s: no ENTITY id\n",
|
||||
__FUNCTION__);
|
||||
return NULL;
|
||||
test_and_clear_bit(PLCI_STATE_ACTIV, &plci->state);
|
||||
return(-EINVAL); //FIXME
|
||||
}
|
||||
id = (contr->entity << 16) | ((i+1) << 8) | (contr->adrController & 0xFF);
|
||||
plci->l3id = (contr->entity << 16) | plci->addr;
|
||||
} else {
|
||||
plci = getPlci4L3id(contr, l3id);
|
||||
if (plci) {
|
||||
printk(KERN_WARNING "mISDN %s: PLCI(%x) allready has l3id(%x)\n",
|
||||
__FUNCTION__, plci->addr, l3id);
|
||||
test_and_clear_bit(PLCI_STATE_ACTIV, &(*plci_p)->state);
|
||||
return(-EBUSY);
|
||||
}
|
||||
plci = *plci_p;
|
||||
plci->l3id = l3id;
|
||||
}
|
||||
plci = contrGetPLCI4ID(contr, id);
|
||||
if (plci) {
|
||||
printk(KERN_ERR "mISDN %s: PLCI(%x) allready has id(%x)\n",
|
||||
__FUNCTION__, plci->adrPLCI, id);
|
||||
return NULL;
|
||||
}
|
||||
plci = kmalloc(sizeof(Plci_t), GFP_ATOMIC);
|
||||
if (!plci) {
|
||||
int_error();
|
||||
return NULL;
|
||||
}
|
||||
contr->plcis[i] = plci;
|
||||
plciConstr(plci, contr, (i+1) << 8 | contr->adrController, id);
|
||||
contrDebug(contr, CAPI_DBG_PLCI, "%s: PLCI(%x) plci(%p,%d) id(%x)",
|
||||
__FUNCTION__, plci->adrPLCI, plci, sizeof(*plci), plci->id);
|
||||
return plci;
|
||||
}
|
||||
|
||||
void
|
||||
contrDelPlci(Contr_t *contr, Plci_t *plci)
|
||||
{
|
||||
int i = plci->adrPLCI >> 8;
|
||||
|
||||
contrDebug(contr, CAPI_DBG_PLCI, "%s: PLCI(%x) plci(%p)", __FUNCTION__, plci->adrPLCI, plci);
|
||||
if ((i < 1) || (i > CAPI_MAXPLCI)) {
|
||||
int_error();
|
||||
return;
|
||||
}
|
||||
if (contr->plcis[i-1] != plci) {
|
||||
int_error();
|
||||
return;
|
||||
}
|
||||
plciDestr(plci);
|
||||
kfree(plci);
|
||||
contr->plcis[i-1] = NULL;
|
||||
__FUNCTION__, plci->addr, plci, sizeof(*plci), plci->l3id);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int
|
||||
contrL3L4(mISDNif_t *hif, struct sk_buff *skb)
|
||||
ControllerReleasePlci(Plci_t *plci)
|
||||
{
|
||||
Contr_t *contr;
|
||||
if (!plci->contr) {
|
||||
int_error();
|
||||
return(-EINVAL);
|
||||
}
|
||||
if (plci->nAppl) {
|
||||
contrDebug(plci->contr, CAPI_DBG_PLCI, "%s: PLCI(%x) still has %d Applications",
|
||||
__FUNCTION__, plci->addr, plci->nAppl);
|
||||
return(-EBUSY);
|
||||
}
|
||||
if (!list_empty(&plci->AppPlcis)) {
|
||||
int_errtxt("PLCI(%x) AppPlcis list not empty", plci->addr);
|
||||
return(-EBUSY);
|
||||
}
|
||||
test_and_clear_bit(PLCI_STATE_ALERTING, &plci->state);
|
||||
test_and_clear_bit(PLCI_STATE_OUTGOING, &plci->state);
|
||||
plci->l3id = MISDN_ID_NONE;
|
||||
if (!test_and_clear_bit(PLCI_STATE_ACTIV, &plci->state))
|
||||
int_errtxt("PLCI(%x) was not activ", plci->addr);
|
||||
return(0);
|
||||
}
|
||||
|
||||
void
|
||||
ControllerAddSSProcess(Controller_t *contr, SSProcess_t *sp)
|
||||
{
|
||||
u_long flags;
|
||||
|
||||
INIT_LIST_HEAD(&sp->head);
|
||||
sp->contr = contr;
|
||||
sp->addr = contr->addr;
|
||||
spin_lock_irqsave(&contr->list_lock, flags);
|
||||
contr->LastInvokeId++;
|
||||
sp->invokeId = contr->LastInvokeId;
|
||||
list_add(&sp->head, &contr->SSProcesse);
|
||||
spin_unlock_irqrestore(&contr->list_lock, flags);
|
||||
}
|
||||
|
||||
SSProcess_t
|
||||
*getSSProcess4Id(Controller_t *contr, __u16 id)
|
||||
{
|
||||
struct list_head *item;
|
||||
SSProcess_t *sp = NULL;
|
||||
|
||||
list_for_each(item, &contr->SSProcesse) {
|
||||
sp = (SSProcess_t *)item;
|
||||
if (sp->invokeId == id)
|
||||
break;
|
||||
sp = NULL;
|
||||
}
|
||||
return(sp);
|
||||
}
|
||||
|
||||
int
|
||||
ControllerL3L4(mISDNif_t *hif, struct sk_buff *skb)
|
||||
{
|
||||
Controller_t *contr;
|
||||
Plci_t *plci;
|
||||
int ret = -EINVAL;
|
||||
mISDN_head_t *hh;
|
||||
|
@ -468,66 +478,103 @@ contrL3L4(mISDNif_t *hif, struct sk_buff *skb)
|
|||
contrDebug(contr, CAPI_DBG_CONTR_INFO, "%s: prim(%x) id(%x)",
|
||||
__FUNCTION__, hh->prim, hh->dinfo);
|
||||
if (hh->prim == (CC_NEW_CR | INDICATION)) {
|
||||
plci = contrNewPlci(contr, hh->dinfo);
|
||||
if (plci) {
|
||||
ret = 0;
|
||||
ret = ControllerNewPlci(contr, &plci, hh->dinfo);
|
||||
if(!ret)
|
||||
dev_kfree_skb(skb);
|
||||
} else
|
||||
ret = -EBUSY;
|
||||
} else if (hh->dinfo == MISDN_ID_DUMMY) {
|
||||
ret = contrDummyInd(contr, hh->prim, skb);
|
||||
ret = Supplementary_l3l4(contr, hh->prim, skb);
|
||||
} else {
|
||||
if (!(plci = contrGetPLCI4ID(contr, hh->dinfo))) {
|
||||
if (!(plci = getPlci4L3id(contr, hh->dinfo))) {
|
||||
contrDebug(contr, CAPI_DBG_WARN, "%s: unknown plci prim(%x) id(%x)",
|
||||
__FUNCTION__, hh->prim, hh->dinfo);
|
||||
return(-ENODEV);
|
||||
}
|
||||
contrDebug(contr, CAPI_DBG_PLCI, "%s: PLCI(%x) plci(%p)", __FUNCTION__, plci->adrPLCI, plci);
|
||||
contrDebug(contr, CAPI_DBG_PLCI, "%s: PLCI(%x) plci(%p)", __FUNCTION__, plci->addr, plci);
|
||||
ret = plci_l3l4(plci, hh->prim, skb);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int
|
||||
contrL4L3(Contr_t *contr, u_int prim, int dinfo, struct sk_buff *skb)
|
||||
ControllerL4L3(Controller_t *contr, u_int prim, int dinfo, struct sk_buff *skb)
|
||||
{
|
||||
return(if_newhead(&contr->inst.down, prim, dinfo, skb));
|
||||
}
|
||||
|
||||
void
|
||||
contrPutStatus(Contr_t *contr, char *msg)
|
||||
ControllerPutStatus(Controller_t *contr, char *msg)
|
||||
{
|
||||
contrDebug(contr, CAPI_DBG_CONTR, "%s: %s", __FUNCTION__, msg);
|
||||
}
|
||||
|
||||
static int
|
||||
contrConstr(Contr_t *contr, mISDNstack_t *st, mISDN_pid_t *pid, mISDNobject_t *ocapi)
|
||||
{
|
||||
int
|
||||
ControllerConstr(Controller_t **contr_p, mISDNstack_t *st, mISDN_pid_t *pid, mISDNobject_t *ocapi)
|
||||
{
|
||||
Controller_t *contr;
|
||||
int retval;
|
||||
mISDNstack_t *cst = st->child;
|
||||
mISDNstack_t *cst;
|
||||
BInst_t *binst;
|
||||
|
||||
memset(contr, 0, sizeof(Contr_t));
|
||||
if (!st)
|
||||
return(-EINVAL);
|
||||
if (!pid)
|
||||
return(-EINVAL);
|
||||
contr = kmalloc(sizeof(Controller_t), GFP_KERNEL);
|
||||
if (!contr)
|
||||
return(-ENOMEM);
|
||||
memset(contr, 0, sizeof(Controller_t));
|
||||
INIT_LIST_HEAD(&contr->Applications);
|
||||
INIT_LIST_HEAD(&contr->SSProcesse);
|
||||
spin_lock_init(&contr->list_lock);
|
||||
memcpy(&contr->inst.pid, pid, sizeof(mISDN_pid_t));
|
||||
#ifndef OLDCAPI_DRIVER_INTERFACE
|
||||
if (!(contr->ctrl = kmalloc(sizeof(struct capi_ctr), GFP_ATOMIC))) {
|
||||
if (!(contr->ctrl = kmalloc(sizeof(struct capi_ctr), GFP_KERNEL))) {
|
||||
printk(KERN_ERR "no mem for contr->ctrl\n");
|
||||
int_error();
|
||||
ControllerDestr(contr);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(contr->ctrl, 0, sizeof(struct capi_ctr));
|
||||
#endif
|
||||
contr->adrController = st->id;
|
||||
cst = st->child;
|
||||
while(cst) {
|
||||
contr->nr_bc++;
|
||||
cst = cst->next;
|
||||
}
|
||||
if (!contr->nr_bc) {
|
||||
printk(KERN_ERR "no bchannels\n");
|
||||
ControllerDestr(contr);
|
||||
return(-EINVAL); // FIXME
|
||||
}
|
||||
if (contr->nr_bc <= 2)
|
||||
contr->maxplci = CAPI_MAXPLCI_BRI;
|
||||
else if (contr->nr_bc <= 8)
|
||||
contr->maxplci = contr->nr_bc * 2 + 4;
|
||||
else
|
||||
contr->maxplci = CAPI_MAXPLCI_PRI;
|
||||
contr->plcis = kmalloc(contr->maxplci*sizeof(Plci_t), GFP_KERNEL);
|
||||
if (!contr->plcis) {
|
||||
printk(KERN_ERR "no mem for contr->plcis\n");
|
||||
int_error();
|
||||
contr->maxplci = 0;
|
||||
ControllerDestr(contr);
|
||||
return -ENOMEM;
|
||||
}
|
||||
// FIXME ???
|
||||
contr->addr = st->id;
|
||||
sprintf(contr->inst.name, "CAPI %d", st->id);
|
||||
init_mISDNinstance(&contr->inst, ocapi, contr);
|
||||
if (!SetHandledPID(ocapi, &contr->inst.pid)) {
|
||||
int_error();
|
||||
ControllerDestr(contr);
|
||||
return(-ENOPROTOOPT);
|
||||
}
|
||||
cst = st->child;
|
||||
while(cst) {
|
||||
if (!(binst = kmalloc(sizeof(BInst_t), GFP_ATOMIC))) {
|
||||
if (!(binst = kmalloc(sizeof(BInst_t), GFP_KERNEL))) {
|
||||
printk(KERN_ERR "no mem for Binst\n");
|
||||
int_error();
|
||||
ControllerDestr(contr);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(binst, 0, sizeof(BInst_t));
|
||||
|
@ -540,7 +587,7 @@ contrConstr(Contr_t *contr, mISDNstack_t *st, mISDN_pid_t *pid, mISDNobject_t *o
|
|||
cst = cst->next;
|
||||
}
|
||||
APPEND_TO_LIST(contr, ocapi->ilist);
|
||||
contr->entity =
|
||||
contr->entity = MISDN_ENTITY_NONE;
|
||||
retval = ocapi->ctrl(&contr->inst, MGR_NEWENTITY | REQUEST, NULL);
|
||||
if (retval) {
|
||||
printk(KERN_WARNING "mISDN %s: MGR_NEWENTITY REQUEST failed err(%x)\n",
|
||||
|
@ -571,38 +618,19 @@ contrConstr(Contr_t *contr, mISDNstack_t *st, mISDN_pid_t *pid, mISDNobject_t *o
|
|||
retval = attach_capi_ctr(contr->ctrl);
|
||||
#endif
|
||||
if (!retval) {
|
||||
contr->adrController = contr->ctrl->cnr;
|
||||
contr->addr = contr->ctrl->cnr;
|
||||
plciInit(contr);
|
||||
ocapi->ctrl(st, MGR_REGLAYER | INDICATION, &contr->inst);
|
||||
contr->inst.up.stat = IF_DOWN;
|
||||
*contr_p = contr;
|
||||
} else {
|
||||
ControllerDestr(contr);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
Contr_t *
|
||||
newContr(mISDNobject_t *ocapi, mISDNstack_t *st, mISDN_pid_t *pid)
|
||||
{
|
||||
Contr_t *contr;
|
||||
|
||||
if (!pid)
|
||||
return(NULL);
|
||||
if (!st) {
|
||||
printk(KERN_ERR "newContr no stack\n");
|
||||
return(NULL);
|
||||
}
|
||||
contr = kmalloc(sizeof(Contr_t), GFP_KERNEL);
|
||||
if (!contr)
|
||||
return(NULL);
|
||||
|
||||
if (contrConstr(contr, st, pid, ocapi) != 0) {
|
||||
contrDestr(contr);
|
||||
kfree(contr);
|
||||
return(NULL);
|
||||
}
|
||||
return contr;
|
||||
}
|
||||
|
||||
BInst_t *
|
||||
contrSelChannel(Contr_t *contr, u_int channel)
|
||||
ControllerSelChannel(Controller_t *contr, u_int channel)
|
||||
{
|
||||
mISDNstack_t *cst;
|
||||
BInst_t *binst;
|
||||
|
@ -610,25 +638,8 @@ contrSelChannel(Contr_t *contr, u_int channel)
|
|||
int ret;
|
||||
|
||||
if (!contr->binst) {
|
||||
cst = contr->inst.st->child;
|
||||
if (!cst)
|
||||
return(NULL);
|
||||
while(cst) {
|
||||
if (!(binst = kmalloc(sizeof(BInst_t), GFP_ATOMIC))) {
|
||||
printk(KERN_ERR "no mem for Binst\n");
|
||||
int_error();
|
||||
return(NULL);
|
||||
}
|
||||
memset(binst, 0, sizeof(BInst_t));
|
||||
binst->bst = cst;
|
||||
binst->inst.st = cst;
|
||||
binst->inst.data = binst;
|
||||
binst->inst.obj = contr->inst.obj;
|
||||
binst->inst.pid.layermask = ISDN_LAYER(4);
|
||||
binst->inst.down.stat = IF_NOACTIV;
|
||||
APPEND_TO_LIST(binst, contr->binst);
|
||||
cst = cst->next;
|
||||
}
|
||||
int_errtxt("no binst for controller(%x)", contr->addr);
|
||||
return(NULL);
|
||||
}
|
||||
ci.channel = channel;
|
||||
ci.st.p = NULL;
|
||||
|
@ -652,13 +663,13 @@ contrSelChannel(Contr_t *contr, u_int channel)
|
|||
static void
|
||||
d2_listener(struct IsdnCardState *cs, u_char *buf, int len)
|
||||
{
|
||||
Contr_t *contr = cs->contr;
|
||||
Controller_t *contr = cs->contr;
|
||||
|
||||
if (!contr) {
|
||||
int_error();
|
||||
return;
|
||||
}
|
||||
|
||||
contrD2Trace(contr, buf, len);
|
||||
ControllerD2Trace(contr, buf, len);
|
||||
}
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "capi.h"
|
||||
#include "m_capi.h"
|
||||
#include "helper.h"
|
||||
#include "debug.h"
|
||||
|
||||
|
@ -43,77 +43,87 @@ static char* str_ev_listen[] = {
|
|||
static struct Fsm listen_fsm =
|
||||
{ 0, 0, 0, 0, 0 };
|
||||
|
||||
static void listen_debug(struct FsmInst *fi, char *fmt, ...)
|
||||
static void
|
||||
listen_debug(struct FsmInst *fi, char *fmt, ...)
|
||||
{
|
||||
char tmp[128];
|
||||
char *p = tmp;
|
||||
va_list args;
|
||||
Listen_t *listen = fi->userdata;
|
||||
Application_t *app = fi->userdata;
|
||||
|
||||
if (!fi->debug)
|
||||
return;
|
||||
va_start(args, fmt);
|
||||
p += sprintf(p, "Controller 0x%x ApplId %d listen ",
|
||||
listen->contr->adrController, listen->ApplId);
|
||||
app->contr->addr, app->ApplId);
|
||||
p += vsprintf(p, fmt, args);
|
||||
*p = 0;
|
||||
listenDebug(listen, CAPI_DBG_LISTEN_STATE, tmp);
|
||||
listenDebug(app, CAPI_DBG_LISTEN_STATE, tmp);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static void listen_req_l_x(struct FsmInst *fi, int event, void *arg, int state)
|
||||
static void
|
||||
listen_req_l_x(struct FsmInst *fi, int event, void *arg, int state)
|
||||
{
|
||||
Listen_t *listen = fi->userdata;
|
||||
_cmsg *cmsg = arg;
|
||||
Application_t *app = fi->userdata;
|
||||
_cmsg *cmsg = arg;
|
||||
|
||||
FsmChangeState(fi, state);
|
||||
|
||||
listen->InfoMask = cmsg->InfoMask;
|
||||
listen->CIPmask = cmsg->CIPmask;
|
||||
listen->CIPmask2 = cmsg->CIPmask2;
|
||||
listenDebug(listen, CAPI_DBG_LISTEN_INFO, "set InfoMask to 0x%x", listen->InfoMask);
|
||||
listenDebug(listen, CAPI_DBG_LISTEN_INFO, "set CIP to 0x%x,0x%x", listen->CIPmask,
|
||||
listen->CIPmask2);
|
||||
app->InfoMask = cmsg->InfoMask;
|
||||
app->CIPmask = cmsg->CIPmask;
|
||||
app->CIPmask2 = cmsg->CIPmask2;
|
||||
listenDebug(app, CAPI_DBG_LISTEN_INFO, "set InfoMask to 0x%x", app->InfoMask);
|
||||
listenDebug(app, CAPI_DBG_LISTEN_INFO, "set CIP to 0x%x,0x%x", app->CIPmask,
|
||||
app->CIPmask2);
|
||||
|
||||
capi_cmsg_answer(cmsg);
|
||||
cmsg->Info = CAPI_NOERROR;
|
||||
|
||||
FsmEvent(&listen->listen_m, EV_LISTEN_CONF, cmsg);
|
||||
contrRecvCmsg(listen->contr, cmsg);
|
||||
if (FsmEvent(&app->listen_m, EV_LISTEN_CONF, cmsg))
|
||||
cmsg_free(cmsg);
|
||||
}
|
||||
|
||||
static void listen_req_l_0(struct FsmInst *fi, int event, void *arg)
|
||||
static void
|
||||
listen_req_l_0(struct FsmInst *fi, int event, void *arg)
|
||||
{
|
||||
listen_req_l_x(fi, event, arg, ST_LISTEN_L_0_1);
|
||||
}
|
||||
|
||||
static void listen_req_l_1(struct FsmInst *fi, int event, void *arg)
|
||||
static void
|
||||
listen_req_l_1(struct FsmInst *fi, int event, void *arg)
|
||||
{
|
||||
listen_req_l_x(fi, event, arg, ST_LISTEN_L_1_1);
|
||||
}
|
||||
|
||||
static void listen_conf_l_x_1(struct FsmInst *fi, int event, void *arg,
|
||||
int state)
|
||||
static void
|
||||
listen_conf_l_x_1(struct FsmInst *fi, int event, void *arg, int state)
|
||||
{
|
||||
Listen_t *listen = fi->userdata;
|
||||
_cmsg *cmsg = arg;
|
||||
Application_t *app = fi->userdata;
|
||||
_cmsg *cmsg = arg;
|
||||
|
||||
if (cmsg->Info != CAPI_NOERROR) {
|
||||
FsmChangeState(fi, state);
|
||||
} else { // Info == 0
|
||||
if (listen->CIPmask == 0)
|
||||
if (app->CIPmask == 0) {
|
||||
test_and_clear_bit(APPL_STATE_LISTEN, &app->state);
|
||||
FsmChangeState(fi, ST_LISTEN_L_0);
|
||||
else
|
||||
} else {
|
||||
test_and_set_bit(APPL_STATE_LISTEN, &app->state);
|
||||
FsmChangeState(fi, ST_LISTEN_L_1);
|
||||
}
|
||||
}
|
||||
SendCmsg2Application(app, cmsg);
|
||||
}
|
||||
|
||||
static void listen_conf_l_0_1(struct FsmInst *fi, int event, void *arg)
|
||||
static void
|
||||
listen_conf_l_0_1(struct FsmInst *fi, int event, void *arg)
|
||||
{
|
||||
listen_conf_l_x_1(fi, event, arg, ST_LISTEN_L_0);
|
||||
}
|
||||
|
||||
static void listen_conf_l_1_1(struct FsmInst *fi, int event, void *arg)
|
||||
static void
|
||||
listen_conf_l_1_1(struct FsmInst *fi, int event, void *arg)
|
||||
{
|
||||
listen_conf_l_x_1(fi, event, arg, ST_LISTEN_L_1);
|
||||
}
|
||||
|
@ -131,53 +141,56 @@ const int FN_LISTEN_COUNT = sizeof(fn_listen_list)/sizeof(struct FsmNode);
|
|||
// ----------------------------------------------------------------------
|
||||
// Methods
|
||||
|
||||
|
||||
void listenConstr(Listen_t *listen, Contr_t *contr, __u16 ApplId)
|
||||
void listenConstr(Application_t *app)
|
||||
{
|
||||
listen->listen_m.fsm = &listen_fsm;
|
||||
listen->listen_m.state = ST_LISTEN_L_0;
|
||||
listen->listen_m.debug = contr->debug & CAPI_DBG_LISTEN_STATE;
|
||||
listen->listen_m.userdata = listen;
|
||||
listen->listen_m.printdebug = listen_debug;
|
||||
|
||||
listen->contr = contr;
|
||||
listen->ApplId = ApplId;
|
||||
listen->InfoMask = 0;
|
||||
listen->CIPmask = 0;
|
||||
listen->CIPmask2 = 0;
|
||||
app->listen_m.fsm = &listen_fsm;
|
||||
app->listen_m.state = ST_LISTEN_L_0;
|
||||
app->listen_m.debug = app->contr->debug & CAPI_DBG_LISTEN_STATE;
|
||||
app->listen_m.userdata = app;
|
||||
app->listen_m.printdebug = listen_debug;
|
||||
app->InfoMask = 0;
|
||||
app->CIPmask = 0;
|
||||
app->CIPmask2 = 0;
|
||||
}
|
||||
|
||||
void listenDestr(Listen_t *listen)
|
||||
void listenDestr(Application_t *app)
|
||||
{
|
||||
listenDebug(listen, CAPI_DBG_LISTEN, "%s", __FUNCTION__);
|
||||
test_and_clear_bit(APPL_STATE_LISTEN, &app->state);
|
||||
listenDebug(app, CAPI_DBG_LISTEN, "%s", __FUNCTION__);
|
||||
}
|
||||
|
||||
void listenSendMessage(Listen_t *listen, struct sk_buff *skb)
|
||||
void
|
||||
listenSendMessage(Application_t *app, struct sk_buff *skb)
|
||||
{
|
||||
_cmsg cmsg;
|
||||
capi_message2cmsg(&cmsg, skb->data);
|
||||
|
||||
switch (CMSGCMD(&cmsg)) {
|
||||
case CAPI_LISTEN_REQ:
|
||||
FsmEvent(&listen->listen_m, EV_LISTEN_REQ, &cmsg);
|
||||
break;
|
||||
default:
|
||||
int_error();
|
||||
}
|
||||
dev_kfree_skb(skb);
|
||||
_cmsg *cmsg;
|
||||
|
||||
cmsg = cmsg_alloc();
|
||||
if (!cmsg) {
|
||||
int_error();
|
||||
dev_kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
capi_message2cmsg(cmsg, skb->data);
|
||||
switch (CMSGCMD(cmsg)) {
|
||||
case CAPI_LISTEN_REQ:
|
||||
if (FsmEvent(&app->listen_m, EV_LISTEN_REQ, cmsg))
|
||||
cmsg_free(cmsg);
|
||||
break;
|
||||
default:
|
||||
int_error();
|
||||
cmsg_free(cmsg);
|
||||
}
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
int listenHandle(Listen_t *listen, __u16 CIPValue)
|
||||
int listenHandle(Application_t *app, __u16 CIPValue)
|
||||
{
|
||||
if ((listen->CIPmask & 1) ||
|
||||
(listen -> CIPmask & (1 << CIPValue)))
|
||||
if ((app->CIPmask & 1) ||
|
||||
(app->CIPmask & (1 << CIPValue)))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
//
|
||||
|
||||
void init_listen(void)
|
||||
{
|
||||
listen_fsm.state_count = ST_LISTEN_COUNT;
|
||||
|
|
|
@ -0,0 +1,619 @@
|
|||
/* $Id$
|
||||
*
|
||||
* Rewritten CAPI Layer (Layer4 in mISDN)
|
||||
*
|
||||
* The CAPI layer knows following basic Objects
|
||||
*
|
||||
* - Controller_t : the contoller instance
|
||||
* - Application_t : applications object
|
||||
* - Plci_t : PLCI object
|
||||
* - AppPlci_t : per application PLCI object
|
||||
* - Ncci_t : NCCI object
|
||||
*
|
||||
* For Supplementary Services
|
||||
* - SSProcess_t : a process handling a service request
|
||||
*
|
||||
* The controller is a Layer4 (D-channel) stack instance of
|
||||
* mISDN.
|
||||
*
|
||||
* Applications are owned by the controller and only
|
||||
* handle this controller, multiplexing multiple
|
||||
* controller with one application is done in the higher
|
||||
* driver independ CAPI driver. The application contain
|
||||
* the Listen state machine.
|
||||
*
|
||||
* Plcis are owned by the controller and are static (allocated
|
||||
* together with the controller). They maybe in use or inactiv.
|
||||
* Currently 8 PLCIs are available on a BRI (2 B-channel) controller
|
||||
* and 40 on a PRI (30 B-channel). They have a list of the associated
|
||||
* application PLCIs.
|
||||
*
|
||||
* AppPlcis are owned by the application and are
|
||||
* instance of the PLCI per application. They contain the
|
||||
* CAPI2.0 PCLI state machine
|
||||
*
|
||||
* Nccis are owned by the application Plcis. In the first version
|
||||
* this driver supports only one NCCI per PLCI.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __mISDN_CAPI_H__
|
||||
#define __mISDN_CAPI_H__
|
||||
|
||||
#include <linux/mISDNif.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/capi.h>
|
||||
#include <linux/kernelcapi.h>
|
||||
#ifdef OLDCAPI_DRIVER_INTERFACE
|
||||
#include "../avmb1/capiutil.h"
|
||||
#include "../avmb1/capicmd.h"
|
||||
#include "../avmb1/capilli.h"
|
||||
#else
|
||||
#include <linux/list.h>
|
||||
#include <linux/isdn/capiutil.h>
|
||||
#include <linux/isdn/capicmd.h>
|
||||
#include <linux/isdn/capilli.h>
|
||||
#endif
|
||||
#include "asn1.h"
|
||||
#include "fsm.h"
|
||||
#ifdef MISDN_MEMDEBUG
|
||||
#include "memdbg.h"
|
||||
#define MISDN_KMEM_DEBUG 1
|
||||
#endif
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// common stuff
|
||||
// debuging levels and functions
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#define CAPI_DBG_WARN 0x00000001
|
||||
#define CAPI_DBG_INFO 0x00000004
|
||||
#define CAPI_DBG_APPL 0x00000010
|
||||
#define CAPI_DBG_APPL_INFO 0x00000040
|
||||
#define CAPI_DBG_APPL_MSG 0x00000080
|
||||
#define CAPI_DBG_LISTEN 0x00000100
|
||||
#define CAPI_DBG_LISTEN_STATE 0x00000200
|
||||
#define CAPI_DBG_LISTEN_INFO 0x00000400
|
||||
#define CAPI_DBG_CONTR 0x00010000
|
||||
#define CAPI_DBG_CONTR_INFO 0x00040000
|
||||
#define CAPI_DBG_CONTR_MSG 0x00080000
|
||||
#define CAPI_DBG_PLCI 0x00100000
|
||||
#define CAPI_DBG_PLCI_STATE 0x00200000
|
||||
#define CAPI_DBG_PLCI_INFO 0x00400000
|
||||
#define CAPI_DBG_PLCI_L3 0x00800000
|
||||
#define CAPI_DBG_NCCI 0x01000000
|
||||
#define CAPI_DBG_NCCI_STATE 0x02000000
|
||||
#define CAPI_DBG_NCCI_INFO 0x04000000
|
||||
#define CAPI_DBG_NCCI_L3 0x08000000
|
||||
void capidebug(int, char *, ...);
|
||||
|
||||
#ifdef OLDCAPI_DRIVER_INTERFACE
|
||||
extern struct capi_driver_interface *cdrv_if;
|
||||
extern struct capi_driver mISDN_driver;
|
||||
#endif
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Init/Exit functions
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void init_listen(void);
|
||||
void init_AppPlci(void);
|
||||
void init_ncci(void);
|
||||
void free_Application(void);
|
||||
void free_listen(void);
|
||||
void free_AppPlci(void);
|
||||
void free_ncci(void);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// More CAPI defines
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/* we implement 64 bit extentions */
|
||||
#define CAPI_B3_DATA_IND_HEADER_SIZE 30
|
||||
#define CAPI_MSG_DEFAULT_LEN 256
|
||||
|
||||
#define CAPIMSG_REQ_DATAHANDLE(m) (m[18] | (m[19]<<8))
|
||||
#define CAPIMSG_RESP_DATAHANDLE(m) (m[12] | (m[13]<<8))
|
||||
|
||||
#define CMSGCMD(cmsg) CAPICMD((cmsg)->Command, (cmsg)->Subcommand)
|
||||
|
||||
#define CAPI_MAXPLCI_BRI 8
|
||||
#define CAPI_MAXPLCI_PRI 40
|
||||
|
||||
__u16 q931CIPValue(Q931_info_t *);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Basic CAPI types
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
typedef struct _Controller Controller_t;
|
||||
typedef struct _Application Application_t;
|
||||
typedef struct _Ncci Ncci_t;
|
||||
typedef struct _Plci Plci_t;
|
||||
typedef struct _AppPlci AppPlci_t;
|
||||
typedef struct _SSProcess SSProcess_t;
|
||||
|
||||
// some helper types
|
||||
typedef struct _ConfQueue ConfQueue_t;
|
||||
typedef struct _BInst BInst_t;
|
||||
|
||||
// Facility types
|
||||
typedef struct FacReqParm FacReqParm_t;
|
||||
typedef struct FacConfParm FacConfParm_t;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Helper structs
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
struct _BInst {
|
||||
struct _BInst *prev;
|
||||
struct _BInst *next;
|
||||
mISDNstack_t *bst;
|
||||
mISDNinstance_t inst;
|
||||
};
|
||||
|
||||
struct _ConfQueue {
|
||||
struct sk_buff *skb;
|
||||
__u16 DataHandle;
|
||||
__u16 MsgId;
|
||||
};
|
||||
|
||||
struct Bprotocol {
|
||||
__u16 B1;
|
||||
__u16 B2;
|
||||
__u16 B3;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// struct Controller
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
struct _Controller {
|
||||
struct _Controller *prev;
|
||||
struct _Controller *next;
|
||||
mISDNinstance_t inst;
|
||||
int nr_bc;
|
||||
BInst_t *binst;
|
||||
struct capi_ctr *ctrl;
|
||||
__u32 addr;
|
||||
int entity;
|
||||
u_int debug;
|
||||
int maxplci;
|
||||
Plci_t *plcis;
|
||||
struct list_head Applications;
|
||||
struct list_head SSProcesse;
|
||||
spinlock_t list_lock;
|
||||
__u32 NotificationMask;
|
||||
__u16 LastInvokeId;
|
||||
char infobuf[128];
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// struct Application
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
struct _Application {
|
||||
struct list_head head;
|
||||
Controller_t *contr;
|
||||
__u16 ApplId;
|
||||
__u16 MsgId;
|
||||
__u32 InfoMask;
|
||||
__u32 CIPmask;
|
||||
__u32 CIPmask2;
|
||||
__u32 NotificationMask;
|
||||
__u32 state;
|
||||
struct FsmInst listen_m;
|
||||
int maxplci;
|
||||
AppPlci_t **AppPlcis;
|
||||
capi_register_params reg_params;
|
||||
};
|
||||
|
||||
#define APPL_STATE_ACTIV 1
|
||||
#define APPL_STATE_RELEASE 2
|
||||
#define APPL_STATE_LISTEN 3
|
||||
#define APPL_STATE_DESTRUCTOR 4
|
||||
#define APPL_STATE_D2TRACE 8
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// struct Plci
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
struct _Plci {
|
||||
Controller_t *contr;
|
||||
__u32 addr;
|
||||
__u32 l3id;
|
||||
__u32 state;
|
||||
int nAppl;
|
||||
struct list_head AppPlcis;
|
||||
};
|
||||
|
||||
#define PLCI_STATE_ACTIV 1
|
||||
#define PLCI_STATE_ALERTING 2
|
||||
#define PLCI_STATE_OUTGOING 3
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// struct AppPlci
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
struct _AppPlci {
|
||||
struct list_head head;
|
||||
__u32 addr;
|
||||
Plci_t *plci;
|
||||
Application_t *appl;
|
||||
Ncci_t *ncci;
|
||||
Controller_t *contr;
|
||||
struct FsmInst plci_m;
|
||||
u_char cause[4];
|
||||
int channel;
|
||||
struct Bprotocol Bprotocol;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// struct Ncci
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
struct _Ncci {
|
||||
__u32 addr;
|
||||
BInst_t *binst;
|
||||
Controller_t *contr;
|
||||
AppPlci_t *AppPlci;
|
||||
Application_t *appl;
|
||||
struct FsmInst ncci_m;
|
||||
int window;
|
||||
__u32 state;
|
||||
ConfQueue_t xmit_skb_handles[CAPI_MAXDATAWINDOW];
|
||||
struct sk_buff *recv_skb_handles[CAPI_MAXDATAWINDOW];
|
||||
struct sk_buff_head squeue;
|
||||
};
|
||||
|
||||
#define NCCI_STATE_FCTRL 1
|
||||
#define NCCI_STATE_BUSY 2
|
||||
#define NCCI_STATE_APPLRELEASED 3
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// struct SSProcess_t
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
struct _SSProcess {
|
||||
struct list_head head;
|
||||
__u16 invokeId;
|
||||
__u16 Function;
|
||||
__u32 Handle;
|
||||
__u32 addr;
|
||||
__u16 ApplId;
|
||||
Controller_t *contr;
|
||||
struct timer_list tl;
|
||||
__u8 buf[128];
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// FUNCTION prototypes
|
||||
//
|
||||
// Controller prototypes
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
int ControllerConstr(Controller_t **, mISDNstack_t *, mISDN_pid_t *, mISDNobject_t *);
|
||||
void ControllerDestr(Controller_t *);
|
||||
void ControllerRun(Controller_t *);
|
||||
void ControllerDebug(Controller_t *, __u32, char *, ...);
|
||||
int ControllerNewPlci(Controller_t *, Plci_t **, u_int);
|
||||
int ControllerReleasePlci(Plci_t *);
|
||||
Application_t *getApplication4Id(Controller_t *, __u16);
|
||||
Plci_t *getPlci4Addr(Controller_t *, __u32);
|
||||
int ControllerL4L3(Controller_t *, u_int, int, struct sk_buff *);
|
||||
int ControllerL3L4(mISDNif_t *, struct sk_buff *);
|
||||
BInst_t *ControllerSelChannel(Controller_t *, u_int);
|
||||
void ControllerAddSSProcess(Controller_t *, SSProcess_t *);
|
||||
SSProcess_t *getSSProcess4Id(Controller_t *, __u16);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Application prototypes
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
int ApplicationConstr(Controller_t *, __u16, capi_register_params *);
|
||||
int ApplicationDestr(Application_t *, int);
|
||||
void ApplicationDebug(Application_t *appl, __u32 level, char *fmt, ...);
|
||||
void ApplicationSendMessage(Application_t *appl, struct sk_buff *skb);
|
||||
void SendCmsg2Application(Application_t *, _cmsg *);
|
||||
void SendCmsgAnswer2Application(Application_t *, _cmsg *, __u16);
|
||||
void AnswerMessage2Application(Application_t *, struct sk_buff *, __u16);
|
||||
void applManufacturerReq(Application_t *appl, struct sk_buff *skb);
|
||||
void applD2Trace(Application_t *appl, u_char *buf, int len);
|
||||
AppPlci_t *ApplicationNewAppPlci(Application_t *, Plci_t *);
|
||||
AppPlci_t *getAppPlci4addr(Application_t *, __u32);
|
||||
void ApplicationDelAppPlci(Application_t *, AppPlci_t *);
|
||||
|
||||
void listenConstr(Application_t *);
|
||||
void listenDestr(Application_t *);
|
||||
void listenSendMessage(Application_t *, struct sk_buff *);
|
||||
int listenHandle(Application_t *, __u16);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// PLCI prototypes
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void plciInit(Controller_t *);
|
||||
void plciDebug(Plci_t *, __u32, char *, ...);
|
||||
int plci_l3l4(Plci_t *, int, struct sk_buff *);
|
||||
void plciAttachAppPlci(Plci_t *, AppPlci_t *);
|
||||
void plciDetachAppPlci(Plci_t *, AppPlci_t *);
|
||||
void plciNewCrInd(Plci_t *, void *);
|
||||
void plciNewCrReq(Plci_t *);
|
||||
int plciL4L3(Plci_t *, __u32, struct sk_buff *);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// AppPLCI prototypes
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
int AppPlciConstr(AppPlci_t **, Application_t *, Plci_t *);
|
||||
void AppPlciDestr(AppPlci_t *);
|
||||
void AppPlciDelNCCI(AppPlci_t *);
|
||||
void AppPlci_l3l4(AppPlci_t *, int, void *);
|
||||
void AppPlciSendMessage(AppPlci_t *, struct sk_buff *);
|
||||
void AppPlciRelease(AppPlci_t *);
|
||||
int AppPlciFacSuspendReq(AppPlci_t *, FacReqParm_t *, FacConfParm_t *);
|
||||
int AppPlciFacResumeReq(AppPlci_t *, FacReqParm_t *, FacConfParm_t *);
|
||||
void AppPlciGetCmsg(AppPlci_t *, _cmsg *);
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// NCCI prototypes
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Ncci_t *ncciConstr(AppPlci_t *);
|
||||
void ncciDestr(Ncci_t *);
|
||||
void ncciLinkUp(Ncci_t *);
|
||||
void ncciLinkDown(Ncci_t *);
|
||||
void ncciApplRelease(Ncci_t *);
|
||||
void ncciDelAppPlci(Ncci_t *);
|
||||
void ncciSendMessage(Ncci_t *, struct sk_buff *);
|
||||
int ncci_l3l4(mISDNif_t *, struct sk_buff *);
|
||||
__u16 ncciSelectBprotocol(Ncci_t *);
|
||||
void ncciGetCmsg(Ncci_t *, _cmsg *);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SSProcess prototypes
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
SSProcess_t *SSProcessConstr(Application_t *, __u16, __u32);
|
||||
void SSProcessDestr(SSProcess_t *);
|
||||
int Supplementary_l3l4(Controller_t *, __u32, struct sk_buff *);
|
||||
void SupplementaryFacilityReq(Application_t *, _cmsg *);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// INFOMASK defines (LISTEN commands)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#define CAPI_INFOMASK_CAUSE (0x0001)
|
||||
#define CAPI_INFOMASK_DATETIME (0x0002)
|
||||
#define CAPI_INFOMASK_DISPLAY (0x0004)
|
||||
#define CAPI_INFOMASK_USERUSER (0x0008)
|
||||
#define CAPI_INFOMASK_PROGRESS (0x0010)
|
||||
#define CAPI_INFOMASK_FACILITY (0x0020)
|
||||
//#define CAPI_INFOMASK_CHARGE (0x0040)
|
||||
//#define CAPI_INFOMASK_CALLEDPN (0x0080)
|
||||
#define CAPI_INFOMASK_CHANNELID (0x0100)
|
||||
#define CAPI_INFOMASK_EARLYB3 (0x0200)
|
||||
//#define CAPI_INFOMASK_REDIRECT (0x0400)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Supplementary Services
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#define SuppServiceTP 0x00000002
|
||||
#define SuppServiceCF 0x00000010
|
||||
#define mISDNSupportedServices (SuppServiceCF | SuppServiceTP)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// structs for Facillity requests
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
struct FacReqListen {
|
||||
__u32 NotificationMask;
|
||||
};
|
||||
|
||||
struct FacReqSuspend {
|
||||
__u8 *CallIdentity;
|
||||
};
|
||||
|
||||
struct FacReqResume {
|
||||
__u8 *CallIdentity;
|
||||
};
|
||||
|
||||
struct FacReqCFActivate {
|
||||
__u32 Handle;
|
||||
__u16 Procedure;
|
||||
__u16 BasicService;
|
||||
__u8 *ServedUserNumber;
|
||||
__u8 *ForwardedToNumber;
|
||||
__u8 *ForwardedToSubaddress;
|
||||
};
|
||||
|
||||
struct FacReqCFDeactivate {
|
||||
__u32 Handle;
|
||||
__u16 Procedure;
|
||||
__u16 BasicService;
|
||||
__u8 *ServedUserNumber;
|
||||
};
|
||||
|
||||
#define FacReqCFInterrogateParameters FacReqCFDeactivate
|
||||
|
||||
struct FacReqCFInterrogateNumbers {
|
||||
__u32 Handle;
|
||||
};
|
||||
|
||||
struct FacReqParm {
|
||||
__u16 Function;
|
||||
union {
|
||||
struct FacReqListen Listen;
|
||||
struct FacReqSuspend Suspend;
|
||||
struct FacReqResume Resume;
|
||||
struct FacReqCFActivate CFActivate;
|
||||
struct FacReqCFDeactivate CFDeactivate;
|
||||
struct FacReqCFInterrogateParameters CFInterrogateParameters;
|
||||
struct FacReqCFInterrogateNumbers CFInterrogateNumbers;
|
||||
} u;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// structs for Facillity confirms
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
struct FacConfGetSupportedServices {
|
||||
__u16 SupplementaryServiceInfo;
|
||||
__u32 SupportedServices;
|
||||
};
|
||||
|
||||
struct FacConfInfo {
|
||||
__u16 SupplementaryServiceInfo;
|
||||
};
|
||||
|
||||
struct FacConfParm {
|
||||
__u16 Function;
|
||||
union {
|
||||
struct FacConfGetSupportedServices GetSupportedServices;
|
||||
struct FacConfInfo Info;
|
||||
} u;
|
||||
};
|
||||
|
||||
int capiEncodeWord(__u8 *dest, __u16 i);
|
||||
int capiEncodeDWord(__u8 *dest, __u32 i);
|
||||
int capiEncodeFacIndCFact(__u8 *dest, __u16 SupplementaryServiceReason, __u32 Handle);
|
||||
int capiEncodeFacIndCFdeact(__u8 *dest, __u16 SupplementaryServiceReason, __u32 Handle);
|
||||
int capiEncodeFacIndCFNotAct(__u8 *dest, struct ActDivNotification *actNot);
|
||||
int capiEncodeFacIndCFNotDeact(__u8 *dest, struct DeactDivNotification *deactNot);
|
||||
int capiEncodeFacIndCFinterParameters(__u8 *dest, __u16 SupplementaryServiceReason, __u32 Handle,
|
||||
struct IntResultList *intResultList);
|
||||
int capiEncodeFacIndCFinterNumbers(__u8 *dest, __u16 SupplementaryServiceReason, __u32 Handle,
|
||||
struct ServedUserNumberList *list);
|
||||
int capiEncodeFacConfParm(__u8 *dest, struct FacConfParm *facConfParm);
|
||||
|
||||
int capiEncodeFacIndSuspend(__u8 *dest, __u16 SupplementaryServiceReason);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// mISDN kmem cache managment functions
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/* kmem caches */
|
||||
extern kmem_cache_t *mISDN_cmsg_cp;
|
||||
extern kmem_cache_t *mISDN_AppPlci_cp;
|
||||
extern kmem_cache_t *mISDN_ncci_cp;
|
||||
extern kmem_cache_t *mISDN_sspc_cp;
|
||||
|
||||
#ifdef MISDN_KMEM_DEBUG
|
||||
typedef struct _kd_cmsg _kd_cmsg_t;
|
||||
typedef struct _kd_Ncci _kd_Ncci_t;
|
||||
typedef struct _kd_AppPlci _kd_AppPlci_t;
|
||||
typedef struct _kd_SSProcess _kd_SSProcess_t;
|
||||
typedef struct _kd_all _kd_all_t;
|
||||
|
||||
typedef struct __km_dbg_item {
|
||||
struct list_head head;
|
||||
long typ;
|
||||
char *file;
|
||||
u_int line;
|
||||
} km_dbg_item_t;
|
||||
|
||||
struct _kd_cmsg {
|
||||
km_dbg_item_t kdi;
|
||||
_cmsg cm;
|
||||
};
|
||||
|
||||
struct _kd_AppPlci {
|
||||
km_dbg_item_t kdi;
|
||||
AppPlci_t ap;
|
||||
};
|
||||
|
||||
struct _kd_Ncci {
|
||||
km_dbg_item_t kdi;
|
||||
Ncci_t ni;
|
||||
};
|
||||
|
||||
struct _kd_SSProcess {
|
||||
km_dbg_item_t kdi;
|
||||
SSProcess_t sp;
|
||||
};
|
||||
|
||||
struct _kd_all {
|
||||
km_dbg_item_t kdi;
|
||||
union {
|
||||
_cmsg cm;
|
||||
AppPlci_t ap;
|
||||
Ncci_t ni;
|
||||
SSProcess_t sp;
|
||||
} a;
|
||||
};
|
||||
|
||||
#define KDB_GET_KDI(kd) ((km_dbg_item_t *)(((u_char *)kd) - sizeof(km_dbg_item_t)))
|
||||
#define KDB_GET_KDALL(kd) ((_kd_all_t *)(((u_char *)kd) - sizeof(km_dbg_item_t)))
|
||||
|
||||
#define KM_DBG_TYP_CM 1
|
||||
#define KM_DBG_TYP_AP 2
|
||||
#define KM_DBG_TYP_NI 3
|
||||
#define KM_DBG_TYP_SP 4
|
||||
|
||||
#define cmsg_alloc() _kd_cmsg_alloc(__FILE__, __LINE__)
|
||||
extern _cmsg *_kd_cmsg_alloc(char *, int);
|
||||
extern void cmsg_free(_cmsg *cm);
|
||||
|
||||
#define AppPlci_alloc() _kd_AppPlci_alloc(__FILE__, __LINE__)
|
||||
extern AppPlci_t *_kd_AppPlci_alloc(char *, int);
|
||||
extern void AppPlci_free(AppPlci_t *ap);
|
||||
|
||||
#define ncci_alloc() _kd_ncci_alloc(__FILE__, __LINE__)
|
||||
extern Ncci_t *_kd_ncci_alloc(char *, int);
|
||||
extern void ncci_free(Ncci_t *ni);
|
||||
|
||||
#define SSProcess_alloc() _kd_SSProcess_alloc(__FILE__, __LINE__)
|
||||
extern SSProcess_t *_kd_SSProcess_alloc(char *, int);
|
||||
extern void SSProcess_free(SSProcess_t *sp);
|
||||
|
||||
#else /* ! MISDN_KMEM_DEBUG */
|
||||
|
||||
static __inline__ _cmsg *cmsg_alloc(void)
|
||||
{
|
||||
return(kmem_cache_alloc(mISDN_cmsg_cp, GFP_ATOMIC));
|
||||
}
|
||||
|
||||
static __inline__ void cmsg_free(_cmsg *cm)
|
||||
{
|
||||
kmem_cache_free(mISDN_cmsg_cp, cm);
|
||||
}
|
||||
|
||||
static __inline__ AppPlci_t *AppPlci_alloc(void)
|
||||
{
|
||||
return(kmem_cache_alloc(mISDN_AppPlci_cp, GFP_ATOMIC));
|
||||
}
|
||||
|
||||
static __inline__ void AppPlci_free(AppPlci_t *ap)
|
||||
{
|
||||
kmem_cache_free(mISDN_AppPlci_cp, ap);
|
||||
}
|
||||
|
||||
static __inline__ Ncci_t *ncci_alloc(void)
|
||||
{
|
||||
return(kmem_cache_alloc(mISDN_ncci_cp, GFP_ATOMIC));
|
||||
}
|
||||
|
||||
static __inline__ void ncci_free(Ncci_t *ni)
|
||||
{
|
||||
kmem_cache_free(mISDN_ncci_cp, ni);
|
||||
}
|
||||
|
||||
static __inline__ SSProcess_t *SSProcess_alloc(void)
|
||||
{
|
||||
return(kmem_cache_alloc(mISDN_sspc_cp, GFP_ATOMIC));
|
||||
}
|
||||
|
||||
static __inline__ void SSProcess_free(SSProcess_t *sp)
|
||||
{
|
||||
kmem_cache_free(mISDN_sspc_cp, sp);
|
||||
}
|
||||
|
||||
#endif /* MISDN_KMEM_DEBUG */
|
||||
// cmsg_alloc with error handling for void functions
|
||||
#define CMSG_ALLOC(cm) if (!(cm = cmsg_alloc())) {int_error();return;}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "capi.h"
|
||||
#include "m_capi.h"
|
||||
#include "dss1.h"
|
||||
#include "helper.h"
|
||||
#include "debug.h"
|
||||
|
@ -11,47 +11,46 @@
|
|||
capidebug(lev, fmt, ## args)
|
||||
|
||||
|
||||
void plciConstr(Plci_t *plci, Contr_t *contr, __u32 adrPLCI, u_int id)
|
||||
void plciInit(Controller_t *contr)
|
||||
{
|
||||
memset(plci, 0, sizeof(Plci_t));
|
||||
plci->adrPLCI = adrPLCI;
|
||||
plci->id = id;
|
||||
plci->contr = contr;
|
||||
}
|
||||
Plci_t *plci = contr->plcis;
|
||||
int i;
|
||||
|
||||
void plciDestr(Plci_t *plci)
|
||||
{
|
||||
#if 0
|
||||
if (plci->l4_pc.l3pc) {
|
||||
// FIXME: we need to kill l3_process, actually
|
||||
plci->l4_pc.l3pc->l4pc = 0;
|
||||
for (i = 0; i < contr->maxplci; i++) {
|
||||
memset(plci, 0, sizeof(Plci_t));
|
||||
plci->addr = ((i + 1) << 8) | contr->addr;
|
||||
plci->l3id = MISDN_ID_NONE;
|
||||
INIT_LIST_HEAD(&plci->AppPlcis);
|
||||
plci->contr = contr;
|
||||
printk(KERN_WARNING "%s: %p PLCI(%x) l3id(%x)\n",
|
||||
__FUNCTION__, plci, plci->addr, plci->l3id);
|
||||
plci++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void plciHandleSetupInd(Plci_t *plci, int pr, Q931_info_t *qi)
|
||||
{
|
||||
int ApplId;
|
||||
__u16 CIPValue;
|
||||
Appl_t *appl;
|
||||
Cplci_t *cplci;
|
||||
__u16 CIPValue;
|
||||
Application_t *appl;
|
||||
AppPlci_t *aplci;
|
||||
struct list_head *item, *next;
|
||||
|
||||
if (!qi) {
|
||||
if (!qi || !plci->contr) {
|
||||
int_error();
|
||||
return;
|
||||
}
|
||||
for (ApplId = 1; ApplId <= CAPI_MAXAPPL; ApplId++) {
|
||||
appl = contrId2appl(plci->contr, ApplId);
|
||||
if (appl) {
|
||||
CIPValue = q931CIPValue(qi);
|
||||
if (listenHandle(&appl->listen, CIPValue)) {
|
||||
cplci = applNewCplci(appl, plci);
|
||||
if (!cplci) {
|
||||
int_error();
|
||||
break;
|
||||
}
|
||||
cplci_l3l4(cplci, pr, qi);
|
||||
CIPValue = q931CIPValue(qi);
|
||||
list_for_each_safe(item, next, &plci->contr->Applications) {
|
||||
appl = (Application_t *)item;
|
||||
if (test_bit(APPL_STATE_RELEASE, &appl->state))
|
||||
continue;
|
||||
if (listenHandle(appl, CIPValue)) {
|
||||
aplci = ApplicationNewAppPlci(appl, plci);
|
||||
if (!aplci) {
|
||||
int_error();
|
||||
break;
|
||||
}
|
||||
AppPlci_l3l4(aplci, pr, qi);
|
||||
}
|
||||
}
|
||||
if (plci->nAppl == 0) {
|
||||
|
@ -62,14 +61,15 @@ void plciHandleSetupInd(Plci_t *plci, int pr, Q931_info_t *qi)
|
|||
AddvarIE(skb,cause);
|
||||
plciL4L3(plci, CC_RELEASE_COMPLETE | REQUEST, skb);
|
||||
}
|
||||
ControllerReleasePlci(plci);
|
||||
}
|
||||
}
|
||||
|
||||
int plci_l3l4(Plci_t *plci, int pr, struct sk_buff *skb)
|
||||
{
|
||||
__u16 applId;
|
||||
Cplci_t *cplci;
|
||||
Q931_info_t *qi;
|
||||
AppPlci_t *aplci;
|
||||
Q931_info_t *qi;
|
||||
struct list_head *item, *next;
|
||||
|
||||
if (skb->len)
|
||||
qi = (Q931_info_t *)skb->data;
|
||||
|
@ -80,47 +80,51 @@ int plci_l3l4(Plci_t *plci, int pr, struct sk_buff *skb)
|
|||
plciHandleSetupInd(plci, pr, qi);
|
||||
break;
|
||||
case CC_RELEASE_CR | INDICATION:
|
||||
if (plci->nAppl == 0) {
|
||||
contrDelPlci(plci->contr, plci);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
for (applId = 1; applId <= CAPI_MAXAPPL; applId++) {
|
||||
cplci = plci->cplcis[applId - 1];
|
||||
if (cplci)
|
||||
cplci_l3l4(cplci, pr, qi);
|
||||
list_for_each_safe(item, next, &plci->AppPlcis) {
|
||||
aplci = (AppPlci_t *)item;
|
||||
AppPlci_l3l4(aplci, pr, qi);
|
||||
}
|
||||
if (plci->nAppl == 0)
|
||||
contrDelPlci(plci->contr, plci);
|
||||
break;
|
||||
}
|
||||
dev_kfree_skb(skb);
|
||||
return(0);
|
||||
}
|
||||
|
||||
void plciAttachCplci(Plci_t *plci, Cplci_t *cplci)
|
||||
{
|
||||
__u16 applId = cplci->appl->ApplId;
|
||||
AppPlci_t *
|
||||
getAppPlci4Id(Plci_t *plci, __u16 appId) {
|
||||
struct list_head *item;
|
||||
AppPlci_t *aplci;
|
||||
|
||||
if (plci->cplcis[applId - 1]) {
|
||||
list_for_each(item, &plci->AppPlcis) {
|
||||
aplci = (AppPlci_t *)item;
|
||||
if (appId == aplci->appl->ApplId)
|
||||
return(aplci);
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
void plciAttachAppPlci(Plci_t *plci, AppPlci_t *aplci)
|
||||
{
|
||||
AppPlci_t *test = getAppPlci4Id(plci, aplci->appl->ApplId);
|
||||
|
||||
if (test) {
|
||||
int_error();
|
||||
return;
|
||||
}
|
||||
plci->cplcis[applId - 1] = cplci;
|
||||
list_add(&aplci->head, &plci->AppPlcis);
|
||||
plci->nAppl++;
|
||||
}
|
||||
|
||||
void plciDetachCplci(Plci_t *plci, Cplci_t *cplci)
|
||||
void
|
||||
plciDetachAppPlci(Plci_t *plci, AppPlci_t *aplci)
|
||||
{
|
||||
__u16 applId = cplci->appl->ApplId;
|
||||
|
||||
if (plci->cplcis[applId - 1] != cplci) {
|
||||
int_error();
|
||||
return;
|
||||
}
|
||||
cplci->plci = 0;
|
||||
plci->cplcis[applId - 1] = 0;
|
||||
aplci->plci = NULL;
|
||||
list_del_init(&aplci->head);
|
||||
plci->nAppl--;
|
||||
if (!plci->nAppl)
|
||||
ControllerReleasePlci(plci);
|
||||
}
|
||||
|
||||
void plciNewCrReq(Plci_t *plci)
|
||||
|
@ -128,7 +132,8 @@ void plciNewCrReq(Plci_t *plci)
|
|||
plciL4L3(plci, CC_NEW_CR | REQUEST, NULL);
|
||||
}
|
||||
|
||||
int plciL4L3(Plci_t *plci, __u32 prim, struct sk_buff *skb)
|
||||
int
|
||||
plciL4L3(Plci_t *plci, __u32 prim, struct sk_buff *skb)
|
||||
{
|
||||
#define MY_RESERVE 8
|
||||
int err;
|
||||
|
@ -141,7 +146,7 @@ int plciL4L3(Plci_t *plci, __u32 prim, struct sk_buff *skb)
|
|||
} else
|
||||
skb_reserve(skb, MY_RESERVE);
|
||||
}
|
||||
err = contrL4L3(plci->contr, prim, plci->id, skb);
|
||||
err = ControllerL4L3(plci->contr, prim, plci->l3id, skb);
|
||||
if (err)
|
||||
dev_kfree_skb(skb);
|
||||
return(err);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "capi.h"
|
||||
#include "m_capi.h"
|
||||
#include "asn1_comp.h"
|
||||
#include "asn1_enc.h"
|
||||
#include "dss1.h"
|
||||
|
@ -12,6 +12,37 @@
|
|||
#define T_DEACTIVATE 4000
|
||||
#define T_INTERROGATE 4000
|
||||
|
||||
static void SSProcessAddTimer(SSProcess_t *, int);
|
||||
|
||||
static __u8 *
|
||||
encodeInvokeComponentHead(__u8 *p)
|
||||
{
|
||||
*p++ = 0; // length -- not known yet
|
||||
*p++ = 0x91; // remote operations protocol
|
||||
*p++ = 0xa1; // invoke component
|
||||
*p++ = 0; // length -- not known yet
|
||||
return p;
|
||||
}
|
||||
|
||||
static void
|
||||
encodeInvokeComponentLength(__u8 *msg, __u8 *p)
|
||||
{
|
||||
msg[3] = p - &msg[5];
|
||||
msg[0] = p - &msg[1];
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
SSProcess_L4L3(SSProcess_t *spc, __u32 prim, struct sk_buff *skb) {
|
||||
int err;
|
||||
|
||||
// FIXME err = ControllerL4L3(contr, prim, contr->addr | DUMMY_CR_FLAG, skb);
|
||||
err = ControllerL4L3(spc->contr, prim, MISDN_ID_DUMMY, skb);
|
||||
if (err)
|
||||
dev_kfree_skb(skb);
|
||||
return(err);
|
||||
}
|
||||
|
||||
static __inline__ int capiGetWord(__u8 *p, __u8 *end, __u16 *word)
|
||||
{
|
||||
if (p + 2 > end) {
|
||||
|
@ -139,8 +170,9 @@ static __inline__ int capiGetFacReqCFInterrogateNumbers(__u8 *p, __u8 *_end, str
|
|||
|
||||
CAPI_GET(capiGetDWord, &CFInterrogateNumbers->Handle);
|
||||
|
||||
if (p != end) return -1;
|
||||
return len + 1;
|
||||
if (p != end)
|
||||
return(-1);
|
||||
return(len + 1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -153,161 +185,48 @@ static __inline__ int capiGetFacReqParm(__u8 *p, struct FacReqParm *facReqParm)
|
|||
CAPI_GET(capiGetWord, &facReqParm->Function);
|
||||
|
||||
switch (facReqParm->Function) {
|
||||
case 0x0000: // GetSupportedServices
|
||||
if (*p++ != 0x00) return -1; // empty struct
|
||||
break;
|
||||
case 0x0001: // Listen
|
||||
CAPI_GET(capiGetFacReqListen, &facReqParm->u.Listen);
|
||||
break;
|
||||
case 0x0004: // Suspend
|
||||
CAPI_GET(capiGetFacReqSuspend, &facReqParm->u.Suspend);
|
||||
break;
|
||||
case 0x0005: // Resume
|
||||
CAPI_GET(capiGetFacReqResume, &facReqParm->u.Resume);
|
||||
break;
|
||||
case 0x0009: // CF Activate
|
||||
CAPI_GET(capiGetFacReqCFActivate, &facReqParm->u.CFActivate);
|
||||
break;
|
||||
case 0x000a: // CF Deactivate
|
||||
CAPI_GET(capiGetFacReqCFDeactivate, &facReqParm->u.CFDeactivate);
|
||||
break;
|
||||
case 0x000b: // CF Interrogate Parameters
|
||||
CAPI_GET(capiGetFacReqCFInterrogateParameters, &facReqParm->u.CFInterrogateParameters);
|
||||
break;
|
||||
case 0x000c: // CF Interrogate Numbers
|
||||
CAPI_GET(capiGetFacReqCFInterrogateNumbers, &facReqParm->u.CFInterrogateNumbers);
|
||||
break;
|
||||
default:
|
||||
return len + 1;
|
||||
case 0x0000: // GetSupportedServices
|
||||
if (*p++ != 0x00) return -1; // empty struct
|
||||
break;
|
||||
case 0x0001: // Listen
|
||||
CAPI_GET(capiGetFacReqListen, &facReqParm->u.Listen);
|
||||
break;
|
||||
case 0x0004: // Suspend
|
||||
CAPI_GET(capiGetFacReqSuspend, &facReqParm->u.Suspend);
|
||||
break;
|
||||
case 0x0005: // Resume
|
||||
CAPI_GET(capiGetFacReqResume, &facReqParm->u.Resume);
|
||||
break;
|
||||
case 0x0009: // CF Activate
|
||||
CAPI_GET(capiGetFacReqCFActivate, &facReqParm->u.CFActivate);
|
||||
break;
|
||||
case 0x000a: // CF Deactivate
|
||||
CAPI_GET(capiGetFacReqCFDeactivate, &facReqParm->u.CFDeactivate);
|
||||
break;
|
||||
case 0x000b: // CF Interrogate Parameters
|
||||
CAPI_GET(capiGetFacReqCFInterrogateParameters, &facReqParm->u.CFInterrogateParameters);
|
||||
break;
|
||||
case 0x000c: // CF Interrogate Numbers
|
||||
CAPI_GET(capiGetFacReqCFInterrogateNumbers, &facReqParm->u.CFInterrogateNumbers);
|
||||
break;
|
||||
default:
|
||||
return(len + 1);
|
||||
}
|
||||
|
||||
if (p != end) return -1;
|
||||
return len + 1;
|
||||
if (p != end)
|
||||
return(-1);
|
||||
return(len + 1);
|
||||
}
|
||||
|
||||
void applSuppFacilityReq(Appl_t *appl, _cmsg *cmsg)
|
||||
{
|
||||
__u8 tmp[10];
|
||||
__u16 Info;
|
||||
struct FacReqParm facReqParm;
|
||||
struct FacConfParm facConfParm;
|
||||
Plci_t *plci;
|
||||
Cplci_t *cplci;
|
||||
|
||||
if (capiGetFacReqParm(cmsg->FacilityRequestParameter, &facReqParm) < 0) {
|
||||
contrAnswerCmsg(appl->contr, cmsg, CapiIllMessageParmCoding);
|
||||
return;
|
||||
}
|
||||
facConfParm.Function = facReqParm.Function;
|
||||
switch (facReqParm.Function) {
|
||||
case 0x0000: // GetSupportedServices
|
||||
Info = applGetSupportedServices(appl, &facReqParm, &facConfParm);
|
||||
break;
|
||||
case 0x0001: // Listen
|
||||
Info = applFacListen(appl, &facReqParm, &facConfParm);
|
||||
break;
|
||||
case 0x0004: // Suspend
|
||||
cplci = applAdr2cplci(appl, cmsg->adr.adrPLCI);
|
||||
if (!cplci) {
|
||||
Info = CapiIllContrPlciNcci;
|
||||
break;
|
||||
}
|
||||
Info = cplciFacSuspendReq(cplci, &facReqParm, &facConfParm);
|
||||
break;
|
||||
case 0x0005: // Resume
|
||||
plci = contrNewPlci(appl->contr, MISDN_ID_ANY);
|
||||
if (!plci) {
|
||||
Info = CapiNoPlciAvailable;
|
||||
break;
|
||||
}
|
||||
cplci = applNewCplci(appl, plci);
|
||||
if (!cplci) {
|
||||
contrDelPlci(appl->contr, plci);
|
||||
Info = CapiNoPlciAvailable;
|
||||
break;
|
||||
}
|
||||
Info = cplciFacResumeReq(cplci, &facReqParm, &facConfParm);
|
||||
if (Info == CapiSuccess)
|
||||
cmsg->adr.adrPLCI = plci->adrPLCI;
|
||||
break;
|
||||
case 0x0009: // CF Activate
|
||||
Info = applFacCFActivate(appl, &facReqParm, &facConfParm);
|
||||
break;
|
||||
case 0x000a: // CF Deactivate
|
||||
Info = applFacCFDeactivate(appl, &facReqParm, &facConfParm);
|
||||
break;
|
||||
case 0x000b: // CF Interrogate Parameters
|
||||
Info = applFacCFInterrogateParameters(appl, &facReqParm, &facConfParm);
|
||||
break;
|
||||
case 0x000c: // CF Interrogate Numbers
|
||||
Info = applFacCFInterrogateNumbers(appl, &facReqParm, &facConfParm);
|
||||
break;
|
||||
default:
|
||||
Info = CapiSuccess;
|
||||
facConfParm.u.Info.SupplementaryServiceInfo = CapiSupplementaryServiceNotSupported;
|
||||
}
|
||||
|
||||
capi_cmsg_answer(cmsg);
|
||||
cmsg->Info = Info;
|
||||
if (Info == 0x0000)
|
||||
capiEncodeFacConfParm(tmp, &facConfParm);
|
||||
else
|
||||
tmp[0] = 0;
|
||||
cmsg->FacilityConfirmationParameter = tmp;
|
||||
contrRecvCmsg(appl->contr, cmsg);
|
||||
}
|
||||
|
||||
__u8 *encodeInvokeComponentHead(__u8 *p)
|
||||
{
|
||||
*p++ = 0; // length -- not known yet
|
||||
*p++ = 0x91; // remote operations protocol
|
||||
*p++ = 0xa1; // invoke component
|
||||
*p++ = 0; // length -- not known yet
|
||||
return p;
|
||||
}
|
||||
|
||||
void encodeInvokeComponentLength(__u8 *msg, __u8 *p)
|
||||
{
|
||||
msg[3] = p - &msg[5];
|
||||
msg[0] = p - &msg[1];
|
||||
}
|
||||
|
||||
|
||||
static int dummy_L4L3(DummyProcess_t *dpc, __u32 prim, struct sk_buff *skb) {
|
||||
Contr_t *contr = dpc->contr;
|
||||
int err;
|
||||
|
||||
// err = contrL4L3(contr, prim, contr->adrController | DUMMY_CR_FLAG, skb);
|
||||
err = contrL4L3(contr, prim, MISDN_ID_DUMMY, skb);
|
||||
if (err)
|
||||
dev_kfree_skb(skb);
|
||||
return(err);
|
||||
}
|
||||
|
||||
DummyProcess_t *applNewDummyPc(Appl_t *appl, __u16 Function, __u32 Handle)
|
||||
{
|
||||
DummyProcess_t *dummy_pc;
|
||||
|
||||
dummy_pc = contrNewDummyPc(appl->contr);
|
||||
if (!dummy_pc)
|
||||
return 0;
|
||||
|
||||
dummy_pc->ApplId = appl->ApplId;
|
||||
dummy_pc->Function = Function;
|
||||
dummy_pc->Handle = Handle;
|
||||
return dummy_pc;
|
||||
}
|
||||
|
||||
int applGetSupportedServices(Appl_t *appl, struct FacReqParm *facReqParm,
|
||||
struct FacConfParm *facConfParm)
|
||||
static int
|
||||
GetSupportedServices(FacReqParm_t *facReqParm, FacConfParm_t *facConfParm)
|
||||
{
|
||||
facConfParm->u.GetSupportedServices.SupplementaryServiceInfo = CapiSuccess;
|
||||
facConfParm->u.GetSupportedServices.SupportedServices = mISDNSupportedServices;
|
||||
return CapiSuccess;
|
||||
}
|
||||
|
||||
int applFacListen(Appl_t *appl, struct FacReqParm *facReqParm,
|
||||
struct FacConfParm *facConfParm)
|
||||
static int
|
||||
FacListen(Application_t *appl, FacReqParm_t *facReqParm, FacConfParm_t *facConfParm)
|
||||
{
|
||||
if (facReqParm->u.Listen.NotificationMask &~ mISDNSupportedServices) {
|
||||
facConfParm->u.Info.SupplementaryServiceInfo = CapiSupplementaryServiceNotSupported;
|
||||
|
@ -318,221 +237,272 @@ int applFacListen(Appl_t *appl, struct FacReqParm *facReqParm,
|
|||
return CapiSuccess;
|
||||
}
|
||||
|
||||
int applFacCFActivate(Appl_t *appl, struct FacReqParm *facReqParm,
|
||||
struct FacConfParm *facConfParm)
|
||||
static int
|
||||
FacCFInterrogateParameters(Application_t *appl, FacReqParm_t *facReqParm, FacConfParm_t *facConfParm)
|
||||
{
|
||||
DummyProcess_t *dummy_pc;
|
||||
SSProcess_t *sspc;
|
||||
struct sk_buff *skb = alloc_l3msg(260, MT_FACILITY);
|
||||
__u8 *p;
|
||||
|
||||
if (!skb)
|
||||
return CAPI_MSGOSRESOURCEERR;
|
||||
dummy_pc = applNewDummyPc(appl, facReqParm->Function, facReqParm->u.CFActivate.Handle);
|
||||
if (!dummy_pc) {
|
||||
kfree_skb(skb);
|
||||
return CAPI_MSGOSRESOURCEERR;
|
||||
}
|
||||
p = encodeInvokeComponentHead(dummy_pc->buf);
|
||||
p += encodeInt(p, dummy_pc->invokeId);
|
||||
p += encodeInt(p, 0x07); // activationDiversion
|
||||
p += encodeActivationDiversion(p, &facReqParm->u.CFActivate);
|
||||
encodeInvokeComponentLength(dummy_pc->buf, p);
|
||||
AddIE(skb, IE_FACILITY, dummy_pc->buf);
|
||||
dummy_L4L3(dummy_pc, CC_FACILITY | REQUEST, skb);
|
||||
dummyPcAddTimer(dummy_pc, T_ACTIVATE);
|
||||
|
||||
facConfParm->u.Info.SupplementaryServiceInfo = CapiSuccess;
|
||||
return CapiSuccess;
|
||||
}
|
||||
|
||||
int applFacCFDeactivate(Appl_t *appl, struct FacReqParm *facReqParm,
|
||||
struct FacConfParm *facConfParm)
|
||||
{
|
||||
DummyProcess_t *dummy_pc;
|
||||
struct sk_buff *skb = alloc_l3msg(260, MT_FACILITY);
|
||||
__u8 *p;
|
||||
|
||||
if (!skb)
|
||||
return CAPI_MSGOSRESOURCEERR;
|
||||
dummy_pc = applNewDummyPc(appl, facReqParm->Function, facReqParm->u.CFDeactivate.Handle);
|
||||
if (!dummy_pc) {
|
||||
kfree_skb(skb);
|
||||
return CAPI_MSGOSRESOURCEERR;
|
||||
}
|
||||
p = encodeInvokeComponentHead(dummy_pc->buf);
|
||||
p += encodeInt(p, dummy_pc->invokeId);
|
||||
p += encodeInt(p, 0x08); // dectivationDiversion
|
||||
p += encodeDeactivationDiversion(p, &facReqParm->u.CFDeactivate);
|
||||
encodeInvokeComponentLength(dummy_pc->buf, p);
|
||||
AddIE(skb, IE_FACILITY, dummy_pc->buf);
|
||||
|
||||
dummy_L4L3(dummy_pc, CC_FACILITY | REQUEST, skb);
|
||||
dummyPcAddTimer(dummy_pc, T_DEACTIVATE);
|
||||
|
||||
facConfParm->u.Info.SupplementaryServiceInfo = CapiSuccess;
|
||||
return CapiSuccess;
|
||||
}
|
||||
|
||||
int applFacCFInterrogateParameters(Appl_t *appl, struct FacReqParm *facReqParm,
|
||||
struct FacConfParm *facConfParm)
|
||||
{
|
||||
DummyProcess_t *dummy_pc;
|
||||
struct sk_buff *skb = alloc_l3msg(260, MT_FACILITY);
|
||||
__u8 *p;
|
||||
|
||||
if (!skb)
|
||||
return CAPI_MSGOSRESOURCEERR;
|
||||
dummy_pc = applNewDummyPc(appl, facReqParm->Function,
|
||||
sspc = SSProcessConstr(appl, facReqParm->Function,
|
||||
facReqParm->u.CFInterrogateParameters.Handle);
|
||||
if (!dummy_pc) {
|
||||
if (!sspc) {
|
||||
kfree_skb(skb);
|
||||
return CAPI_MSGOSRESOURCEERR;
|
||||
}
|
||||
|
||||
p = encodeInvokeComponentHead(dummy_pc->buf);
|
||||
p += encodeInt(p, dummy_pc->invokeId);
|
||||
p = encodeInvokeComponentHead(sspc->buf);
|
||||
p += encodeInt(p, sspc->invokeId);
|
||||
p += encodeInt(p, 0x0b); // interrogationDiversion
|
||||
p += encodeInterrogationDiversion(p, &facReqParm->u.CFInterrogateParameters);
|
||||
encodeInvokeComponentLength(dummy_pc->buf, p);
|
||||
AddIE(skb, IE_FACILITY, dummy_pc->buf);
|
||||
encodeInvokeComponentLength(sspc->buf, p);
|
||||
AddIE(skb, IE_FACILITY, sspc->buf);
|
||||
|
||||
dummy_L4L3(dummy_pc, CC_FACILITY | REQUEST, skb);
|
||||
dummyPcAddTimer(dummy_pc, T_INTERROGATE);
|
||||
SSProcess_L4L3(sspc, CC_FACILITY | REQUEST, skb);
|
||||
SSProcessAddTimer(sspc, T_INTERROGATE);
|
||||
|
||||
facConfParm->u.Info.SupplementaryServiceInfo = CapiSuccess;
|
||||
return CapiSuccess;
|
||||
}
|
||||
|
||||
int applFacCFInterrogateNumbers(Appl_t *appl, struct FacReqParm *facReqParm,
|
||||
struct FacConfParm *facConfParm)
|
||||
static int
|
||||
FacCFInterrogateNumbers(Application_t *appl, FacReqParm_t *facReqParm, FacConfParm_t *facConfParm)
|
||||
{
|
||||
DummyProcess_t *dummy_pc;
|
||||
SSProcess_t *sspc;
|
||||
struct sk_buff *skb = alloc_l3msg(260, MT_FACILITY);
|
||||
__u8 *p;
|
||||
|
||||
if (!skb)
|
||||
return CAPI_MSGOSRESOURCEERR;
|
||||
dummy_pc = applNewDummyPc(appl, facReqParm->Function,
|
||||
sspc = SSProcessConstr(appl, facReqParm->Function,
|
||||
facReqParm->u.CFInterrogateNumbers.Handle);
|
||||
if (!dummy_pc) {
|
||||
if (!sspc) {
|
||||
kfree_skb(skb);
|
||||
return CAPI_MSGOSRESOURCEERR;
|
||||
}
|
||||
|
||||
p = encodeInvokeComponentHead(dummy_pc->buf);
|
||||
p += encodeInt(p, dummy_pc->invokeId);
|
||||
p = encodeInvokeComponentHead(sspc->buf);
|
||||
p += encodeInt(p, sspc->invokeId);
|
||||
p += encodeInt(p, 0x11); // InterrogateServedUserNumbers
|
||||
encodeInvokeComponentLength(dummy_pc->buf, p);
|
||||
AddIE(skb, IE_FACILITY, dummy_pc->buf);
|
||||
dummy_L4L3(dummy_pc, CC_FACILITY | REQUEST, skb);
|
||||
dummyPcAddTimer(dummy_pc, T_INTERROGATE);
|
||||
encodeInvokeComponentLength(sspc->buf, p);
|
||||
AddIE(skb, IE_FACILITY, sspc->buf);
|
||||
SSProcess_L4L3(sspc, CC_FACILITY | REQUEST, skb);
|
||||
SSProcessAddTimer(sspc, T_INTERROGATE);
|
||||
|
||||
facConfParm->u.Info.SupplementaryServiceInfo = CapiSuccess;
|
||||
return CapiSuccess;
|
||||
}
|
||||
|
||||
|
||||
void dummyProcessTimeout(unsigned long arg);
|
||||
|
||||
void dummyPcConstr(DummyProcess_t *dummy_pc, Contr_t *contr, __u16 invokeId)
|
||||
static int
|
||||
FacCFActivate(Application_t *appl, FacReqParm_t *facReqParm, FacConfParm_t *facConfParm)
|
||||
{
|
||||
memset(dummy_pc, 0, sizeof(DummyProcess_t));
|
||||
dummy_pc->contr = contr;
|
||||
dummy_pc->invokeId = invokeId;
|
||||
}
|
||||
SSProcess_t *sspc;
|
||||
struct sk_buff *skb = alloc_l3msg(260, MT_FACILITY);
|
||||
__u8 *p;
|
||||
|
||||
void dummyPcDestr(DummyProcess_t *dummy_pc)
|
||||
{
|
||||
del_timer(&dummy_pc->tl);
|
||||
}
|
||||
|
||||
void dummyPcAddTimer(DummyProcess_t *dummy_pc, int msec)
|
||||
{
|
||||
dummy_pc->tl.function = dummyProcessTimeout;
|
||||
dummy_pc->tl.data = (unsigned long) dummy_pc;
|
||||
init_timer(&dummy_pc->tl);
|
||||
dummy_pc->tl.expires = jiffies + (msec * HZ) / 1000;
|
||||
add_timer(&dummy_pc->tl);
|
||||
}
|
||||
|
||||
DummyProcess_t *contrNewDummyPc(Contr_t* contr)
|
||||
{
|
||||
DummyProcess_t *dummy_pc;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CAPI_MAXDUMMYPCS; i++) {
|
||||
if (!contr->dummy_pcs[i])
|
||||
break;
|
||||
if (!skb)
|
||||
return CAPI_MSGOSRESOURCEERR;
|
||||
sspc = SSProcessConstr(appl, facReqParm->Function, facReqParm->u.CFActivate.Handle);
|
||||
if (!sspc) {
|
||||
kfree_skb(skb);
|
||||
return CAPI_MSGOSRESOURCEERR;
|
||||
}
|
||||
if (i == CAPI_MAXDUMMYPCS)
|
||||
return 0;
|
||||
dummy_pc = kmalloc(sizeof(DummyProcess_t), GFP_ATOMIC);
|
||||
if (!dummy_pc) {
|
||||
int_error();
|
||||
return 0;
|
||||
}
|
||||
contr->dummy_pcs[i] = dummy_pc;
|
||||
dummyPcConstr(dummy_pc, contr, ++contr->lastInvokeId);
|
||||
return dummy_pc;
|
||||
p = encodeInvokeComponentHead(sspc->buf);
|
||||
p += encodeInt(p, sspc->invokeId);
|
||||
p += encodeInt(p, 0x07); // activationDiversion
|
||||
p += encodeActivationDiversion(p, &facReqParm->u.CFActivate);
|
||||
encodeInvokeComponentLength(sspc->buf, p);
|
||||
AddIE(skb, IE_FACILITY, sspc->buf);
|
||||
SSProcess_L4L3(sspc, CC_FACILITY | REQUEST, skb);
|
||||
SSProcessAddTimer(sspc, T_ACTIVATE);
|
||||
|
||||
facConfParm->u.Info.SupplementaryServiceInfo = CapiSuccess;
|
||||
return CapiSuccess;
|
||||
}
|
||||
|
||||
void contrDelDummyPc(Contr_t* contr, DummyProcess_t *dummy_pc)
|
||||
static int
|
||||
FacCFDeactivate(Application_t *appl, FacReqParm_t *facReqParm, FacConfParm_t *facConfParm)
|
||||
{
|
||||
int i;
|
||||
SSProcess_t *sspc;
|
||||
struct sk_buff *skb = alloc_l3msg(260, MT_FACILITY);
|
||||
__u8 *p;
|
||||
|
||||
for (i = 0; i < CAPI_MAXDUMMYPCS; i++) {
|
||||
if (contr->dummy_pcs[i] == dummy_pc)
|
||||
break;
|
||||
if (!skb)
|
||||
return CAPI_MSGOSRESOURCEERR;
|
||||
sspc = SSProcessConstr(appl, facReqParm->Function, facReqParm->u.CFDeactivate.Handle);
|
||||
if (!sspc) {
|
||||
kfree_skb(skb);
|
||||
return CAPI_MSGOSRESOURCEERR;
|
||||
}
|
||||
if (i == CAPI_MAXDUMMYPCS) {
|
||||
int_error();
|
||||
p = encodeInvokeComponentHead(sspc->buf);
|
||||
p += encodeInt(p, sspc->invokeId);
|
||||
p += encodeInt(p, 0x08); // dectivationDiversion
|
||||
p += encodeDeactivationDiversion(p, &facReqParm->u.CFDeactivate);
|
||||
encodeInvokeComponentLength(sspc->buf, p);
|
||||
AddIE(skb, IE_FACILITY, sspc->buf);
|
||||
|
||||
SSProcess_L4L3(sspc, CC_FACILITY | REQUEST, skb);
|
||||
SSProcessAddTimer(sspc, T_DEACTIVATE);
|
||||
|
||||
facConfParm->u.Info.SupplementaryServiceInfo = CapiSuccess;
|
||||
return CapiSuccess;
|
||||
}
|
||||
|
||||
void
|
||||
SupplementaryFacilityReq(Application_t *appl, _cmsg *cmsg)
|
||||
{
|
||||
__u8 tmp[10];
|
||||
__u16 Info;
|
||||
FacReqParm_t facReqParm;
|
||||
FacConfParm_t facConfParm;
|
||||
Plci_t *plci;
|
||||
AppPlci_t *aplci;
|
||||
int ret;
|
||||
|
||||
if (capiGetFacReqParm(cmsg->FacilityRequestParameter, &facReqParm) < 0) {
|
||||
SendCmsgAnswer2Application(appl, cmsg, CapiIllMessageParmCoding);
|
||||
return;
|
||||
}
|
||||
contr->dummy_pcs[i] = 0;
|
||||
dummyPcDestr(dummy_pc);
|
||||
kfree(dummy_pc);
|
||||
}
|
||||
|
||||
DummyProcess_t *contrId2DummyPc(Contr_t* contr, __u16 invokeId)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CAPI_MAXDUMMYPCS; i++) {
|
||||
if (contr->dummy_pcs[i])
|
||||
if (contr->dummy_pcs[i]->invokeId == invokeId)
|
||||
facConfParm.Function = facReqParm.Function;
|
||||
switch (facReqParm.Function) {
|
||||
case 0x0000: // GetSupportedServices
|
||||
Info = GetSupportedServices(&facReqParm, &facConfParm);
|
||||
break;
|
||||
case 0x0001: // Listen
|
||||
Info = FacListen(appl, &facReqParm, &facConfParm);
|
||||
break;
|
||||
case 0x0004: // Suspend
|
||||
aplci = getAppPlci4addr(appl, cmsg->adr.adrPLCI);
|
||||
if (!aplci) {
|
||||
Info = CapiIllContrPlciNcci;
|
||||
break;
|
||||
}
|
||||
Info = AppPlciFacSuspendReq(aplci, &facReqParm, &facConfParm);
|
||||
break;
|
||||
case 0x0005: // Resume
|
||||
ret = ControllerNewPlci(appl->contr, &plci, MISDN_ID_ANY);
|
||||
if (ret) {
|
||||
Info = CapiNoPlciAvailable;
|
||||
break;
|
||||
}
|
||||
aplci = ApplicationNewAppPlci(appl, plci);
|
||||
if (!aplci) {
|
||||
ControllerReleasePlci(plci);
|
||||
Info = CapiNoPlciAvailable;
|
||||
break;
|
||||
}
|
||||
Info = AppPlciFacResumeReq(aplci, &facReqParm, &facConfParm);
|
||||
if (Info == CapiSuccess)
|
||||
cmsg->adr.adrPLCI = plci->addr;
|
||||
break;
|
||||
case 0x0009: // CF Activate
|
||||
Info = FacCFActivate(appl, &facReqParm, &facConfParm);
|
||||
break;
|
||||
case 0x000a: // CF Deactivate
|
||||
Info = FacCFDeactivate(appl, &facReqParm, &facConfParm);
|
||||
break;
|
||||
case 0x000b: // CF Interrogate Parameters
|
||||
Info = FacCFInterrogateParameters(appl, &facReqParm, &facConfParm);
|
||||
break;
|
||||
case 0x000c: // CF Interrogate Numbers
|
||||
Info = FacCFInterrogateNumbers(appl, &facReqParm, &facConfParm);
|
||||
break;
|
||||
default:
|
||||
Info = CapiSuccess;
|
||||
facConfParm.u.Info.SupplementaryServiceInfo = CapiSupplementaryServiceNotSupported;
|
||||
}
|
||||
if (i == CAPI_MAXDUMMYPCS)
|
||||
return 0;
|
||||
|
||||
return contr->dummy_pcs[i];
|
||||
|
||||
if (Info == 0x0000)
|
||||
capiEncodeFacConfParm(tmp, &facConfParm);
|
||||
else
|
||||
tmp[0] = 0;
|
||||
cmsg->FacilityConfirmationParameter = tmp;
|
||||
SendCmsgAnswer2Application(appl, cmsg, Info);
|
||||
}
|
||||
|
||||
void dummyProcessTimeout(unsigned long arg)
|
||||
SSProcess_t *
|
||||
SSProcessConstr(Application_t *appl, __u16 Function, __u32 Handle)
|
||||
{
|
||||
DummyProcess_t *dummy_pc = (DummyProcess_t *) arg;
|
||||
Contr_t* contr = dummy_pc->contr;
|
||||
Appl_t *appl;
|
||||
__u8 tmp[10], *p;
|
||||
_cmsg cmsg;
|
||||
SSProcess_t *sspc;
|
||||
|
||||
|
||||
del_timer(&dummy_pc->tl);
|
||||
appl = contrId2appl(contr, dummy_pc->ApplId);
|
||||
if (!appl)
|
||||
return;
|
||||
|
||||
capi_cmsg_header(&cmsg, dummy_pc->ApplId, CAPI_FACILITY, CAPI_IND,
|
||||
appl->MsgId++, contr->adrController);
|
||||
p = &tmp[1];
|
||||
p += capiEncodeWord(p, dummy_pc->Function);
|
||||
p += capiEncodeFacIndCFact(p, CapiTimeOut, dummy_pc->Handle);
|
||||
tmp[0] = p - &tmp[1];
|
||||
contrDelDummyPc(contr, dummy_pc);
|
||||
cmsg.FacilityIndicationParameter = tmp;
|
||||
contrRecvCmsg(contr, &cmsg);
|
||||
sspc = SSProcess_alloc();
|
||||
if (!sspc)
|
||||
return(NULL);
|
||||
memset(sspc, 0, sizeof(SSProcess_t));
|
||||
sspc->ApplId = appl->ApplId;
|
||||
sspc->Function = Function;
|
||||
sspc->Handle = Handle;
|
||||
ControllerAddSSProcess(appl->contr, sspc);
|
||||
return(sspc);
|
||||
}
|
||||
|
||||
void SSProcessDestr(SSProcess_t *sspc)
|
||||
{
|
||||
del_timer(&sspc->tl);
|
||||
list_del_init(&sspc->head);
|
||||
SSProcess_free(sspc);
|
||||
}
|
||||
|
||||
static void
|
||||
SendSSFacilityInd(Application_t *appl, __u32 addr, __u8 *para)
|
||||
{
|
||||
_cmsg *cmsg;
|
||||
|
||||
CMSG_ALLOC(cmsg);
|
||||
capi_cmsg_header(cmsg, appl->ApplId, CAPI_FACILITY, CAPI_IND, appl->MsgId++, addr);
|
||||
cmsg->FacilitySelector = 0x0003;
|
||||
cmsg->FacilityIndicationParameter = para;
|
||||
SendCmsg2Application(appl, cmsg);
|
||||
}
|
||||
|
||||
static void
|
||||
SendSSFacilityInd2All(Controller_t *contr, __u32 nMask, __u8 *para)
|
||||
{
|
||||
struct list_head *item;
|
||||
Application_t *appl;
|
||||
|
||||
list_for_each(item, &contr->Applications) {
|
||||
appl = (Application_t *)item;
|
||||
if (test_bit(APPL_STATE_RELEASE, &appl->state))
|
||||
continue;
|
||||
if (!(appl->NotificationMask & nMask))
|
||||
continue;
|
||||
SendSSFacilityInd(appl, contr->addr, para);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SSProcessTimeout(unsigned long arg)
|
||||
{
|
||||
SSProcess_t *sspc = (SSProcess_t *) arg;
|
||||
Application_t *appl;
|
||||
__u8 tmp[10], *p;
|
||||
|
||||
appl = getApplication4Id(sspc->contr, sspc->ApplId);
|
||||
if (!appl) {
|
||||
SSProcessDestr(sspc);
|
||||
return;
|
||||
}
|
||||
p = &tmp[1];
|
||||
p += capiEncodeWord(p, sspc->Function);
|
||||
p += capiEncodeFacIndCFact(p, CapiTimeOut, sspc->Handle);
|
||||
tmp[0] = p - &tmp[1];
|
||||
SendSSFacilityInd(appl, sspc->addr, tmp);
|
||||
SSProcessDestr(sspc);
|
||||
}
|
||||
|
||||
void SSProcessAddTimer(SSProcess_t *sspc, int msec)
|
||||
{
|
||||
sspc->tl.function = SSProcessTimeout;
|
||||
sspc->tl.data = (unsigned long) sspc;
|
||||
init_timer(&sspc->tl);
|
||||
sspc->tl.expires = jiffies + (msec * HZ) / 1000;
|
||||
add_timer(&sspc->tl);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
void printPublicPartyNumber(struct PublicPartyNumber *publicPartyNumber)
|
||||
{
|
||||
|
@ -570,16 +540,15 @@ void printAddress(struct Address *address)
|
|||
}
|
||||
#endif
|
||||
|
||||
void contrDummyFacility(Contr_t *contr, Q931_info_t *qi)
|
||||
static void
|
||||
SSProcessFacility(Controller_t *contr, Q931_info_t *qi)
|
||||
{
|
||||
Appl_t *appl;
|
||||
Application_t *appl;
|
||||
int ie_len;
|
||||
struct asn1_parm parm;
|
||||
DummyProcess_t *dummy_pc;
|
||||
_cmsg cmsg;
|
||||
__u8 tmp[255];
|
||||
SSProcess_t *sspc;
|
||||
__u8 tmp[256];
|
||||
__u8 *p, *end;
|
||||
__u16 ApplId;
|
||||
|
||||
if (!qi || !qi->facility) {
|
||||
int_error();
|
||||
|
@ -601,136 +570,104 @@ void contrDummyFacility(Contr_t *contr, Q931_info_t *qi)
|
|||
}
|
||||
ParseComponent(&parm, p, end);
|
||||
switch (parm.comp) {
|
||||
case invoke:
|
||||
case invoke:
|
||||
#if 0
|
||||
printk("invokeId %d\n", parm.u.inv.invokeId);
|
||||
printk("operationValue %d\n", parm.u.inv.operationValue);
|
||||
printk("invokeId %d\n", parm.u.inv.invokeId);
|
||||
printk("operationValue %d\n", parm.u.inv.operationValue);
|
||||
#endif
|
||||
switch (parm.u.inv.operationValue) {
|
||||
case 0x0009:
|
||||
switch (parm.u.inv.operationValue) {
|
||||
case 0x0009:
|
||||
#if 0
|
||||
printk("procedure %d basicService %d\n", parm.c.inv.o.actNot.procedure,
|
||||
parm.c.inv.o.actNot.basicService);
|
||||
printServedUserNr(&parm.c.inv.o.actNot.servedUserNr);
|
||||
printAddress(&parm.c.inv.o.actNot.address);
|
||||
printk("procedure %d basicService %d\n", parm.c.inv.o.actNot.procedure,
|
||||
parm.c.inv.o.actNot.basicService);
|
||||
printServedUserNr(&parm.c.inv.o.actNot.servedUserNr);
|
||||
printAddress(&parm.c.inv.o.actNot.address);
|
||||
#endif
|
||||
for (ApplId = 1; ApplId <= CAPI_MAXAPPL; ApplId++) {
|
||||
appl = contrId2appl(contr, ApplId);
|
||||
if (!appl)
|
||||
continue;
|
||||
if (!(appl->NotificationMask & 0x00000010))
|
||||
continue;
|
||||
|
||||
capi_cmsg_header(&cmsg, ApplId, CAPI_FACILITY, CAPI_IND,
|
||||
appl->MsgId++, contr->adrController);
|
||||
p = &tmp[1];
|
||||
p += capiEncodeWord(p, 0x8006);
|
||||
p += capiEncodeFacIndCFNotAct(p, &parm.u.inv.o.actNot);
|
||||
tmp[0] = p - &tmp[1];
|
||||
cmsg.FacilitySelector = 0x0003;
|
||||
cmsg.FacilityIndicationParameter = tmp;
|
||||
contrRecvCmsg(contr, &cmsg);
|
||||
p = &tmp[1];
|
||||
p += capiEncodeWord(p, 0x8006);
|
||||
p += capiEncodeFacIndCFNotAct(p, &parm.u.inv.o.actNot);
|
||||
tmp[0] = p - &tmp[1];
|
||||
SendSSFacilityInd2All(contr, SuppServiceCF, tmp);
|
||||
break;
|
||||
case 0x000a:
|
||||
#if 0
|
||||
printk("procedure %d basicService %d\n", parm.c.inv.o.deactNot.procedure,
|
||||
parm.c.inv.o.deactNot.basicService);
|
||||
printServedUserNr(&parm.c.inv.o.deactNot.servedUserNr);
|
||||
#endif
|
||||
p = &tmp[1];
|
||||
p += capiEncodeWord(p, 0x8007);
|
||||
p += capiEncodeFacIndCFNotDeact(p, &parm.u.inv.o.deactNot);
|
||||
tmp[0] = p - &tmp[1];
|
||||
SendSSFacilityInd2All(contr, SuppServiceCF, tmp);
|
||||
break;
|
||||
default:
|
||||
int_error();
|
||||
}
|
||||
break;
|
||||
case 0x000a:
|
||||
#if 0
|
||||
printk("procedure %d basicService %d\n", parm.c.inv.o.deactNot.procedure,
|
||||
parm.c.inv.o.deactNot.basicService);
|
||||
printServedUserNr(&parm.c.inv.o.deactNot.servedUserNr);
|
||||
#endif
|
||||
for (ApplId = 1; ApplId <= CAPI_MAXAPPL; ApplId++) {
|
||||
appl = contrId2appl(contr, ApplId);
|
||||
if (!appl)
|
||||
continue;
|
||||
if (!(appl->NotificationMask & 0x00000010))
|
||||
continue;
|
||||
|
||||
capi_cmsg_header(&cmsg, ApplId, CAPI_FACILITY, CAPI_IND,
|
||||
appl->MsgId++, contr->adrController);
|
||||
p = &tmp[1];
|
||||
p += capiEncodeWord(p, 0x8007);
|
||||
p += capiEncodeFacIndCFNotDeact(p, &parm.u.inv.o.deactNot);
|
||||
tmp[0] = p - &tmp[1];
|
||||
cmsg.FacilitySelector = 0x0003;
|
||||
cmsg.FacilityIndicationParameter = tmp;
|
||||
contrRecvCmsg(contr, &cmsg);
|
||||
case returnResult:
|
||||
sspc = getSSProcess4Id(contr, parm.u.retResult.invokeId);
|
||||
if (!sspc)
|
||||
return;
|
||||
appl = getApplication4Id(contr, sspc->ApplId);
|
||||
if (!appl)
|
||||
return;
|
||||
p = &tmp[1];
|
||||
p += capiEncodeWord(p, sspc->Function);
|
||||
switch (sspc->Function) {
|
||||
case 0x0009:
|
||||
p += capiEncodeFacIndCFact(p, 0, sspc->Handle);
|
||||
break;
|
||||
case 0x000a:
|
||||
p += capiEncodeFacIndCFdeact(p, 0, sspc->Handle);
|
||||
break;
|
||||
case 0x000b:
|
||||
p += capiEncodeFacIndCFinterParameters(p, 0, sspc->Handle,
|
||||
&parm.u.retResult.o.resultList);
|
||||
break;
|
||||
case 0x000c:
|
||||
p += capiEncodeFacIndCFinterNumbers(p, 0, sspc->Handle,
|
||||
&parm.u.retResult.o.list);
|
||||
break;
|
||||
default:
|
||||
int_error();
|
||||
break;
|
||||
}
|
||||
tmp[0] = p - &tmp[1];
|
||||
SendSSFacilityInd(appl, sspc->addr, tmp);
|
||||
SSProcessDestr(sspc);
|
||||
break;
|
||||
case returnError:
|
||||
sspc = getSSProcess4Id(contr, parm.u.retResult.invokeId);
|
||||
if (!sspc)
|
||||
return;
|
||||
appl = getApplication4Id(contr, sspc->ApplId);
|
||||
if (!appl)
|
||||
return;
|
||||
p = &tmp[1];
|
||||
p += capiEncodeWord(p, sspc->Function);
|
||||
p += capiEncodeFacIndCFact(p, 0x3600 | (parm.u.retError.errorValue & 0xff),
|
||||
sspc->Handle);
|
||||
tmp[0] = p - &tmp[1];
|
||||
SendSSFacilityInd(appl, sspc->addr, tmp);
|
||||
SSProcessDestr(sspc);
|
||||
break;
|
||||
default:
|
||||
int_error();
|
||||
}
|
||||
break;
|
||||
case returnResult:
|
||||
dummy_pc = contrId2DummyPc(contr, parm.u.retResult.invokeId);
|
||||
if (!dummy_pc)
|
||||
return;
|
||||
|
||||
appl = contrId2appl(contr, dummy_pc->ApplId);
|
||||
if (!appl)
|
||||
return;
|
||||
|
||||
capi_cmsg_header(&cmsg, dummy_pc->ApplId, CAPI_FACILITY, CAPI_IND,
|
||||
appl->MsgId++, contr->adrController);
|
||||
p = &tmp[1];
|
||||
p += capiEncodeWord(p, dummy_pc->Function);
|
||||
switch (dummy_pc->Function) {
|
||||
case 0x0009:
|
||||
p += capiEncodeFacIndCFact(p, 0, dummy_pc->Handle);
|
||||
break;
|
||||
case 0x000a:
|
||||
p += capiEncodeFacIndCFdeact(p, 0, dummy_pc->Handle);
|
||||
break;
|
||||
case 0x000b:
|
||||
p += capiEncodeFacIndCFinterParameters(p, 0, dummy_pc->Handle,
|
||||
&parm.u.retResult.o.resultList);
|
||||
break;
|
||||
case 0x000c:
|
||||
p += capiEncodeFacIndCFinterNumbers(p, 0, dummy_pc->Handle,
|
||||
&parm.u.retResult.o.list);
|
||||
break;
|
||||
default:
|
||||
int_error();
|
||||
break;
|
||||
}
|
||||
tmp[0] = p - &tmp[1];
|
||||
cmsg.FacilityIndicationParameter = tmp;
|
||||
contrRecvCmsg(contr, &cmsg);
|
||||
contrDelDummyPc(contr, dummy_pc);
|
||||
break;
|
||||
case returnError:
|
||||
dummy_pc = contrId2DummyPc(contr, parm.u.retResult.invokeId);
|
||||
if (!dummy_pc)
|
||||
return;
|
||||
|
||||
appl = contrId2appl(contr, dummy_pc->ApplId);
|
||||
if (!appl)
|
||||
return;
|
||||
|
||||
capi_cmsg_header(&cmsg, dummy_pc->ApplId, CAPI_FACILITY, CAPI_IND,
|
||||
appl->MsgId++, contr->adrController);
|
||||
p = &tmp[1];
|
||||
p += capiEncodeWord(p, dummy_pc->Function);
|
||||
p += capiEncodeFacIndCFact(p, 0x3600 | (parm.u.retError.errorValue &0xff),
|
||||
dummy_pc->Handle);
|
||||
tmp[0] = p - &tmp[1];
|
||||
cmsg.FacilityIndicationParameter = tmp;
|
||||
contrRecvCmsg(contr, &cmsg);
|
||||
contrDelDummyPc(contr, dummy_pc);
|
||||
break;
|
||||
default:
|
||||
int_error();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int contrDummyInd(Contr_t *contr, __u32 prim, struct sk_buff *skb)
|
||||
int
|
||||
Supplementary_l3l4(Controller_t *contr, __u32 prim, struct sk_buff *skb)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (!skb)
|
||||
return(ret);
|
||||
switch (prim) {
|
||||
case CC_FACILITY | INDICATION:
|
||||
if (skb && skb->len)
|
||||
contrDummyFacility(contr, (Q931_info_t *)skb->data);
|
||||
if (skb->len)
|
||||
SSProcessFacility(contr, (Q931_info_t *)skb->data);
|
||||
dev_kfree_skb(skb);
|
||||
ret = 0;
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue