update asterisk channel driver for lantiq SoCs to version ce67bdb8

git-svn-id: svn://svn.openwrt.org/openwrt/packages@33995 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
mirko 2012-10-29 17:38:12 +00:00
parent 66b769c491
commit 5c826e1eca
2 changed files with 141 additions and 26 deletions

View File

@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=asterisk18
PKG_VERSION:=1.8.10.1
PKG_RELEASE:=2
PKG_RELEASE:=4
PKG_SOURCE:=asterisk-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=http://downloads.asterisk.org/pub/telephony/asterisk/releases/

View File

@ -105,16 +105,24 @@ enum channel_state {
};
static struct lantiq_pvt {
struct ast_channel *owner; /* Channel we belong to, possibly NULL */
int port_id; /* Port number of this object, 0..n */
struct ast_channel *owner; /* Channel we belong to, possibly NULL */
int port_id; /* Port number of this object, 0..n */
int channel_state;
char context[AST_MAX_CONTEXT]; /* this port's dialplan context */
char ext[AST_MAX_EXTENSION+1]; /* the extension this port is connecting*/
int dial_timer; /* timer handle for autodial timeout */
char dtmfbuf[AST_MAX_EXTENSION+1]; /* buffer holding dialed digits */
int dtmfbuf_len; /* lenght of dtmfbuf */
int rtp_timestamp; /* timestamp for RTP packets */
uint16_t rtp_seqno; /* Sequence nr for RTP packets */
char context[AST_MAX_CONTEXT]; /* this port's dialplan context */
char ext[AST_MAX_EXTENSION+1]; /* the extension this port is connecting */
int dial_timer; /* timer handle for autodial timeout */
char dtmfbuf[AST_MAX_EXTENSION+1]; /* buffer holding dialed digits */
int dtmfbuf_len; /* lenght of dtmfbuf */
int rtp_timestamp; /* timestamp for RTP packets */
uint16_t rtp_seqno; /* Sequence nr for RTP packets */
uint32_t call_setup_start; /* Start of dialling in ms */
uint32_t call_setup_delay; /* time between ^ and 1st ring in ms */
uint16_t jb_size; /* Jitter buffer size */
uint32_t jb_underflow; /* Jitter buffer injected samples */
uint32_t jb_overflow; /* Jitter buffer dropped samples */
uint16_t jb_delay; /* Jitter buffer: playout delay */
uint16_t jb_invalid; /* Jitter buffer: Nr. of invalid packets */
} *iflist = NULL;
static struct lantiq_ctx {
@ -134,6 +142,8 @@ static struct ast_frame *ast_lantiq_exception(struct ast_channel *ast);
static int ast_lantiq_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
static int ast_lantiq_fixup(struct ast_channel *old, struct ast_channel *new);
static struct ast_channel *ast_lantiq_requester(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
static int acf_channel_read(struct ast_channel *chan, const char *funcname, char *args, char *buf, size_t buflen);
static void lantiq_jb_get_stats(int c);
static const struct ast_channel_tech lantiq_tech = {
.type = "TAPI",
@ -149,7 +159,8 @@ static const struct ast_channel_tech lantiq_tech = {
.exception = ast_lantiq_exception,
.indicate = ast_lantiq_indicate,
.fixup = ast_lantiq_fixup,
.requester = ast_lantiq_requester
.requester = ast_lantiq_requester,
.func_channel_read = acf_channel_read
};
/* Protect the interface list (of lantiq_pvt's) */
@ -193,6 +204,14 @@ typedef struct rtp_header
uint32_t ssrc;
} rtp_header_t;
static uint32_t now(void) {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
uint64_t tmp = ts.tv_sec*1000 + (ts.tv_nsec/1000000);
return (uint32_t) tmp;
}
static int lantiq_dev_open(const char *dev_path, const int32_t ch_num)
{
char dev_name[PATH_MAX];
@ -201,12 +220,31 @@ static int lantiq_dev_open(const char *dev_path, const int32_t ch_num)
return open((const char*)dev_name, O_RDWR, 0644);
}
static void lantiq_ring(int c, int r)
static void lantiq_ring(int c, int r, const char *cid)
{
uint8_t status;
if (r) {
status = (uint8_t) ioctl(dev_ctx.ch_fd[c], IFX_TAPI_RING_START, 0);
if (!cid) {
status = (uint8_t) ioctl(dev_ctx.ch_fd[c], IFX_TAPI_RING_START, 0);
} else {
IFX_TAPI_CID_MSG_t msg;
IFX_TAPI_CID_MSG_STRING_t cid_el;
memset(&msg, 0, sizeof(msg));
memset(&cid_el, 0, sizeof(cid_el));
cid_el.elementType = IFX_TAPI_CID_ST_CLI;
cid_el.len = strlen(cid);
strncpy((char*)cid_el.element, cid, (size_t)cid_el.len);
msg.txMode = IFX_TAPI_CID_HM_ONHOOK;
msg.messageType = IFX_TAPI_CID_MT_CSUP;
msg.message = (IFX_TAPI_CID_MSG_ELEMENT_t *)&cid_el;
msg.nMsgElements = 1;
status = (uint8_t) ioctl(dev_ctx.ch_fd[c], IFX_TAPI_CID_TX_SEQ_START, (IFX_int32_t) &msg);
}
} else {
status = (uint8_t) ioctl(dev_ctx.ch_fd[c], IFX_TAPI_RING_STOP, 0);
}
@ -379,6 +417,7 @@ static int ast_lantiq_indicate(struct ast_channel *chan, int condition, const vo
}
case AST_CONTROL_RINGING:
{
pvt->call_setup_delay = now() - pvt->call_setup_start;
lantiq_play_tone(pvt->port_id, TAPI_TONE_LOCALE_RINGING_CODE);
return 0;
}
@ -419,7 +458,11 @@ static int ast_lantiq_call(struct ast_channel *ast, char *dest, int timeout)
if (pvt->channel_state == ONHOOK) {
ast_log(LOG_DEBUG, "port %i is ringing\n", pvt->port_id);
lantiq_ring(pvt->port_id, 1);
char *cid = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
ast_log(LOG_DEBUG, "port %i CID: %s\n", pvt->port_id, cid ? cid : "none");
lantiq_ring(pvt->port_id, 1, cid);
pvt->channel_state = RINGING;
ast_setstate(ast, AST_STATE_RINGING);
@ -429,7 +472,7 @@ static int ast_lantiq_call(struct ast_channel *ast, char *dest, int timeout)
ast_setstate(ast, AST_STATE_BUSY);
ast_queue_control(ast, AST_CONTROL_BUSY);
}
ast_mutex_unlock(&iflock);
return 0;
@ -451,7 +494,7 @@ static int ast_lantiq_hangup(struct ast_channel *ast)
switch (pvt->channel_state) {
case RINGING:
case ONHOOK:
lantiq_ring(pvt->port_id, 0);
lantiq_ring(pvt->port_id, 0, NULL);
pvt->channel_state = ONHOOK;
break;
default:
@ -460,6 +503,8 @@ static int ast_lantiq_hangup(struct ast_channel *ast)
lantiq_play_tone(pvt->port_id, TAPI_TONE_LOCALE_BUSY_CODE);
}
lantiq_jb_get_stats(pvt->port_id);
ast_setstate(ast, AST_STATE_DOWN);
ast_module_unref(ast_module_info->self);
ast->tech_pvt = NULL;
@ -538,12 +583,73 @@ static int ast_lantiq_write(struct ast_channel *ast, struct ast_frame *frame)
return 0;
}
static int acf_channel_read(struct ast_channel *chan, const char *funcname, char *args, char *buf, size_t buflen)
{
struct lantiq_pvt *pvt;
int res = 0;
if (!chan || chan->tech != &lantiq_tech) {
ast_log(LOG_ERROR, "This function requires a valid Lantiq TAPI channel\n");
return -1;
}
ast_mutex_lock(&iflock);
pvt = (struct lantiq_pvt*) chan->tech_pvt;
if (!strcasecmp(args, "csd")) {
snprintf(buf, buflen, "%lu", (unsigned long int) pvt->call_setup_delay);
} else if (!strcasecmp(args, "jitter_stats")){
lantiq_jb_get_stats(pvt->port_id);
snprintf(buf, buflen, "jbBufSize=%u,jbUnderflow=%u,jbOverflow=%u,jbDelay=%u,jbInvalid=%u",
(uint32_t) pvt->jb_size,
(uint32_t) pvt->jb_underflow,
(uint32_t) pvt->jb_overflow,
(uint32_t) pvt->jb_delay,
(uint32_t) pvt->jb_invalid);
} else {
res = -1;
}
ast_mutex_unlock(&iflock);
return res;
}
static struct ast_frame * ast_lantiq_exception(struct ast_channel *ast)
{
ast_log(LOG_DEBUG, "entering... no code here...\n");
return NULL;
}
static void lantiq_jb_get_stats(int c) {
struct lantiq_pvt *pvt = &iflist[c];
IFX_TAPI_JB_STATISTICS_t param;
memset (&param, 0, sizeof (param));
if (ioctl (dev_ctx.ch_fd[c], IFX_TAPI_JB_STATISTICS_GET, (IFX_int32_t) &param) != IFX_SUCCESS) {
ast_debug(1, "Error getting jitter buffer stats.\n");
} else {
ast_debug(1, "Jitter buffer stats: dev=%u, ch=%u, nType=%u, nBufSize=%u, nIsUnderflow=%u, nDsOverflow=%u, nPODelay=%u, nInvalid=%u",
(uint32_t) param.dev,
(uint32_t) param.ch,
(uint32_t) param.nType,
(uint32_t) param.nBufSize,
(uint32_t) param.nIsUnderflow,
(uint32_t) param.nDsOverflow,
(uint32_t) param.nPODelay,
(uint32_t) param.nInvalid);
pvt->jb_size = param.nBufSize;
pvt->jb_underflow = param.nIsUnderflow;
pvt->jb_overflow = param.nDsOverflow;
pvt->jb_invalid = param.nInvalid;
pvt->jb_delay = param.nPODelay;
}
}
static int lantiq_standby(int c)
{
if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_LINE_FEED_SET, IFX_TAPI_LINE_FEED_STANDBY)) {
@ -566,7 +672,7 @@ static int lantiq_standby(int c)
static int lantiq_end_dialing(int c)
{
ast_log(LOG_DEBUG, "TODO - DEBUG MSG");
ast_log(LOG_DEBUG, "TODO - DEBUG MSG\n");
struct lantiq_pvt *pvt = &iflist[c];
if (pvt->dial_timer) {
@ -583,11 +689,12 @@ static int lantiq_end_dialing(int c)
static int lantiq_end_call(int c)
{
ast_log(LOG_DEBUG, "TODO - DEBUG MSG");
ast_log(LOG_DEBUG, "TODO - DEBUG MSG\n");
struct lantiq_pvt *pvt = &iflist[c];
if(pvt->owner) {
lantiq_jb_get_stats(c);
ast_queue_hangup(pvt->owner);
}
@ -596,7 +703,7 @@ static int lantiq_end_call(int c)
static struct ast_channel * lantiq_channel(int state, int c, char *ext, char *ctx)
{
ast_log(LOG_DEBUG, "TODO - DEBUG MSG");
ast_log(LOG_DEBUG, "TODO - DEBUG MSG\n");
struct ast_channel *chan = NULL;
@ -670,7 +777,6 @@ static int lantiq_dev_data_handler(int c)
frame.datalen = res - RTP_HEADER_LEN;
frame.data.ptr = buf + RTP_HEADER_LEN;
ast_mutex_lock(&iflock);
struct lantiq_pvt *pvt = (struct lantiq_pvt *) &iflist[c];
if (pvt->owner && (pvt->owner->_state == AST_STATE_UP)) {
if(!ast_channel_trylock(pvt->owner)) {
@ -679,8 +785,6 @@ static int lantiq_dev_data_handler(int c)
}
}
ast_mutex_unlock(&iflock);
/* ast_debug(1, "lantiq_dev_data_handler(): size: %i version: %i padding: %i extension: %i csrc_count: %i \n"
"marker: %i payload_type: %s seqno: %i timestamp: %i ssrc: %i\n",
(int)res,
@ -699,7 +803,7 @@ static int lantiq_dev_data_handler(int c)
static int accept_call(int c)
{
ast_log(LOG_DEBUG, "TODO - DEBUG MSG");
ast_log(LOG_DEBUG, "TODO - DEBUG MSG\n");
struct lantiq_pvt *pvt = &iflist[c];
@ -708,6 +812,7 @@ static int accept_call(int c)
switch (chan->_state) {
case AST_STATE_RINGING:
lantiq_play_tone(c, TAPI_TONE_LOCALE_NONE);
ast_queue_control(pvt->owner, AST_CONTROL_ANSWER);
pvt->channel_state = INCALL;
break;
@ -726,7 +831,7 @@ static int lantiq_dev_event_hook(int c, int state)
ast_log(LOG_DEBUG, "on port %i detected event %s hook\n", c, state ? "on" : "off");
int ret = -1;
if (state) {
if (state) { /* going onhook */
switch (iflist[c].channel_state) {
case OFFHOOK:
ret = lantiq_standby(c);
@ -744,7 +849,7 @@ static int lantiq_dev_event_hook(int c, int state)
break;
}
iflist[c].channel_state = ONHOOK;
} else {
} else { /* going offhook */
if (ioctl(dev_ctx.ch_fd[c], IFX_TAPI_LINE_FEED_SET, IFX_TAPI_LINE_FEED_ACTIVE)) {
ast_log(LOG_ERROR, "IFX_TAPI_LINE_FEED_SET ioctl failed\n");
goto out;
@ -799,7 +904,7 @@ static void lantiq_dial(struct lantiq_pvt *pvt)
ast_verbose(VERBOSE_PREFIX_3 " extension exists, starting PBX %s\n", pvt->ext);
chan = lantiq_channel(AST_STATE_UP, 1, pvt->ext+1, pvt->context);
chan = lantiq_channel(AST_STATE_UP, pvt->port_id, pvt->ext+1, pvt->context);
chan->tech_pvt = pvt;
pvt->owner = chan;
@ -807,6 +912,8 @@ static void lantiq_dial(struct lantiq_pvt *pvt)
ast_setstate(chan, AST_STATE_RING);
pvt->channel_state = INCALL;
pvt->call_setup_start = now();
if (ast_pbx_start(chan)) {
ast_log(LOG_WARNING, " unable to start PBX on %s\n", chan->name);
ast_hangup(chan);
@ -1104,6 +1211,13 @@ static struct lantiq_pvt *lantiq_init_pvt(struct lantiq_pvt *pvt)
pvt->dial_timer = 0;
pvt->dtmfbuf[0] = '\0';
pvt->dtmfbuf_len = 0;
pvt->call_setup_start = 0;
pvt->call_setup_delay = 0;
pvt->jb_size = 0;
pvt->jb_underflow = 0;
pvt->jb_overflow = 0;
pvt->jb_delay = 0;
pvt->jb_invalid = 0;
} else {
ast_log(LOG_ERROR, "unable to clear pvt structure\n");
}
@ -1327,6 +1441,7 @@ static int load_module(void)
return AST_MODULE_LOAD_DECLINE;
}
} else if (!strcasecmp(v->name, "calleridtype")) {
ast_log(LOG_DEBUG, "Setting CID type to %s.\n", v->value);
if (!strcasecmp(v->value, "telecordia")) {
cid_type = IFX_TAPI_CID_STD_TELCORDIA;
} else if (!strcasecmp(v->value, "etsifsk")) {