diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index 55a00905042f46ecceac8f0881a73a766c1c705d..5adb797a5aae2fdff433e746cf5e664dbc5b1bc9 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -1642,19 +1642,29 @@ static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *calle } if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) { + int pres = ast_party_id_presentation(&caller->id); if (cwcid == 0) { - p->cidlen = ast_callerid_generate(p->cidspill, + p->cidlen = ast_callerid_full_generate(p->cidspill, caller->id.name.str, caller->id.number.str, + NULL, + -1, + pres, + 0, + CID_TYPE_MDMF, AST_LAW(p)); } else { ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", caller->id.name.str, caller->id.number.str); p->callwaitcas = 0; p->cidcwexpire = 0; - p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, + p->cidlen = ast_callerid_callwaiting_full_generate(p->cidspill, caller->id.name.str, caller->id.number.str, + NULL, + -1, + pres, + 0, AST_LAW(p)); p->cidlen += READ_SIZE * 4; } diff --git a/channels/sig_analog.c b/channels/sig_analog.c index bd16d3561475b78644e7f7c7c6fb3d7cd3d7da60..76ee645c26f03bbf56d6a61a0d6b508cff4a595b 100644 --- a/channels/sig_analog.c +++ b/channels/sig_analog.c @@ -1089,6 +1089,10 @@ int analog_call(struct analog_pvt *p, struct ast_channel *ast, const char *rdest if (p->use_callerid) { p->caller.id.name.str = p->lastcid_name; p->caller.id.number.str = p->lastcid_num; + p->caller.id.name.valid = ast_channel_connected(ast)->id.name.valid; + p->caller.id.number.valid = ast_channel_connected(ast)->id.number.valid; + p->caller.id.name.presentation = ast_channel_connected(ast)->id.name.presentation; + p->caller.id.number.presentation = ast_channel_connected(ast)->id.number.presentation; } ast_setstate(ast, AST_STATE_RINGING); @@ -2264,10 +2268,8 @@ static void *__analog_ss_thread(void *data) ast_verb(3, "Disabling Caller*ID on %s\n", ast_channel_name(chan)); /* Disable Caller*ID if enabled */ p->hidecallerid = 1; - ast_party_number_free(&ast_channel_caller(chan)->id.number); - ast_party_number_init(&ast_channel_caller(chan)->id.number); - ast_party_name_free(&ast_channel_caller(chan)->id.name); - ast_party_name_init(&ast_channel_caller(chan)->id.name); + ast_channel_caller(chan)->id.number.presentation = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED; + ast_channel_caller(chan)->id.name.presentation = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED; res = analog_play_tone(p, idx, ANALOG_TONE_DIALRECALL); if (res) { ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", @@ -2353,7 +2355,8 @@ static void *__analog_ss_thread(void *data) ast_verb(3, "Enabling Caller*ID on %s\n", ast_channel_name(chan)); /* Enable Caller*ID if enabled */ p->hidecallerid = 0; - ast_set_callerid(chan, p->cid_num, p->cid_name, NULL); + ast_channel_caller(chan)->id.number.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED; + ast_channel_caller(chan)->id.name.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED; res = analog_play_tone(p, idx, ANALOG_TONE_DIALRECALL); if (res) { ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", diff --git a/include/asterisk/callerid.h b/include/asterisk/callerid.h index 460f105c18fb010cc56c7d99db7aff8980783a6e..16a3df11f49ce00cba3efb44c400435526f65185 100644 --- a/include/asterisk/callerid.h +++ b/include/asterisk/callerid.h @@ -55,6 +55,7 @@ #define CID_UNKNOWN_NUMBER (1 << 3) #define CID_MSGWAITING (1 << 4) #define CID_NOMSGWAITING (1 << 5) +#define CID_QUALIFIER (1 << 6) #define CID_SIG_BELL 1 #define CID_SIG_V23 2 @@ -67,6 +68,12 @@ #define CID_START_POLARITY_IN 3 #define CID_START_DTMF_NOALERT 4 +/* Caller ID message formats */ +/*! SDMF - number only */ +#define CID_TYPE_SDMF 0x00 +/*! MDMF - name, number, etc. */ +#define CID_TYPE_MDMF 0x01 + /* defines dealing with message waiting indication generation */ /*! MWI SDMF format */ #define CID_MWI_TYPE_SDMF 0x00 @@ -101,7 +108,26 @@ void callerid_init(void); * \return It returns the size * (in bytes) of the data (if it returns a size of 0, there is probably an error) */ -int callerid_generate(unsigned char *buf, const char *number, const char *name, int flags, int callwaiting, struct ast_format *codec); +int callerid_generate(unsigned char *buf, const char *number, const char *name, int flags, int callwaiting, struct ast_format *codec); + +/*! \brief Generates a CallerID FSK stream in ulaw format suitable for transmission. + * \param buf Buffer to use. If "buf" is supplied, it will use that buffer instead of allocating its own. + * "buf" must be at least 32000 bytes in size of you want to be sure you don't have an overrun. + * \param number Use NULL for no number or "P" for "private" + * \param name name to be used + * \param ddn Dialable Directory Number (or NULL) + * \param redirecting Redirecting reason + * \param flags passed flags + * \param format Message format + * \param callwaiting callwaiting flag + * \param codec -- either AST_FORMAT_ULAW or AST_FORMAT_ALAW + * \details + * This function creates a stream of callerid (a callerid spill) data in ulaw format. + * \return It returns the size + * (in bytes) of the data (if it returns a size of 0, there is probably an error) + */ +int callerid_full_generate(unsigned char *buf, const char *number, const char *name, const char *ddn, int redirecting, + int flags, int format, int callwaiting, struct ast_format *codec); /*! \brief Create a callerID state machine * \param cid_signalling Type of signalling in use @@ -177,6 +203,23 @@ void callerid_free(struct callerid_state *cid); */ int ast_callerid_generate(unsigned char *buf, const char *name, const char *number, struct ast_format *codec); +/*! \brief Generate Caller-ID spill from the "callerid" field of asterisk (in e-mail address like format) + * \param buf buffer for output samples. See callerid_generate() for details regarding buffer. + * \param name Caller-ID Name + * \param number Caller-ID Number + * \param ddn Dialable Directory Number (or NULL) + * \param redirecting Redirecting Reason (-1 if N/A) + * \param pres Presentation (0 for default) + * \param qualifier Call Qualifier (0 for no, 1 for yes) + * \param format Message Format + * \param codec Asterisk codec (either AST_FORMAT_ALAW or AST_FORMAT_ULAW) + * + * \details + * Like ast_callerid_generate but with additional parameters. + */ +int ast_callerid_full_generate(unsigned char *buf, const char *name, const char *number, + const char *ddn, int redirecting, int pres, int qualifier, int format, struct ast_format *codec); + /*! * \brief Generate message waiting indicator * \param buf @@ -198,6 +241,12 @@ int ast_callerid_vmwi_generate(unsigned char *buf, int active, int type, struct */ int ast_callerid_callwaiting_generate(unsigned char *buf, const char *name, const char *number, struct ast_format *codec); +/*! \brief Generate Caller-ID spill but in a format suitable for Call Waiting(tm)'s Caller*ID(tm) + * \see ast_callerid_generate() for other details + */ +int ast_callerid_callwaiting_full_generate(unsigned char *buf, const char *name, const char *number, + const char *ddn, int redirecting, int pres, int qualifier, struct ast_format *codec); + /*! \brief Destructively parse inbuf into name and location (or number) * \details * Parses callerid stream from inbuf and changes into useable form, outputted in name and location. diff --git a/main/callerid.c b/main/callerid.c index 4d6186b3bccd4c93cea95b2cf6bf5cb8e45f24e3..c6c29a002a649ed7757f8401eaa8bf08b7863a4f 100644 --- a/main/callerid.c +++ b/main/callerid.c @@ -736,7 +736,8 @@ void callerid_free(struct callerid_state *cid) ast_free(cid); } -static int callerid_genmsg(char *msg, int size, const char *number, const char *name, int flags) +static int callerid_genmsg(char *msg, int size, const char *number, const char *name, int flags, int format, + const char *ddn, int redirecting) { struct timeval now = ast_tvnow(); struct ast_tm tm; @@ -754,6 +755,7 @@ static int callerid_genmsg(char *msg, int size, const char *number, const char * tm.tm_mday, tm.tm_hour, tm.tm_min); size -= res; ptr += res; + if (ast_strlen_zero(number) || (flags & CID_UNKNOWN_NUMBER)) { /* Indicate number not known */ res = snprintf(ptr, size, "\004\001O"); @@ -779,6 +781,11 @@ static int callerid_genmsg(char *msg, int size, const char *number, const char * size -= i; } + if (format == CID_TYPE_SDMF) { /* If Simple Data Message Format, we're done. */ + /* (some older Caller ID units only support SDMF. If they get an MDMF spill, it's useless.) */ + return (ptr - msg); + } + if (ast_strlen_zero(name) || (flags & CID_UNKNOWN_NAME)) { /* Indicate name not known */ res = snprintf(ptr, size, "\010\001O"); @@ -803,8 +810,44 @@ static int callerid_genmsg(char *msg, int size, const char *number, const char * ptr += i; size -= i; } - return (ptr - msg); + /* Call Qualifier */ + if (flags & CID_QUALIFIER) { + res = snprintf(ptr, size, "\006\001L"); /* LDC (Long Distance Call) is the only valid option */ + size -= res; + ptr += res; + } + + /* DDN (Dialable Directory Number) - 11 digits MAX, parameter 003 */ + /* some CPE seem to display the DDN instead of the CLID, if sent */ + + /* Redirecting Reason */ + if (redirecting >= 0) { + res = 0; + switch (redirecting) { + case AST_REDIRECTING_REASON_USER_BUSY: + res = snprintf(ptr, size, "\005\001\001"); + break; + case AST_REDIRECTING_REASON_NO_ANSWER: + res = snprintf(ptr, size, "\005\001\002"); + break; + case AST_REDIRECTING_REASON_UNCONDITIONAL: + res = snprintf(ptr, size, "\005\001\003"); + break; + case AST_REDIRECTING_REASON_CALL_FWD_DTE: + res = snprintf(ptr, size, "\005\001\004"); + break; + case AST_REDIRECTING_REASON_DEFLECTION: + res = snprintf(ptr, size, "\005\001\005"); + break; + default: + break; + } + ptr += res; + size -= res; + } + + return (ptr - msg); } int ast_callerid_vmwi_generate(unsigned char *buf, int active, int type, struct ast_format *codec, @@ -824,7 +867,7 @@ int ast_callerid_vmwi_generate(unsigned char *buf, int active, int type, struct msg[0] = 0x82; /* put date, number info at the right place */ - len = callerid_genmsg(msg+2, sizeof(msg)-2, number, name, flags); + len = callerid_genmsg(msg+2, sizeof(msg)-2, number, name, flags, CID_TYPE_MDMF, "", -1); /* length of MDMF CLI plus Message Waiting Structure */ msg[1] = len+3; @@ -896,6 +939,12 @@ int ast_callerid_vmwi_generate(unsigned char *buf, int active, int type, struct } int callerid_generate(unsigned char *buf, const char *number, const char *name, int flags, int callwaiting, struct ast_format *codec) +{ + return callerid_full_generate(buf, number, name, NULL, -1, flags, CID_TYPE_MDMF, callwaiting, codec); +} + +int callerid_full_generate(unsigned char *buf, const char *number, const char *name, const char *ddn, int redirecting, + int flags, int format, int callwaiting, struct ast_format *codec) { int bytes = 0; int x, sum; @@ -906,7 +955,7 @@ int callerid_generate(unsigned char *buf, const char *number, const char *name, float ci = 0.0; float scont = 0.0; char msg[256]; - len = callerid_genmsg(msg, sizeof(msg), number, name, flags); + len = callerid_genmsg(msg, sizeof(msg), number, name, flags, format, ddn, redirecting); if (!callwaiting) { /* Wait a half a second */ for (x = 0; x < 4000; x++) @@ -1051,23 +1100,56 @@ int ast_callerid_parse(char *input_str, char **name, char **location) return 0; } -static int __ast_callerid_generate(unsigned char *buf, const char *name, const char *number, int callwaiting, struct ast_format *codec) +static int __ast_callerid_generate(unsigned char *buf, const char *name, const char *number, + const char *ddn, int redirecting, int pres, int qualifier, int format, int callwaiting, struct ast_format *codec) { + int flags = 0; + + ast_debug(1, "Caller ID Type %s: Number: %s, Name: %s, Redirecting No: %s, Redirecting Reason: %s, Pres: %s, Qualifier: %s, Format: %s\n", + callwaiting ? "II" : "I", number, name, ddn, ast_redirecting_reason_describe(redirecting), + ast_named_caller_presentation(pres), qualifier ? "LDC" : "None", format == CID_TYPE_MDMF ? "MDMF" : "SDMF"); + if (ast_strlen_zero(name)) name = NULL; if (ast_strlen_zero(number)) number = NULL; - return callerid_generate(buf, number, name, 0, callwaiting, codec); + + if (pres & AST_PRES_RESTRICTED) { + flags |= CID_PRIVATE_NUMBER; + flags |= CID_PRIVATE_NAME; + } else if (pres & AST_PRES_UNAVAILABLE) { + flags |= CID_UNKNOWN_NUMBER; + flags |= CID_UNKNOWN_NAME; + } + + if (qualifier) { + flags |= CID_QUALIFIER; + } + + return callerid_full_generate(buf, number, name, ddn, redirecting, flags, format, callwaiting, codec); } int ast_callerid_generate(unsigned char *buf, const char *name, const char *number, struct ast_format *codec) { - return __ast_callerid_generate(buf, name, number, 0, codec); + return __ast_callerid_generate(buf, name, number, "", -1, 0, 0, CID_TYPE_MDMF, 0, codec); } int ast_callerid_callwaiting_generate(unsigned char *buf, const char *name, const char *number, struct ast_format *codec) { - return __ast_callerid_generate(buf, name, number, 1, codec); + return __ast_callerid_generate(buf, name, number, "", -1, 0, 0, CID_TYPE_MDMF, 1, codec); +} + +int ast_callerid_full_generate(unsigned char *buf, const char *name, const char *number, + const char *ddn, int redirecting, int pres, int qualifier, int format, struct ast_format *codec) +{ + return __ast_callerid_generate(buf, name, number, ddn, redirecting, pres, qualifier, format, 0, codec); +} + +int ast_callerid_callwaiting_full_generate(unsigned char *buf, const char *name, const char *number, + const char *ddn, int redirecting, int pres, int qualifier, struct ast_format *codec) +{ + /* Type II Caller ID (CWCID) only uses MDMF, so format isn't an argument */ + return __ast_callerid_generate(buf, name, number, ddn, redirecting, pres, qualifier, CID_TYPE_MDMF, 1, codec); } char *ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)