Index: cdr.c =================================================================== --- cdr.c (revision 7258) +++ cdr.c (working copy) @@ -256,6 +256,8 @@ snprintf(workspace, workspacelen, "%d", cdr->billsec); else if (!strcasecmp(name, "disposition")) ast_copy_string(workspace, ast_cdr_disp2str(cdr->disposition), workspacelen); + else if (!strcasecmp(name, "hangupcause")) + snprintf(workspace, workspacelen, "%d", cdr->hangupcause); else if (!strcasecmp(name, "amaflags")) ast_copy_string(workspace, ast_cdr_flags2str(cdr->amaflags), workspacelen); else if (!strcasecmp(name, "accountcode")) @@ -274,8 +276,8 @@ /* readonly cdr variables */ static const char *cdr_readonly_vars[] = { "clid", "src", "dst", "dcontext", "channel", "dstchannel", "lastapp", "lastdata", "start", "answer", "end", "duration", - "billsec", "disposition", "amaflags", "accountcode", "uniqueid", - "userfield", NULL }; + "billsec", "disposition", "hangupcause", "amaflags", "accountcode", + "uniqueid", "userfield", NULL }; /*! Set a CDR channel variable \note You can't set the CDR variables that belong to the actual CDR record, like "billsec". */ @@ -618,6 +620,7 @@ ast_copy_string(cdr->src, num ? num : "", sizeof(cdr->src)); cdr->disposition = (c->_state == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NOANSWER; + cdr->hangupcause = 0; cdr->amaflags = c->amaflags ? c->amaflags : ast_default_amaflags; ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode)); /* Destination information */ @@ -730,6 +733,18 @@ return 0; } +int ast_cdr_sethangupcause(struct ast_channel *chan) +{ + struct ast_cdr *cdr = chan->cdr; + + while (cdr) { + if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) + cdr->hangupcause = chan->hangupcause; + cdr = cdr->next; + } + return 0; +} + int ast_cdr_update(struct ast_channel *c) { struct ast_cdr *cdr = c->cdr; Index: channel.c =================================================================== --- channel.c (revision 7258) +++ channel.c (working copy) @@ -1302,6 +1302,7 @@ chan->generatordata = NULL; chan->generator = NULL; if (chan->cdr) { /* End the CDR if it hasn't already */ + ast_cdr_sethangupcause(chan); ast_cdr_end(chan->cdr); ast_cdr_detach(chan->cdr); /* Post and Free the CDR */ chan->cdr = NULL; Index: doc/README.cdr =================================================================== --- doc/README.cdr (revision 7258) +++ doc/README.cdr (working copy) @@ -94,6 +94,7 @@ ${CDR(duration)} Duration of the call. ${CDR(billsec)} Duration of the call once it was answered. ${CDR(disposition)} ANSWERED, NO ANSWER, BUSY +${CDR(hangupcause)} Channel hangup cause ${CDR(amaflags)} DOCUMENTATION, BILL, IGNORE etc ${CDR(accountcode)} The channel's account code. ${CDR(uniqueid)} The channel's unique id. Index: doc/README.variables =================================================================== --- doc/README.variables (revision 7258) +++ doc/README.variables (working copy) @@ -778,6 +778,7 @@ ${CDR(duration)} Duration of the call. ${CDR(billsec)} Duration of the call once it was answered. ${CDR(disposition)} ANSWERED, NO ANSWER, BUSY +${CDR(hangupcause)} Channel hangup cause ${CDR(amaflags)} DOCUMENTATION, BILL, IGNORE etc ${CDR(accountcode)} The channel's account code. ${CDR(uniqueid)} The channel's unique id. Index: include/asterisk/cdr.h =================================================================== --- include/asterisk/cdr.h (revision 7258) +++ include/asterisk/cdr.h (working copy) @@ -79,6 +79,8 @@ int billsec; /*! What happened to the call */ int disposition; + /*! Why is the channel hanged up */ + int hangupcause; /*! What flags to use */ int amaflags; /*! What account number to use */ @@ -273,8 +275,8 @@ extern int ast_cdr_setuserfield(struct ast_channel *chan, const char *userfield); extern int ast_cdr_appenduserfield(struct ast_channel *chan, const char *userfield); +extern int ast_cdr_sethangupcause(struct ast_channel *chan); - /* Update CDR on a channel */ extern int ast_cdr_update(struct ast_channel *chan);