Sat Nov 1 06:28:50 2008

Asterisk developer's documentation


callerid.c File Reference

CallerID Generation support. More...

#include "asterisk.h"
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include <ctype.h>
#include "asterisk/ulaw.h"
#include "asterisk/alaw.h"
#include "asterisk/frame.h"
#include "asterisk/channel.h"
#include "asterisk/callerid.h"
#include "asterisk/logger.h"
#include "asterisk/fskmodem.h"
#include "asterisk/options.h"
#include "asterisk/utils.h"

Include dependency graph for callerid.c:

Go to the source code of this file.

Data Structures

struct  callerid_state

Defines

#define AST_CALLERID_UNKNOWN   "<unknown>"
#define CALLERID_MARK   1200.0
#define CALLERID_SPACE   2200.0
#define CAS_FREQ1   2130.0
#define CAS_FREQ2   2750.0
#define SAS_FREQ   440.0

Functions

static int __ast_callerid_generate (unsigned char *buf, const char *name, const char *number, int callwaiting, int codec)
int ast_callerid_callwaiting_generate (unsigned char *buf, const char *name, const char *number, int codec)
 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_generate (unsigned char *buf, const char *name, const char *number, int codec)
 Generate Caller-ID spill from the "callerid" field of asterisk (in e-mail address like format).
