- don't show error if capi_read has no message.
- supplementary should not export internal structure - added preliminary capicommand(chat)V1_1
parent
117ae4eb13
commit
025d7c827c
2
Makefile
2
Makefile
|
@ -94,7 +94,7 @@ SHAREDOS=chan_capi.so
|
|||
|
||||
OBJECTS=chan_capi.o chan_capi_utils.o chan_capi_rtp.o \
|
||||
chan_capi_qsig_core.o chan_capi_qsig_ecma.o chan_capi_qsig_asn197ade.o \
|
||||
chan_capi_qsig_asn197no.o chan_capi_supplementary.o
|
||||
chan_capi_qsig_asn197no.o chan_capi_supplementary.o chan_capi_chat.o
|
||||
|
||||
CFLAGS+=-Wno-missing-prototypes -Wno-missing-declarations
|
||||
|
||||
|
|
19
chan_capi.c
19
chan_capi.c
|
@ -36,6 +36,7 @@
|
|||
#include "chan_capi_qsig_asn197no.h"
|
||||
#include "chan_capi_utils.h"
|
||||
#include "chan_capi_supplementary.h"
|
||||
#include "chan_capi_chat.h"
|
||||
|
||||
/* #define CC_VERSION "x.y.z" */
|
||||
#define CC_VERSION "$Revision$"
|
||||
|
@ -49,7 +50,6 @@ unsigned capi_ApplID = CAPI_APPLID_UNUSED;
|
|||
|
||||
static const char tdesc[] = "Common ISDN API Driver (" CC_VERSION ")";
|
||||
static const char channeltype[] = "CAPI";
|
||||
static const struct ast_channel_tech capi_tech;
|
||||
#ifdef CC_AST_HAS_VERSION_1_4
|
||||
#define AST_MODULE "chan_capi"
|
||||
#else
|
||||
|
@ -1378,8 +1378,9 @@ static struct ast_frame *pbx_capi_read(struct ast_channel *c)
|
|||
f->subclass = 0;
|
||||
|
||||
readsize = read(i->readerfd, f, sizeof(struct ast_frame));
|
||||
if (readsize != sizeof(struct ast_frame)) {
|
||||
cc_log(LOG_ERROR, "did not read a whole frame\n");
|
||||
if ((readsize != sizeof(struct ast_frame)) && (readsize > 0)) {
|
||||
cc_log(LOG_ERROR, "did not read a whole frame (len=%d, err=%d)\n",
|
||||
readsize, errno);
|
||||
}
|
||||
|
||||
f->mallocd = 0;
|
||||
|
@ -2948,7 +2949,6 @@ static int handle_facility_indication_dtmf(
|
|||
*/
|
||||
static void capidev_handle_facility_indication(_cmsg *CMSG, unsigned int PLCI, unsigned int NCCI, struct capi_pvt *i)
|
||||
{
|
||||
_cmsg CMSG2;
|
||||
int resp_done = 0;
|
||||
|
||||
switch (FACILITY_IND_FACILITYSELECTOR(CMSG)) {
|
||||
|
@ -2969,10 +2969,10 @@ static void capidev_handle_facility_indication(_cmsg *CMSG, unsigned int PLCI, u
|
|||
}
|
||||
|
||||
if (!resp_done) {
|
||||
FACILITY_RESP_HEADER(&CMSG2, capi_ApplID, HEADER_MSGNUM(CMSG), PLCI);
|
||||
FACILITY_RESP_FACILITYSELECTOR(&CMSG2) = FACILITY_IND_FACILITYSELECTOR(CMSG);
|
||||
FACILITY_RESP_FACILITYRESPONSEPARAMETERS(&CMSG2) = FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG);
|
||||
_capi_put_cmsg(&CMSG2);
|
||||
capi_sendf(NULL, 0, CAPI_FACILITY_RESP, PLCI, HEADER_MSGNUM(CMSG),
|
||||
"w()",
|
||||
FACILITYSELECTOR_SUPPLEMENTARY
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4527,6 +4527,7 @@ static struct capicommands_s {
|
|||
{ "ccbs", pbx_capi_ccbs, 0 },
|
||||
{ "ccbsstop", pbx_capi_ccbsstop, 0 },
|
||||
{ "ccpartybusy", pbx_capi_ccpartybusy, 0 },
|
||||
{ "chat", pbx_capi_chat, 0 },
|
||||
{ "hangup", pbx_capi_realhangup, 0 },
|
||||
{ "qsig_ssct", pbx_capi_qsig_ssct, 1 },
|
||||
{ "qsig_ct", pbx_capi_qsig_ct, 1 },
|
||||
|
@ -5305,7 +5306,7 @@ static struct ast_cli_entry cli_debug =
|
|||
static struct ast_cli_entry cli_no_debug =
|
||||
{ { "capi", "no", "debug", NULL }, pbxcli_capi_no_debug, "Disable CAPI debugging", no_debug_usage };
|
||||
|
||||
static const struct ast_channel_tech capi_tech = {
|
||||
const struct ast_channel_tech capi_tech = {
|
||||
.type = channeltype,
|
||||
.description = tdesc,
|
||||
.capabilities = AST_FORMAT_ALAW,
|
||||
|
|
|
@ -562,6 +562,7 @@ struct cc_capi_controller {
|
|||
/*
|
||||
* prototypes
|
||||
*/
|
||||
extern const struct ast_channel_tech capi_tech;
|
||||
extern unsigned capi_ApplID;
|
||||
extern struct capi_pvt *iflist;
|
||||
extern void cc_start_b3(struct capi_pvt *i);
|
||||
|
|
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
* (CAPI*)
|
||||
*
|
||||
* An implementation of Common ISDN API 2.0 for Asterisk
|
||||
*
|
||||
* Copyright (C) 2005-2007 Cytronics & Melware
|
||||
*
|
||||
* Armin Schindler <armin@melware.de>
|
||||
*
|
||||
* This program is free software and may be modified and
|
||||
* distributed under the terms of the GNU Public License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "chan_capi20.h"
|
||||
#include "chan_capi.h"
|
||||
#include "chan_capi_chat.h"
|
||||
#include "chan_capi_utils.h"
|
||||
|
||||
#define CAPI_MAX_MEETME_NAME 32
|
||||
|
||||
struct capichat_s {
|
||||
char name[CAPI_MAX_MEETME_NAME];
|
||||
unsigned int number;
|
||||
struct ast_channel *chan;
|
||||
struct capi_pvt *i;
|
||||
_cdword plci;
|
||||
struct capichat_s *next;
|
||||
};
|
||||
|
||||
static struct capichat_s *chat_list = NULL;
|
||||
AST_MUTEX_DEFINE_STATIC(chat_lock);
|
||||
|
||||
/*
|
||||
* update the capi mixer for the given char room
|
||||
*/
|
||||
static void update_capi_mixer(int remove, unsigned int roomnumber, _cdword plci)
|
||||
{
|
||||
struct capichat_s *room;
|
||||
unsigned char p_list[360];
|
||||
_cdword dest;
|
||||
_cdword datapath;
|
||||
capi_prestruct_t p_struct;
|
||||
unsigned int found = 0;
|
||||
_cword j = 0;
|
||||
|
||||
cc_mutex_lock(&chat_lock);
|
||||
room = chat_list;
|
||||
while (room) {
|
||||
if ((room->number == roomnumber) &&
|
||||
(room->plci != plci)) {
|
||||
found++;
|
||||
if (j + 9 > sizeof(p_list)) {
|
||||
/* maybe we need to split capi messages here */
|
||||
break;
|
||||
}
|
||||
p_list[j++] = 8;
|
||||
p_list[j++] = (_cbyte)(room->plci);
|
||||
p_list[j++] = (_cbyte)(room->plci >> 8);
|
||||
p_list[j++] = (_cbyte)(room->plci >> 16);
|
||||
p_list[j++] = (_cbyte)(room->plci >> 24);
|
||||
dest = (remove) ? 0x00000000 : 0x00000003;
|
||||
p_list[j++] = (_cbyte)(dest);
|
||||
p_list[j++] = (_cbyte)(dest >> 8);
|
||||
p_list[j++] = (_cbyte)(dest >> 16);
|
||||
p_list[j++] = (_cbyte)(dest >> 24);
|
||||
}
|
||||
room = room->next;
|
||||
}
|
||||
cc_mutex_unlock(&chat_lock);
|
||||
|
||||
if (found) {
|
||||
p_struct.wLen = j;
|
||||
p_struct.info = p_list;
|
||||
|
||||
/* don't send DATA_B3 to me */
|
||||
datapath = 0x00000000;
|
||||
if (remove) {
|
||||
/* now we need DATA_B3 again */
|
||||
datapath = 0x000000c0;
|
||||
if (found == 1) {
|
||||
/* only one left, enable DATA_B3 too */
|
||||
p_list[5] |= 0x30;
|
||||
}
|
||||
}
|
||||
|
||||
capi_sendf(NULL, 0, CAPI_FACILITY_REQ, plci, get_capi_MessageNumber(),
|
||||
"w(w(dc))",
|
||||
FACILITYSELECTOR_LINE_INTERCONNECT,
|
||||
0x0001, /* CONNECT */
|
||||
datapath,
|
||||
&p_struct
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* delete a chat member
|
||||
*/
|
||||
static void del_chat_member(struct capichat_s *room)
|
||||
{
|
||||
struct capichat_s *tmproom;
|
||||
struct capichat_s *tmproom2 = NULL;
|
||||
unsigned int roomnumber = room->number;
|
||||
_cdword plci = room->plci;
|
||||
|
||||
cc_mutex_lock(&chat_lock);
|
||||
tmproom = chat_list;
|
||||
while (tmproom) {
|
||||
if (tmproom == room) {
|
||||
if (!tmproom2) {
|
||||
chat_list = tmproom->next;
|
||||
} else {
|
||||
tmproom2->next = tmproom->next;
|
||||
}
|
||||
cc_verbose(3, 1, VERBOSE_PREFIX_3 "capi chat: removed member from room %s (%d)\n",
|
||||
room->name, room->number);
|
||||
free(room);
|
||||
}
|
||||
tmproom2 = tmproom;
|
||||
tmproom = tmproom->next;
|
||||
}
|
||||
cc_mutex_unlock(&chat_lock);
|
||||
|
||||
update_capi_mixer(1, roomnumber, plci);
|
||||
}
|
||||
|
||||
/*
|
||||
* add a new chat member
|
||||
*/
|
||||
static struct capichat_s *add_chat_member(char *roomname,
|
||||
struct ast_channel *chan, struct capi_pvt *i)
|
||||
{
|
||||
struct capichat_s *room = NULL;
|
||||
struct capichat_s *tmproom;
|
||||
unsigned int roomnumber = 1;
|
||||
|
||||
room = malloc(sizeof(struct capichat_s));
|
||||
if (room == NULL) {
|
||||
cc_log(LOG_ERROR, "Unable to allocate capi chat struct.\n");
|
||||
return NULL;
|
||||
}
|
||||
memset(room, 0, sizeof(struct capichat_s));
|
||||
|
||||
strncpy(room->name, roomname, sizeof(room->name));
|
||||
room->name[sizeof(room->name) - 1] = 0;
|
||||
room->chan = chan;
|
||||
room->i = i;
|
||||
room->plci = i->PLCI;
|
||||
|
||||
cc_mutex_lock(&chat_lock);
|
||||
|
||||
tmproom = chat_list;
|
||||
while (tmproom) {
|
||||
if (!strcmp(tmproom->name, roomname)) {
|
||||
roomnumber = tmproom->number;
|
||||
break;
|
||||
} else {
|
||||
if (tmproom->number == roomnumber) {
|
||||
roomnumber++;
|
||||
}
|
||||
}
|
||||
tmproom = tmproom->next;
|
||||
}
|
||||
|
||||
room->number = roomnumber;
|
||||
|
||||
room->next = chat_list;
|
||||
chat_list = room;
|
||||
|
||||
cc_mutex_unlock(&chat_lock);
|
||||
|
||||
cc_verbose(3, 1, VERBOSE_PREFIX_3 "capi chat: added new member to room %s (%d)\n",
|
||||
roomname, roomnumber);
|
||||
|
||||
update_capi_mixer(0, roomnumber, room->plci);
|
||||
|
||||
return room;
|
||||
}
|
||||
|
||||
/*
|
||||
* start the chat
|
||||
*/
|
||||
int pbx_capi_chat(struct ast_channel *c, char *param)
|
||||
{
|
||||
struct capi_pvt *i = NULL;
|
||||
char *roomname, *options;
|
||||
struct capichat_s *room;
|
||||
struct ast_frame *f;
|
||||
|
||||
if (c->tech == &capi_tech) {
|
||||
i = CC_CHANNEL_PVT(c);
|
||||
} else
|
||||
return -1;
|
||||
|
||||
roomname = strsep(¶m, "|");
|
||||
options = param;
|
||||
|
||||
if (!roomname) {
|
||||
cc_log(LOG_WARNING, "capi chat requires room name.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cc_verbose(3, 1, VERBOSE_PREFIX_3 "capi chat: %s: roomname=%s options=%s\n",
|
||||
c->name, roomname, options);
|
||||
|
||||
room = add_chat_member(roomname, c, i);
|
||||
if (!room) {
|
||||
cc_log(LOG_WARNING, "Unable to open capi chat room.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (ast_waitfor(c, 500) >= 0) {
|
||||
f = ast_read(c);
|
||||
if (f) {
|
||||
ast_frfree(f);
|
||||
} else {
|
||||
/* channel was hung up or something else happened */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
del_chat_member(room);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* (CAPI*)
|
||||
*
|
||||
* An implementation of Common ISDN API 2.0 for Asterisk
|
||||
*
|
||||
* Copyright (C) 2006-2007 Cytronics & Melware
|
||||
*
|
||||
* Armin Schindler <armin@melware.de>
|
||||
*
|
||||
* This program is free software and may be modified and
|
||||
* distributed under the terms of the GNU Public License.
|
||||
*/
|
||||
|
||||
#ifndef _PBX_CAPI_CHAT_H
|
||||
#define _PBX_CAPI_CHAT_H
|
||||
|
||||
/*
|
||||
* prototypes
|
||||
*/
|
||||
extern int pbx_capi_chat(struct ast_channel *c, char *param);
|
||||
|
||||
#endif
|
|
@ -20,6 +20,30 @@
|
|||
#include "chan_capi_supplementary.h"
|
||||
#include "chan_capi_utils.h"
|
||||
|
||||
|
||||
#define CCBSNR_TYPE_CCBS 1
|
||||
#define CCBSNR_TYPE_CCNR 2
|
||||
|
||||
#define CCBSNR_AVAILABLE 1
|
||||
#define CCBSNR_REQUESTED 2
|
||||
#define CCBSNR_ACTIVATED 3
|
||||
|
||||
struct ccbsnr_s {
|
||||
char type;
|
||||
_cword id;
|
||||
unsigned int plci;
|
||||
unsigned int state;
|
||||
unsigned int handle;
|
||||
_cword mode;
|
||||
_cword rbref;
|
||||
char partybusy;
|
||||
char context[AST_MAX_CONTEXT];
|
||||
char exten[AST_MAX_EXTENSION];
|
||||
int priority;
|
||||
time_t age;
|
||||
struct ccbsnr_s *next;
|
||||
};
|
||||
|
||||
static struct ccbsnr_s *ccbsnr_list = NULL;
|
||||
AST_MUTEX_DEFINE_STATIC(ccbsnr_lock);
|
||||
|
||||
|
|
|
@ -14,29 +14,6 @@
|
|||
#ifndef _PBX_CAPI_SUPP_H
|
||||
#define _PBX_CAPI_SUPP_H
|
||||
|
||||
#define CCBSNR_TYPE_CCBS 1
|
||||
#define CCBSNR_TYPE_CCNR 2
|
||||
|
||||
#define CCBSNR_AVAILABLE 1
|
||||
#define CCBSNR_REQUESTED 2
|
||||
#define CCBSNR_ACTIVATED 3
|
||||
|
||||
struct ccbsnr_s {
|
||||
char type;
|
||||
_cword id;
|
||||
unsigned int plci;
|
||||
unsigned int state;
|
||||
unsigned int handle;
|
||||
_cword mode;
|
||||
_cword rbref;
|
||||
char partybusy;
|
||||
char context[AST_MAX_CONTEXT];
|
||||
char exten[AST_MAX_EXTENSION];
|
||||
int priority;
|
||||
time_t age;
|
||||
struct ccbsnr_s *next;
|
||||
};
|
||||
|
||||
/*
|
||||
* prototypes
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue