- don't show error if capi_read has no message.

- supplementary should not export internal structure
- added preliminary capicommand(chat)
This commit is contained in:
MelwareDE 2007-04-27 23:02:27 +00:00
parent 117ae4eb13
commit 025d7c827c
7 changed files with 288 additions and 33 deletions

View File

@ -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

View File

@ -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,

View File

@ -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);

230
chan_capi_chat.c Normal file
View File

@ -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(&param, "|");
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;
}

22
chan_capi_chat.h Normal file
View File

@ -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

View File

@ -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);

View File

@ -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
*/