char * ast_callerid_merge (char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
int ast_callerid_parse (char *instr, char **name, char **location)
 Destructively parse inbuf into name and location (or number) Parses callerid stream from inbuf and changes into useable form, outputed in name and location.
int ast_callerid_split (const char *buf, char *name, int namelen, char *num, int numlen)
const char * ast_describe_caller_presentation (int data)
 Convert caller ID pres value to explanatory string.
int ast_gen_cas (unsigned char *outbuf, int sendsas, int len, int codec)
int ast_is_shrinkable_phonenumber (const char *exten)
 Check if a string consists only of digits and and + # ( ) - . (meaning it can be cleaned with ast_shrink_phone_number).
static int ast_is_valid_string (const char *exten, const char *valid)
 Checks if phone number consists of valid characters.
int ast_isphonenumber (const char *n)
 Check if a string consists only of digits and + #.
int ast_parse_caller_presentation (const char *data)
 Convert caller ID text code to value used in config file parsing.
void ast_shrink_phone_number (char *n)
 Shrink a phone number in place to just digits (more accurately it just removes ()'s, .'s, and -'s...
static unsigned short calc_crc (unsigned short crc, unsigned char data)
int callerid_feed (struct callerid_state *cid, unsigned char *ubuf, int len, int codec)
 Read samples into the state machine.
int callerid_feed_jp (struct callerid_state *cid, unsigned char *ubuf, int len, int codec)
 Read samples into the state machine.
void callerid_free (struct callerid_state *cid)
 Free a callerID state.
int callerid_generate (unsigned char *buf, const char *number, const char *name, int flags, int callwaiting, int codec)
 Generates a CallerID FSK stream in ulaw format suitable for transmission.
static int callerid_genmsg (char *msg, int size, const char *number, const char *name, int flags)
void callerid_get (struct callerid_state *cid, char **name, char **number, int *flags)
 Extract info out of callerID state machine. Flags are listed above.
void callerid_get_dtmf (char *cidstring, char *number, int *flags)
void callerid_init (void)
 CallerID Initialization.
callerid_statecallerid_new (int cid_signalling)
 Create a callerID state machine.
static void gen_tone (unsigned char *buf, int len, int codec, float ddr1, float ddi1, float *cr1, float *ci1)
static void gen_tones (unsigned char *buf, int len, int codec, float ddr1, float ddi1, float ddr2, float ddi2, float *cr1, float *ci1, float *cr2, float *ci2)
int vmwi_generate (unsigned char *buf, int active, int mdmf, int codec)
 Generate message waiting indicator (stutter tone).

Variables

float casdi1
float casdi2
float casdr1
float casdr2
float cid_di [4]
float cid_dr [4]
float clidsb = 8000.0 / 1200.0
struct {
   char *   description
   char *   name
   int   val
pres_types []
 Translation table for Caller ID Presentation settings.
float sasdi
float sasdr


Detailed Description

CallerID Generation support.

Author:
Mark Spencer <markster@digium.com>

Definition in file callerid.c.


Define Documentation

#define AST_CALLERID_UNKNOWN   "<unknown>"

Definition at line 78 of file callerid.c.

#define CALLERID_MARK   1200.0

1200 hz for "1"

Definition at line 73 of file callerid.c.

Referenced by callerid_init().

#define CALLERID_SPACE   2200.0

2200 hz for "0"

Definition at line 72 of file callerid.c.

Referenced by callerid_init().

#define CAS_FREQ1   2130.0

Definition at line 75 of file callerid.c.

Referenced by callerid_init().

#define CAS_FREQ2   2750.0

Definition at line 76 of file callerid.c.

Referenced by callerid_init().

#define SAS_FREQ   440.0

Definition at line 74 of file callerid.c.

Referenced by callerid_init().


Function Documentation

static int __ast_callerid_generate ( unsigned char *  buf,
const char *  name,
const char *  number,
int  callwaiting,
int  codec 
) [static]

Definition at line 1008 of file callerid.c.

References ast_strlen_zero(), and callerid_generate().

Referenced by ast_callerid_callwaiting_generate(), and ast_callerid_generate().

01009 {
01010    if (ast_strlen_zero(name))
01011       name = NULL;
01012    if (ast_strlen_zero(number))
01013       number = NULL;
01014    return callerid_generate(buf, number, name, 0, callwaiting, codec);
01015 }

int ast_callerid_callwaiting_generate ( unsigned char *  buf,
const char *  name,
const char *  number,
int  codec 
)

Generate Caller-ID spill but in a format suitable for Call Waiting(tm)'s Caller*ID(tm) See ast_callerid_generate() for other details.

Definition at line 1022 of file callerid.c.

References __ast_callerid_generate().

Referenced by send_cwcidspill().

01023 {
01024    return __ast_callerid_generate(buf, name, number, 1, codec);
01025 }

int ast_callerid_generate ( unsigned char *  buf,
const char *  name,
const char *  number,
int  codec 
)

Generate Caller-ID spill from the "callerid" field of asterisk (in e-mail address like format).

Parameters:
buf buffer for output samples. See callerid_generate() for details regarding buffer.
name Caller-ID Name
number Caller-ID Number
codec Asterisk codec (either AST_FORMAT_ALAW or AST_FORMAT_ULAW)
Acts like callerid_generate except uses an asterisk format callerid string.

Definition at line 1017 of file callerid.c.

References __ast_callerid_generate().

Referenced by dahdi_call().

01018 {
01019    return __ast_callerid_generate(buf, name, number, 0, codec);
01020 }

char* ast_callerid_merge ( char *  buf,
int  bufsiz,
const char *  name,
const char *  num,
const char *  unknown 
)

Definition at line 1027 of file callerid.c.

Referenced by _sip_show_peer(), iax2_show_peer(), leave_voicemail(), prep_email_sub_vars(), and sip_show_user().

01028 {
01029    if (!unknown)
01030       unknown = "<unknown>";
01031    if (name && num)
01032       snprintf(buf, bufsiz, "\"%s\" <%s>", name, num);
01033    else if (name) 
01034       ast_copy_string(buf, name, bufsiz);
01035    else if (num)
01036       ast_copy_string(buf, num, bufsiz);
01037    else
01038       ast_copy_string(buf, unknown, bufsiz);
01039    return buf;
01040 }

int ast_callerid_parse ( char *  instr,
char **  name,
char **  location 
)

Destructively parse inbuf into name and location (or number) Parses callerid stream from inbuf and changes into useable form, outputed in name and location.

Returns:
always returns 0, as the code always returns something.
Note:
XXX 'name' is not parsed consistently e.g. we have input location name " foo bar " <123> 123 ' foo bar ' (with spaces around) " foo bar " NULL 'foo bar' (without spaces around) " foo bar <123>" 123 '" foo bar' The parsing of leading and trailing space/quotes should be more consistent.

Definition at line 970 of file callerid.c.

References ast_isphonenumber(), and ast_shrink_phone_number().

Referenced by action_originate(), advanced_options(), ast_callerid_split(), ast_privacy_check(), ast_privacy_set(), handle_setcallerid(), misdn_new(), play_message_callerid(), rpt_call(), and write_metadata().

00971 {
00972    char *ns, *ne, *ls, *le;
00973 
00974    /* Try "name" <location> format or name <location> format */
00975    if ((ls = strchr(instr, '<')) && (le = strchr(ls, '>'))) {
00976       *ls = *le = '\0'; /* location found, trim off the brackets */
00977       *location = ls + 1;  /* and this is the result */
00978       if ((ns = strchr(instr, '"')) && (ne = strchr(ns + 1, '"'))) {
00979          *ns = *ne = '\0'; /* trim off the quotes */
00980          *name = ns + 1;      /* and this is the name */
00981       } else { /* no quotes, trim off leading and trailing spaces */
00982          *name = ast_skip_blanks(instr);
00983          ast_trim_blanks(*name);
00984       }
00985    } else { /* no valid brackets */
00986       char tmp[256];
00987 
00988       ast_copy_string(tmp, instr, sizeof(tmp));
00989       ast_shrink_phone_number(tmp);
00990       if (ast_isphonenumber(tmp)) { /* Assume it's just a location */
00991          *name = NULL;
00992          strcpy(instr, tmp); /* safe, because tmp will always be the same size or smaller than instr */
00993          *location = instr;
00994       } else { /* Assume it's just a name. */
00995          *location = NULL;
00996          if ((ns = strchr(instr, '"')) && (ne = strchr(ns + 1, '"'))) {
00997             *ns = *ne = '\0'; /* trim off the quotes */
00998             *name = ns + 1;      /* and this is the name */
00999          } else { /* no quotes, trim off leading and trailing spaces */
01000             *name = ast_skip_blanks(instr);
01001             ast_trim_blanks(*name);
01002          }
01003       }
01004    }
01005    return 0;
01006 }

int ast_callerid_split ( const char *  buf,
char *  name,
int  namelen,
char *  num,
int  numlen 
)

Definition at line 1042 of file callerid.c.

References ast_callerid_parse(), ast_shrink_phone_number(), and ast_strdupa.

Referenced by apply_outgoing(), build_device(), build_gateway(), build_peer(), build_user(), callerid_read(), callerid_write(), disa_exec(), load_module(), process_dahdi(), setcallerid_exec(), store_callerid(), and update_common_options().

01043 {
01044    char *tmp;
01045    char *l = NULL, *n = NULL;
01046 
01047    tmp = ast_strdupa(buf);
01048    ast_callerid_parse(tmp, &n, &l);
01049    if (n)
01050       ast_copy_string(name, n, namelen);
01051    else
01052       name[0] = '\0';
01053    if (l) {
01054       ast_shrink_phone_number(l);
01055       ast_copy_string(num, l, numlen);
01056    } else
01057       num[0] = '\0';
01058    return 0;
01059 }

const char* ast_describe_caller_presentation ( int  data  ) 

Convert caller ID pres value to explanatory string.

Parameters:
data value (see callerid.h AST_PRES_ )
Returns:
string for human presentation

Definition at line 1099 of file callerid.c.

References pres_types.

Referenced by _sip_show_peer(), ast_set_callerid(), and sip_show_user().

01100 {
01101    int i;
01102 
01103    for (i = 0; i < ((sizeof(pres_types) / sizeof(pres_types[0]))); i++) {
01104       if (pres_types[i].val == data)
01105          return pres_types[i].description;
01106    }
01107 
01108    return "unknown";
01109 }

int ast_gen_cas ( unsigned char *  outbuf,
int  sas,
int  len,
int  codec 
)

Parameters:
outbuf Allocated buffer for data. Must be at least 2400 bytes unless no SAS is desired
sas Non-zero if CAS should be preceeded by SAS
len How many samples to generate.
codec Which codec (AST_FORMAT_ALAW or AST_FORMAT_ULAW)
Returns:
Returns -1 on error (if len is less than 2400), 0 on success.

Definition at line 235 of file callerid.c.

References gen_tone(), gen_tones(), and callerid_state::pos.

Referenced by __adsi_transmit_messages(), and dahdi_callwait().

00236 {
00237    int pos = 0;
00238    int saslen=2400;
00239    float cr1 = 1.0;
00240    float ci1 = 0.0;
00241    float cr2 = 1.0;
00242    float ci2 = 0.0;
00243    if (sendsas) {
00244       if (len < saslen)
00245          return -1;
00246       gen_tone(outbuf, saslen, codec, sasdr, sasdi, &cr1, &ci1);
00247       len -= saslen;
00248       pos += saslen;
00249       cr2 = cr1;
00250       ci2 = ci1;
00251    }
00252    gen_tones(outbuf + pos, len, codec, casdr1, casdi1, casdr2, casdi2, &cr1, &ci1, &cr2, &ci2);
00253    return 0;
00254 }

int ast_is_shrinkable_phonenumber ( const char *  exten  ) 

Check if a string consists only of digits and and + # ( ) - . (meaning it can be cleaned with ast_shrink_phone_number).

Returns:
1 if string is valid AST shrinkable phone number

0 if not

Definition at line 955 of file callerid.c.

References ast_is_valid_string().

Referenced by check_user_full().

00956 {
00957    return ast_is_valid_string(exten, "0123456789*#+()-.");
00958 }

static int ast_is_valid_string ( const char *  exten,
const char *  valid 
) [static]

Checks if phone number consists of valid characters.

Parameters:
exten String that needs to be checked
valid Valid characters in string
Returns:
1 if valid string, 0 if string contains invalid characters

Definition at line 929 of file callerid.c.

References ast_strlen_zero().

Referenced by ast_is_shrinkable_phonenumber(), and ast_isphonenumber().

00930 {
00931    int x;
00932 
00933    if (ast_strlen_zero(exten))
00934       return 0;
00935    for (x=0; exten[x]; x++)
00936       if (!strchr(valid, exten[x]))
00937          return 0;
00938    return 1;
00939 }

int ast_isphonenumber ( const char *  n  ) 

Check if a string consists only of digits and + #.

Returns:
1 if string is valid AST phone number

0 if not

Definition at line 945 of file callerid.c.

References ast_is_valid_string().

Referenced by ast_callerid_parse().

00946 {
00947    return ast_is_valid_string(n, "0123456789*#+");
00948 }

int ast_parse_caller_presentation ( const char *  data  ) 

Convert caller ID text code to value used in config file parsing.

Parameters:
data text string
Returns:
value AST_PRES_ from callerid.h

Definition at line 1083 of file callerid.c.

References name, and pres_types.

Referenced by build_peer(), build_user(), and setcallerid_pres_exec().

01084 {
01085    int i;
01086 
01087    for (i = 0; i < ((sizeof(pres_types) / sizeof(pres_types[0]))); i++) {
01088       if (!strcasecmp(pres_types[i].name, data))
01089          return pres_types[i].val;
01090    }
01091 
01092    return -1;
01093 }

void ast_shrink_phone_number ( char *  n  ) 

Shrink a phone number in place to just digits (more accurately it just removes ()'s, .'s, and -'s...

Parameters:
n The number to be stripped/shrunk
Returns:
Returns nothing important

Definition at line 893 of file callerid.c.

Referenced by action_originate(), ast_callerid_parse(), ast_callerid_split(), ast_privacy_check(), ast_privacy_set(), check_access(), check_user_full(), handle_setcallerid(), pbx_load_config(), and write_metadata().

00894 {
00895    int x, y=0;
00896    int bracketed = 0;
00897 
00898    for (x=0; n[x]; x++) {
00899       switch(n[x]) {
00900       case '[':
00901          bracketed++;
00902          n[y++] = n[x];
00903          break;
00904       case ']':
00905          bracketed--;
00906          n[y++] = n[x];
00907          break;
00908       case '-':
00909          if (bracketed)
00910             n[y++] = n[x];
00911          break;
00912       case '.':
00913          if (!n[x+1])
00914             n[y++] = n[x];
00915          break;
00916       default:
00917          if (!strchr("( )", n[x]))
00918             n[y++] = n[x];
00919       }
00920    }
00921    n[y] = '\0';
00922 }

static unsigned short calc_crc ( unsigned short  crc,
unsigned char  data 
) [static]

Definition at line 256 of file callerid.c.

References org.

Referenced by callerid_feed_jp().

00257 {
00258    unsigned int i, j, org, dst;
00259    org = data;
00260    dst = 0;
00261 
00262    for (i=0; i < CHAR_BIT; i++) {
00263       org <<= 1;
00264       dst >>= 1;
00265       if (org & 0x100) {
00266          dst |= 0x80;
00267       }
00268    }
00269    data = (unsigned char)dst;
00270    crc ^= (unsigned int)data << (16 - CHAR_BIT);
00271    for ( j=0; j<CHAR_BIT; j++ ) {
00272       if ( crc & 0x8000U )
00273          crc = (crc << 1) ^ 0x1021U ;
00274       else
00275          crc <<= 1 ;
00276    }
00277       return crc;
00278 }

int callerid_feed ( struct callerid_state cid,
unsigned char *  ubuf,
int  samples,
int  codec 
)

Read samples into the state machine.

Parameters:
cid Which state machine to act upon
ubuf containing your samples
samples number of samples contained within the buffer.
codec which codec (AST_FORMAT_ALAW or AST_FORMAT_ULAW)
Send received audio to the Caller*ID demodulator.
Returns:
Returns -1 on error, 0 for "needs more samples", and 1 if the CallerID spill reception is complete.

Definition at line 540 of file callerid.c.

References ast_calloc, ast_log(), ast_strlen_zero(), AST_XLAW, CID_PRIVATE_NAME, CID_PRIVATE_NUMBER, CID_UNKNOWN_NAME, CID_UNKNOWN_NUMBER, callerid_state::cksum, callerid_state::flags, free, fsk_serie(), callerid_state::fskd, callerid_state::len, LOG_ERROR, LOG_NOTICE, LOG_WARNING, callerid_state::name, callerid_state::number, callerid_state::oldlen, callerid_state::oldstuff, callerid_state::pos, callerid_state::rawdata, callerid_state::sawflag, and callerid_state::type.

Referenced by ss_thread().

00541 {
00542    int mylen = len;
00543    int olen;
00544    int b = 'X';
00545    int res;
00546    int x;
00547    short *buf;
00548    short *obuf;
00549 
00550    if (!(buf = ast_calloc(1, 2 * len + cid->oldlen))) {
00551       return -1;
00552    }
00553 
00554    obuf = buf;
00555    memcpy(buf, cid->oldstuff, cid->oldlen);
00556    mylen += cid->oldlen/2;
00557 
00558    for (x=0;x<len;x++) 
00559       buf[x+cid->oldlen/2] = AST_XLAW(ubuf[x]);
00560    while(mylen >= 160) {
00561       olen = mylen;
00562       res = fsk_serie(&cid->fskd, buf, &mylen, &b);
00563       if (mylen < 0) {
00564          ast_log(LOG_ERROR, "No start bit found in fsk data.\n");
00565          free(obuf);
00566          return -1;
00567       }
00568       buf += (olen - mylen);
00569       if (res < 0) {
00570          ast_log(LOG_NOTICE, "fsk_serie failed\n");
00571          free(obuf);
00572          return -1;
00573       }
00574       if (res == 1) {
00575          /* Ignore invalid bytes */
00576          if (b > 0xff)
00577             continue;
00578          switch(cid->sawflag) {
00579          case 0: /* Look for flag */
00580             if (b == 'U')
00581                cid->sawflag = 2;
00582             break;
00583          case 2: /* Get lead-in */
00584             if ((b == 0x04) || (b == 0x80)) {
00585                cid->type = b;
00586                cid->sawflag = 3;
00587                cid->cksum = b;
00588             }
00589             break;
00590          case 3:  /* Get length */
00591             /* Not a lead in.  We're ready  */
00592             cid->sawflag = 4;
00593             cid->len = b;
00594             cid->pos = 0;
00595             cid->cksum += b;
00596             break;
00597          case 4: /* Retrieve message */
00598             if (cid->pos >= 128) {
00599                ast_log(LOG_WARNING, "Caller ID too long???\n");
00600                free(obuf);
00601                return -1;
00602             }
00603             cid->rawdata[cid->pos++] = b;
00604             cid->len--;
00605             cid->cksum += b;
00606             if (!cid->len) {
00607                cid->rawdata[cid->pos] = '\0';
00608                cid->sawflag = 5;
00609             }
00610             break;
00611          case 5: /* Check checksum */
00612             if (b != (256 - (cid->cksum & 0xff))) {
00613                ast_log(LOG_NOTICE, "Caller*ID failed checksum\n");
00614                /* Try again */
00615                cid->sawflag = 0;
00616                break;
00617             }
00618       
00619             cid->number[0] = '\0';
00620             cid->name[0] = '\0';
00621             /* If we get this far we're fine.  */
00622             if (cid->type == 0x80) {
00623                /* MDMF */
00624                /* Go through each element and process */
00625                for (x=0;x< cid->pos;) {
00626                   switch(cid->rawdata[x++]) {
00627                   case 1:
00628                      /* Date */
00629                      break;
00630                   case 2: /* Number */
00631                   case 3: /* Number (for Zebble) */
00632                   case 4: /* Number */
00633                      res = cid->rawdata[x];
00634                      if (res > 32) {
00635                         ast_log(LOG_NOTICE, "Truncating long caller ID number from %d bytes to 32\n", cid->rawdata[x]);
00636                         res = 32; 
00637                      }
00638                      if (ast_strlen_zero(cid->number)) {
00639                         memcpy(cid->number, cid->rawdata + x + 1, res);
00640                         /* Null terminate */
00641                         cid->number[res] = '\0';
00642                      }
00643                      break;
00644                   case 6: /* Stentor Call Qualifier (ie. Long Distance call) */
00645                      break;
00646                   case 7: /* Name */
00647                   case 8: /* Name */
00648                      res = cid->rawdata[x];
00649                      if (res > 32) {
00650                         ast_log(LOG_NOTICE, "Truncating long caller ID name from %d bytes to 32\n", cid->rawdata[x]);
00651                         res = 32; 
00652                      }
00653                      memcpy(cid->name, cid->rawdata + x + 1, res);
00654                      cid->name[res] = '\0';
00655                      break;
00656                   case 17: /* UK: Call type, 1=Voice Call, 2=Ringback when free, 129=Message waiting  */
00657                   case 19: /* UK: Network message system status (Number of messages waiting) */
00658                   case 22: /* Something French */
00659                      break;
00660                   default:
00661                      ast_log(LOG_NOTICE, "Unknown IE %d\n", cid->rawdata[x-1]);
00662                   }
00663                   res = cid->rawdata[x];
00664                   if (0 > res){  /* Negative offset in the CID Spill */
00665                      ast_log(LOG_NOTICE, "IE %d has bad field length of %d at offset %d\n", cid->rawdata[x-1], cid->rawdata[x], x);
00666                      /* Try again */
00667                      cid->sawflag = 0;
00668                      break;   /* Exit the loop */
00669                   }
00670                   x += cid->rawdata[x];
00671                   x++;
00672                }
00673             } else {
00674                /* SDMF */
00675                ast_copy_string(cid->number, cid->rawdata + 8, sizeof(cid->number));
00676             }
00677             /* Update flags */
00678             cid->flags = 0;
00679             if (!strcmp(cid->number, "P")) {
00680                strcpy(cid->number, "");
00681                cid->flags |= CID_PRIVATE_NUMBER;
00682             } else if (!strcmp(cid->number, "O") || ast_strlen_zero(cid->number)) {
00683                strcpy(cid->number, "");
00684                cid->flags |= CID_UNKNOWN_NUMBER;
00685             }
00686             if (!strcmp(cid->name, "P")) {
00687                strcpy(cid->name, "");
00688                cid->flags |= CID_PRIVATE_NAME;
00689             } else if (!strcmp(cid->name, "O") || ast_strlen_zero(cid->name)) {
00690                strcpy(cid->name, "");
00691                cid->flags |= CID_UNKNOWN_NAME;
00692             }
00693             free(obuf);
00694             return 1;
00695             break;
00696          default:
00697             ast_log(LOG_ERROR, "Dunno what to do with a digit in sawflag %d\n", cid->sawflag);
00698          }
00699       }
00700    }
00701    if (mylen) {
00702       memcpy(cid->oldstuff, buf, mylen * 2);
00703       cid->oldlen = mylen * 2;
00704    } else
00705       cid->oldlen = 0;
00706    free(obuf);
00707    return 0;
00708 }

int callerid_feed_jp ( struct callerid_state cid,
unsigned char *  ubuf,
int  samples,
int  codec 
)

Read samples into the state machine.

Parameters:
cid Which state machine to act upon
ubuf containing your samples
samples number of samples contained within the buffer.
codec which codec (AST_FORMAT_ALAW or AST_FORMAT_ULAW)
Send received audio to the Caller*ID demodulator (for japanese style lines).
Returns:
Returns -1 on error, 0 for "needs more samples", and 1 if the CallerID spill reception is complete.

Definition at line 280 of file callerid.c.

References ast_calloc, ast_log(), AST_XLAW, calc_crc(), CID_UNKNOWN_NUMBER, callerid_state::crc, callerid_state::flags, free, fsk_serie(), callerid_state::fskd, callerid_state::len, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, callerid_state::name, callerid_state::number, callerid_state::oldlen, callerid_state::oldstuff, option_debug, callerid_state::pos, callerid_state::rawdata, callerid_state::sawflag, and callerid_state::skipflag.

Referenced by ss_thread().

00281 {
00282    int mylen = len;
00283    int olen;
00284    int b = 'X';
00285    int b2 ;
00286    int res;
00287    int x;
00288    short *buf;
00289    short *obuf;
00290 
00291    if (!(buf = ast_calloc(1, 2 * len + cid->oldlen))) {
00292       return -1;
00293    }
00294 
00295    obuf = buf;
00296    memcpy(buf, cid->oldstuff, cid->oldlen);
00297    mylen += cid->oldlen/2;
00298 
00299    for (x=0;x<len;x++) 
00300       buf[x+cid->oldlen/2] = AST_XLAW(ubuf[x]);
00301 
00302    while (mylen >= 160) {
00303       b = b2 = 0;
00304       olen = mylen;
00305       res = fsk_serie(&cid->fskd, buf, &mylen, &b);
00306 
00307       if (mylen < 0) {
00308          ast_log(LOG_ERROR, "No start bit found in fsk data.\n");
00309          free(obuf);
00310          return -1;
00311       }
00312 
00313       buf += (olen - mylen);
00314 
00315       if (res < 0) {
00316          ast_log(LOG_NOTICE, "fsk_serie failed\n");
00317          free(obuf);
00318          return -1;
00319       }
00320 
00321       if (res == 1) {
00322 
00323          b2 = b ;
00324          b  = b & 0x7f ;
00325 
00326          /* crc checksum calculation */
00327          if ( cid->sawflag > 1 ) {
00328             cid->crc = calc_crc(cid->crc, (unsigned char)b2);
00329          }
00330 
00331          /* Ignore invalid bytes */
00332          if (b > 0xff) {
00333             continue;
00334          }
00335 
00336          /* skip DLE if needed */
00337          if ( cid->sawflag > 0 ) {
00338             if ( cid->sawflag != 5 && cid->skipflag == 0 && b == 0x10 ) {
00339                cid->skipflag = 1 ;
00340                continue ;
00341             }
00342          }
00343          if ( cid->skipflag == 1 ) {
00344             cid->skipflag = 0 ;
00345          }
00346 
00347          /* caller id retrieval */
00348          switch(cid->sawflag) {
00349             case 0: /* DLE */
00350                if (b == 0x10) {
00351                   cid->sawflag = 1;
00352                   cid->skipflag = 0;
00353                   cid->crc = 0;
00354                }
00355                break;
00356             case 1: /* SOH */
00357                if (b == 0x01) {
00358                   cid->sawflag = 2;
00359                }
00360                break ;
00361             case 2: /* HEADER */
00362                if (b == 0x07) {
00363                   cid->sawflag = 3;
00364                }
00365                break;
00366             case 3: /* STX */
00367                if (b == 0x02) {
00368                   cid->sawflag = 4;
00369                }
00370                break;
00371             case 4: /* SERVICE TYPE */
00372                if (b == 0x40) {
00373                   cid->sawflag = 5;
00374                }
00375                break;
00376             case 5: /* Frame Length */
00377                cid->sawflag = 6;
00378                break;   
00379             case 6: /* NUMBER TYPE */
00380                cid->sawflag = 7;
00381                cid->pos = 0;
00382                cid->rawdata[cid->pos++] = b;
00383                break;
00384             case 7:  /* NUMBER LENGTH */
00385                cid->sawflag = 8;
00386                cid->len = b;
00387                if ( (cid->len+2) >= sizeof( cid->rawdata ) ) {
00388                   ast_log(LOG_WARNING, "too long caller id string\n" ) ;
00389                   free(obuf);
00390                   return -1;
00391                }
00392                cid->rawdata[cid->pos++] = b;
00393                break;
00394             case 8:  /* Retrieve message */
00395                cid->rawdata[cid->pos++] = b;
00396                cid->len--;
00397                if (cid->len<=0) {
00398                   cid->rawdata[cid->pos] = '\0';
00399                   cid->sawflag = 9;
00400                }
00401                break;
00402             case 9:  /* ETX */
00403                cid->sawflag = 10;
00404                break;
00405             case 10: /* CRC Checksum 1 */
00406                cid->sawflag = 11;
00407                break;
00408             case 11: /* CRC Checksum 2 */
00409                cid->sawflag = 12;
00410                if ( cid->crc != 0 ) {
00411                   ast_log(LOG_WARNING, "crc checksum error\n" ) ;
00412                   free(obuf);
00413                   return -1;
00414                } 
00415                /* extract caller id data */
00416                for (x=0; x<cid->pos; ) {
00417                   switch (cid->rawdata[x++]) {
00418                   case 0x02: /* caller id  number */
00419                      cid->number[0] = '\0';
00420                      cid->name[0] = '\0';
00421                      cid->flags = 0;
00422                      res = cid->rawdata[x++];
00423                      ast_copy_string(cid->number, &cid->rawdata[x], res+1 );
00424                      x += res;
00425                      break;
00426                   case 0x21: /* additional information */
00427                      /* length */
00428                      x++; 
00429                      /* number type */
00430                                        switch (cid->rawdata[x]) { 
00431                      case 0x00: /* unknown */
00432                      case 0x01: /* international number */
00433                      case 0x02: /* domestic number */
00434                      case 0x03: /* network */
00435                      case 0x04: /* local call */
00436                      case 0x06: /* short dial number */
00437                      case 0x07: /* reserved */
00438                      default:   /* reserved */
00439                         if (option_debug > 1)
00440                            ast_log(LOG_DEBUG, "cid info:#1=%X\n", cid->rawdata[x]);
00441                         break ;
00442                      }
00443                      x++; 
00444                      /* numbering plan octed 4 */
00445                      x++; 
00446                      /* numbering plan octed 5 */
00447                      switch (cid->rawdata[x]) { 
00448                      case 0x00: /* unknown */
00449                      case 0x01: /* recommendation E.164 ISDN */
00450                      case 0x03: /* recommendation X.121 */
00451                      case 0x04: /* telex dial plan */
00452                      case 0x08: /* domestic dial plan */
00453                      case 0x09: /* private dial plan */
00454                      case 0x05: /* reserved */
00455                      default:   /* reserved */
00456                         if (option_debug > 1)
00457                            ast_log(LOG_DEBUG, "cid info:#2=%X\n", cid->rawdata[x]);
00458                         break ;
00459                      }
00460                      x++; 
00461                      break ;
00462                   case 0x04: /* no callerid reason */
00463                      /* length */
00464                      x++; 
00465                      /* no callerid reason code */
00466                      switch (cid->rawdata[x]) {
00467                      case 'P': /* caller id denied by user */
00468                      case 'O': /* service not available */
00469                      case 'C': /* pay phone */
00470                      case 'S': /* service congested */
00471                                     cid->flags |= CID_UNKNOWN_NUMBER;
00472                         if (option_debug > 1)
00473                            ast_log(LOG_DEBUG, "no cid reason:%c\n",cid->rawdata[x]);
00474                         break ;
00475                      }
00476                      x++; 
00477                      break ;
00478                   case 0x09: /* dialed number */
00479                      /* length */
00480                      res = cid->rawdata[x++];
00481                      /* dialed number */
00482                      x += res;
00483                      break ;
00484                   case 0x22: /* dialed number additional information */
00485                      /* length */
00486                      x++;
00487                      /* number type */
00488                      switch (cid->rawdata[x]) {
00489                      case 0x00: /* unknown */
00490                      case 0x01: /* international number */
00491                      case 0x02: /* domestic number */
00492                      case 0x03: /* network */
00493                      case 0x04: /* local call */
00494                      case 0x06: /* short dial number */
00495                      case 0x07: /* reserved */
00496                      default</