Add line PLCI of resource PLCI

This commit is contained in:
MelwareDE 2009-04-14 21:58:03 +00:00
parent 0c961ad003
commit a0bf189dbc
5 changed files with 111 additions and 44 deletions

View File

@ -3811,13 +3811,16 @@ static void capidev_handle_connect_active_indication(_cmsg *CMSG, unsigned int P
if (i->outgoing == 1) {
/* outgoing call */
if (i->channeltype == CAPI_CHANNELTYPE_NULL) {
/* NULL-PLCI needs a virtual connection */
capi_sendf(NULL, 0, CAPI_FACILITY_REQ, PLCI, get_capi_MessageNumber(),
"w(w(d()))",
FACILITYSELECTOR_LINE_INTERCONNECT,
0x0001, /* CONNECT */
0x00000030 /* mask */
);
if (i->resource_plci_type != CAPI_RESOURCE_PLCI_LINE) {
/* NULL-PLCI needs a virtual connection */
capi_sendf(NULL, 0, CAPI_FACILITY_REQ, PLCI, get_capi_MessageNumber(),
"w(w(d()))",
FACILITYSELECTOR_LINE_INTERCONNECT,
0x0001, /* CONNECT */
(i->line_plci == 0) ? 0x00000030 : 0x00000000 /* mask */
);
}
}
cc_start_b3(i);
} else {

View File

@ -490,6 +490,11 @@ struct capi_pvt {
/* Resource PLCI data */
int resource_plci_type; /* NULL PLCI, DATA, LINE */
/* Resource PLCI line if data */
struct capi_pvt *line_plci;
/* Resource PLCI data data if line */
struct capi_pvt *data_plci;
/*! Next channel in list */
struct capi_pvt *next;

View File

@ -83,7 +83,7 @@ static struct capichat_s* update_capi_mixer_part(
p_list[j++] = (_cbyte)(ii->PLCI >> 16);
p_list[j++] = (_cbyte)(ii->PLCI >> 24);
dest = (remove) ? 0x00000000 : 0x00000003;
if (ii->channeltype == CAPI_CHANNELTYPE_NULL) {
if (ii->channeltype == CAPI_CHANNELTYPE_NULL && ii->line_plci == 0) {
dest |= 0x00000030;
}
p_list[j++] = (_cbyte)(dest);
@ -104,21 +104,26 @@ static struct capichat_s* update_capi_mixer_part(
datapath = 0x00000000;
if (remove) {
/* now we need DATA_B3 again */
if (i->channeltype != CAPI_CHANNELTYPE_NULL) {
datapath = 0x0000000c;
} else {
datapath = 0x00000030;
if (i->line_plci == 0) {
if (i->channeltype != CAPI_CHANNELTYPE_NULL) {
datapath = 0x0000000c;
} else {
datapath = 0x00000030;
}
}
if (overall_found == 1) {
/* only one left, enable DATA_B3 too */
if (ii_last->channeltype != CAPI_CHANNELTYPE_NULL) {
p_list[5] |= 0x0c;
} else {
p_list[5] |= 0x30;
if (ii_last->line_plci == 0) {
if (ii_last->channeltype != CAPI_CHANNELTYPE_NULL) {
p_list[5] |= 0x0c;
} else {
p_list[5] |= 0x30;
}
}
}
}
if (i->channeltype == CAPI_CHANNELTYPE_NULL) {
if (i->channeltype == CAPI_CHANNELTYPE_NULL && i->line_plci == 0) {
if (!remove) {
datapath |= 0x00000030;
}
@ -492,15 +497,16 @@ int pbx_capi_chat_associate_resource_plci(struct ast_channel *c, char *param)
}
if (c->tech != &capi_tech) {
i = capi_mkresourceif(c, contr);
i = capi_mkresourceif(c, contr, 0);
if (i != NULL) {
char buffer[24];
snprintf(buffer, sizeof(buffer)-1, "%p", i);
pbx_builtin_setvar_helper(c, "RESOURCEPLCI", buffer);
capi_mkresourceif(c, contr, i);
}
}
return ((i != NULL) ? 0 : -1);
return (0); /* Always return success in case c->tech == &capi_tech or to fallback to NULL PLCI */
}
/*

View File

@ -86,10 +86,17 @@ void capi_remove_nullif(struct capi_pvt *i)
return;
}
cc_mutex_lock(&i->lock);
if (i->line_plci != 0) {
ii = i->line_plci;
i->line_plci = 0;
capi_remove_nullif(ii);
}
cc_mutex_unlock(&i->lock);
if (i->PLCI != 0) {
/* if the interface is in use, hangup first */
cc_mutex_lock(&i->lock);
state = i->state;
i->state = CAPI_STATE_DISCONNECTING;
capi_activehangup(i, state);
@ -211,25 +218,30 @@ struct capi_pvt *capi_mknullif(struct ast_channel *c, unsigned long long control
return tmp;
}
struct capi_pvt *capi_mkresourceif(struct ast_channel *c, unsigned long long controllermask)
{
struct capi_pvt *capi_mkresourceif(struct ast_channel *c, unsigned long long controllermask, struct capi_pvt *data_plci_ifc) {
struct capi_pvt *data_ifc /*, *line_ifc */;
unsigned int controller = 1;
int contrcount;
int channelcount = 0xffff;
int maxcontr = (CAPI_MAX_CONTROLLERS > (sizeof(controllermask)*8)) ?
(sizeof(controllermask)*8) : CAPI_MAX_CONTROLLERS;
cc_verbose(3, 1, VERBOSE_PREFIX_4 "capi_mkresourceif: find controller for mask 0x%lx\n",
controllermask);
/* find the next controller of mask with least plcis used */
for (contrcount = 0; contrcount < maxcontr; contrcount++) {
if ((controllermask & (1ULL << contrcount)) != 0) {
if (controller_nullplcis[contrcount] < channelcount) {
channelcount = controller_nullplcis[contrcount];
controller = contrcount + 1;
if (data_plci_ifc == 0) {
int contrcount;
int channelcount = 0xffff;
int maxcontr = (CAPI_MAX_CONTROLLERS > (sizeof(controllermask)*8)) ?
(sizeof(controllermask)*8) : CAPI_MAX_CONTROLLERS;
cc_verbose(3, 1, VERBOSE_PREFIX_4 "capi_mkresourceif: find controller for mask 0x%lx\n",
controllermask);
/* find the next controller of mask with least plcis used */
for (contrcount = 0; contrcount < maxcontr; contrcount++) {
if ((controllermask & (1ULL << contrcount)) != 0) {
if (controller_nullplcis[contrcount] < channelcount) {
channelcount = controller_nullplcis[contrcount];
controller = contrcount + 1;
}
}
}
} else {
controller = data_plci_ifc->controller;
}
data_ifc = malloc(sizeof(struct capi_pvt));
@ -241,11 +253,11 @@ struct capi_pvt *capi_mkresourceif(struct ast_channel *c, unsigned long long con
cc_mutex_init(&data_ifc->lock);
ast_cond_init(&data_ifc->event_trigger, NULL);
snprintf(data_ifc->name, sizeof(data_ifc->name) - 1, "%s-NULLPLCI", c->name);
snprintf(data_ifc->name, sizeof(data_ifc->name) - 1, "%s-%sPLCI", c->name, (data_plci_ifc == 0) ? "DATA" : "LINE");
snprintf(data_ifc->vname, sizeof(data_ifc->vname) - 1, "%s", data_ifc->name);
data_ifc->channeltype = CAPI_CHANNELTYPE_NULL;
data_ifc->resource_plci_type = CAPI_RESOURCE_PLCI_DATA;
data_ifc->resource_plci_type = (data_plci_ifc == 0) ? CAPI_RESOURCE_PLCI_DATA : CAPI_RESOURCE_PLCI_LINE;
data_ifc->used = c;
data_ifc->peer = c;
@ -265,9 +277,14 @@ struct capi_pvt *capi_mkresourceif(struct ast_channel *c, unsigned long long con
data_ifc->txgain = 1.0;
capi_gains(&data_ifc->g, 1.0, 1.0);
if (!(capi_create_reader_writer_pipe(data_ifc))) {
free(data_ifc);
return NULL;
if (data_plci_ifc == 0) {
if (!(capi_create_reader_writer_pipe(data_ifc))) {
free(data_ifc);
return NULL;
}
} else {
data_ifc->readerfd = -1;
data_ifc->writerfd = -1;
}
data_ifc->bproto = CC_BPROTO_TRANSPARENT;
@ -295,14 +312,39 @@ struct capi_pvt *capi_mkresourceif(struct ast_channel *c, unsigned long long con
"dw(wbb(www()()()()))",
_DI_MANU_ID,
_DI_ASSIGN_PLCI,
4, /* data */
0, /* bchannel */
(data_plci_ifc == 0) ? 4 : 5, /* data */
(data_plci_ifc == 0) ? 0 : (unsigned char)(data_plci_ifc->PLCI >> 8), /* bchannel */
1, /* connect */
1, 1, 0);
cc_mutex_unlock(&data_ifc->lock);
cc_verbose(3, 1, VERBOSE_PREFIX_4 "%s: created resource-interface on controller %d.\n",
data_ifc->vname, data_ifc->controller);
if (data_plci_ifc != 0) {
if (data_ifc->PLCI == 0) {
cc_log(LOG_WARNING, "%s: failed to create\n", data_ifc->vname);
capi_remove_nullif(data_ifc);
data_ifc = 0;
} else {
cc_mutex_lock(&data_plci_ifc->lock);
data_plci_ifc->line_plci = data_ifc;
capi_sendf(data_plci_ifc, 1, CAPI_FACILITY_REQ, data_plci_ifc->PLCI, get_capi_MessageNumber(),
"w(w(d()))",
FACILITYSELECTOR_LINE_INTERCONNECT,
0x0001, /* CONNECT */
0x00000000 /* mask */
);
cc_mutex_unlock(&data_plci_ifc->lock);
data_ifc->data_plci = data_plci_ifc;
data_ifc->writerfd = data_plci_ifc->writerfd;
data_plci_ifc->writerfd = -1;
}
}
if (data_ifc != 0) {
cc_verbose(3, 1, VERBOSE_PREFIX_4 "%s: created %s-resource-interface on controller %d.\n",
data_ifc->vname, (data_plci_ifc == 0) ? "data" : "line", data_ifc->controller);
}
return data_ifc;
}
@ -1279,6 +1321,17 @@ int capi_write_frame(struct capi_pvt *i, struct ast_frame *f)
cc_log(LOG_ERROR, "channel has no interface\n");
return -1;
}
{
struct capi_pvt *ii = i;
cc_mutex_lock(&ii->lock);
if (i->line_plci != 0)
i = i->line_plci;
cc_mutex_unlock(&ii->lock);
}
if (unlikely((!(i->isdnstate & CAPI_ISDN_STATE_B3_UP)) || (!i->NCCI) ||
((i->isdnstate & (CAPI_ISDN_STATE_B3_CHANGE | CAPI_ISDN_STATE_LI))))) {

View File

@ -54,7 +54,7 @@ extern int cc_add_peer_link_id(struct ast_channel *c);
extern struct ast_channel *cc_get_peer_link_id(const char *p);
extern void capi_remove_nullif(struct capi_pvt *i);
extern struct capi_pvt *capi_mknullif(struct ast_channel *c, unsigned long long controllermask);
extern struct capi_pvt *capi_mkresourceif(struct ast_channel *c, unsigned long long controllermask);
struct capi_pvt *capi_mkresourceif(struct ast_channel *c, unsigned long long controllermask, struct capi_pvt *data_plci_ifc);
extern int capi_create_reader_writer_pipe(struct capi_pvt *i);
extern struct ast_frame *capi_read_pipeframe(struct capi_pvt *i);
extern int capi_write_frame(struct capi_pvt *i, struct ast_frame *f);