Add line PLCI of resource PLCI
This commit is contained in:
parent
0c961ad003
commit
a0bf189dbc
17
chan_capi.c
17
chan_capi.c
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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))))) {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue