Codename Pineapple

Home page | Mailing list | Docs

Last updated: Sat Feb 3 05:01:02 2007

Asterisk developer's documentation :: Codename Pineapple


callerid.c File Reference


Detailed Description

CallerID Generation support.

Author:
Mark Spencer <markster@digium.com>

Definition in file callerid.c.

#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 + #.
const char * ast_named_caller_presentation (int data)
 Convert caller ID pres value to text code.
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 {
   int   alarm
   const char *   description
   unsigned int   event_log:1
   char *   ext
   char *   mtype
   char *   name
   const char *   name
   rtpPayloadType   payloadType
   unsigned int   queue_log:1
   char *   subtype
   char *   type
   int   val
pres_types []
 Translation table for Caller ID Presentation settings.
float sasdi
float sasdr


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 980 of file callerid.c.

References ast_strlen_zero(), and callerid_generate().

Referenced by ast_callerid_callwaiting_generate(), and ast_callerid_generate().

00981 {
00982    if (ast_strlen_zero(name))
00983       name = NULL;
00984    if (ast_strlen_zero(number))
00985       number = NULL;
00986    return callerid_generate(buf, number, name, 0, callwaiting, codec);
00987 }

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 994 of file callerid.c.

References __ast_callerid_generate().

Referenced by send_cwcidspill().

00995 {
00996    return __ast_callerid_generate(buf, name, number, 1, codec);
00997 }

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 989 of file callerid.c.

References __ast_callerid_generate().

Referenced by zt_call().

00990 {
00991    return __ast_callerid_generate(buf, name, number, 0, codec);
00992 }

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

Definition at line 999 of file callerid.c.

Referenced by _sip_show_device(), _sip_show_peer(), iax2_show_peer(), and sip_show_user().

01000 {
01001    if (!unknown)
01002       unknown = "<unknown>";
01003    if (name && num)
01004       snprintf(buf, bufsiz, "\"%s\" <%s>", name, num);
01005    else if (name) 
01006       ast_copy_string(buf, name, bufsiz);
01007    else if (num)
01008       ast_copy_string(buf, num, bufsiz);
01009    else
01010       ast_copy_string(buf, unknown, bufsiz);
01011    return buf;
01012 }

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. XXX note that '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 942 of file callerid.c.

References ast_isphonenumber(), and ast_shrink_phone_number().

Referenced by action_originate(), ast_callerid_split(), ast_privacy_check(), ast_privacy_set(), and handle_setcallerid().

00943 {
00944    char *ns, *ne, *ls, *le;
00945 
00946    /* Try "name" <location> format or name <location> format */
00947    if ((ls = strchr(instr, '<')) && (le = strchr(ls, '>'))) {
00948       *ls = *le = '\0'; /* location found, trim off the brackets */
00949       *location = ls + 1;  /* and this is the result */
00950       if ((ns = strchr(instr, '"')) && (ne = strchr(ns + 1, '"'))) {
00951          *ns = *ne = '\0'; /* trim off the quotes */
00952          *name = ns + 1;      /* and this is the name */
00953       } else { /* no quotes, trim off leading and trailing spaces */
00954          *name = ast_skip_blanks(instr);
00955          ast_trim_blanks(*name);
00956       }
00957    } else { /* no valid brackets */
00958       char tmp[256];
00959 
00960       ast_copy_string(tmp, instr, sizeof(tmp));
00961       ast_shrink_phone_number(tmp);
00962       if (ast_isphonenumber(tmp)) { /* Assume it's just a location */
00963          *name = NULL;
00964          strcpy(instr, tmp); /* safe, because tmp will always be the same size or smaller than instr */
00965          *location = instr;
00966       } else { /* Assume it's just a name. */
00967          *location = NULL;
00968          if ((ns = strchr(instr, '"')) && (ne = strchr(ns + 1, '"'))) {
00969             *ns = *ne = '\0'; /* trim off the quotes */
00970             *name = ns + 1;      /* and this is the name */
00971          } else { /* no quotes, trim off leading and trailing spaces */
00972             *name = ast_skip_blanks(instr);
00973             ast_trim_blanks(*name);
00974          }
00975       }
00976    }
00977    return 0;
00978 }

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

Definition at line 1014 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(), load_module(), set_device_cid(), store_callerid(), and update_common_options().

01015 {
01016    char *tmp;
01017    char *l = NULL, *n = NULL;
01018 
01019    tmp = ast_strdupa(buf);
01020    ast_callerid_parse(tmp, &n, &l);
01021    if (n)
01022       ast_copy_string(name, n, namelen);
01023    else
01024       name[0] = '\0';
01025    if (l) {
01026       ast_shrink_phone_number(l);
01027       ast_copy_string(num, l, numlen);
01028    } else
01029       num[0] = '\0';
01030    return 0;
01031 }

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 1071 of file callerid.c.

References pres_types.

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

01072 {
01073    int i;
01074 
01075    for (i = 0; i < ((sizeof(pres_types) / sizeof(pres_types[0]))); i++) {
01076       if (pres_types[i].val == data)
01077          return pres_types[i].description;
01078    }
01079 
01080    return "unknown";
01081 }

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 casdi1, casdi2, casdr1, casdr2, gen_tone(), gen_tones(), callerid_state::pos, sasdi, and sasdr.

Referenced by __adsi_transmit_messages(), and zt_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 
00244    if (sendsas) {
00245       if (len < saslen)
00246          return -1;
00247       gen_tone(outbuf, saslen, codec, sasdr, sasdi, &cr1, &ci1);
00248       len -= saslen;
00249       pos += saslen;
00250       cr2 = cr1;
00251       ci2 = ci1;
00252    }
00253    gen_tones(outbuf + pos, len, codec, casdr1, casdi1, casdr2, casdi2, &cr1, &ci1, &cr2, &ci2);
00254    return 0;
00255 }

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 927 of file callerid.c.

References ast_is_valid_string().

Referenced by check_peer_ok(), check_user_full(), check_user_ok(), and replace_cid().

00928 {
00929    return ast_is_valid_string(exten, "0123456789*#+()-.");
00930 }

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 901 of file callerid.c.

References ast_strlen_zero().

Referenced by ast_is_shrinkable_phonenumber(), and ast_isphonenumber().

00902 {
00903    int x;
00904 
00905    if (ast_strlen_zero(exten))
00906       return 0;
00907    for (x = 0; exten[x]; x++)
00908       if (!strchr(valid, exten[x]))
00909          return 0;
00910    return 1;
00911 }

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 917 of file callerid.c.

References ast_is_valid_string().

Referenced by ast_callerid_parse().

00918 {
00919    return ast_is_valid_string(n, "0123456789*#+");
00920 }

const char* ast_named_caller_presentation int  data  ) 
 

Convert caller ID pres value to text code.

Parameters:
data text string
Returns:
string for config file

Definition at line 1087 of file callerid.c.

References pres_types.

01088 {
01089    int i;
01090 
01091    for (i = 0; i < ((sizeof(pres_types) / sizeof(pres_types[0]))); i++) {
01092       if (pres_types[i].val == data)
01093          return pres_types[i].name;
01094    }
01095 
01096    return "unknown";
01097 }

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 1055 of file callerid.c.

References name, and pres_types.

Referenced by build_device(), and build_peer().

01056 {
01057    int i;
01058 
01059    for (i = 0; i < ((sizeof(pres_types) / sizeof(pres_types[0]))); i++) {
01060       if (!strcasecmp(pres_types[i].name, data))
01061          return pres_types[i].val;
01062    }
01063 
01064    return -1;
01065 }

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 865 of file callerid.c.

Referenced by action_originate(), ast_callerid_parse(), ast_callerid_split(), ast_privacy_check(), ast_privacy_set(), check_access(), check_peer_ok(), check_user_full(), check_user_ok(), handle_setcallerid(), and replace_cid().

00866 {
00867    int x, y=0;
00868    int bracketed = 0;
00869 
00870    for (x = 0; n[x]; x++) {
00871       switch (n[x]) {
00872       case '[':
00873          bracketed++;
00874          n[y++] = n[x];
00875          break;
00876       case ']':
00877          bracketed--;
00878          n[y++] = n[x];
00879          break;
00880       case '-':
00881          if (bracketed)
00882             n[y++] = n[x];
00883          break;
00884       case '.':
00885          if (!n[x+1])
00886             n[y++] = n[x];
00887          break;
00888       default:
00889          if (!strchr("()", n[x]))
00890             n[y++] = n[x];
00891       }
00892    }
00893    n[y] = '\0';
00894 }

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

Definition at line 257 of file callerid.c.

References org.

Referenced by callerid_feed_jp().

00258 {
00259    unsigned int i, j, org, dst;
00260    org = data;
00261    dst = 0;
00262 
00263    for (i = 0; i < CHAR_BIT; i++) {
00264       org <<= 1;
00265       dst >>= 1;
00266       if (org & 0x100) 
00267          dst |= 0x80;
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 523 of file callerid.c.

References ast_log(), ast_strlen_zero(), AST_XLAW, callerid_state::cksum, fsk_serial(), 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().

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

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_log(), AST_XLAW, calc_crc(), CID_UNKNOWN_NUMBER, callerid_state::crc, callerid_state::flags, fsk_serial(), 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 
00290    buf = alloca(2 * len + cid->oldlen);
00291 
00292    memcpy(buf, cid->oldstuff, cid->oldlen);
00293    mylen += cid->oldlen / 2;
00294 
00295    for (x = 0; x < len; x++) 
00296       buf[x+cid->oldlen/2] = AST_XLAW(ubuf[x]);
00297 
00298    while (mylen >= 160) {
00299       b = b2 = 0;
00300       olen = mylen;
00301       res = fsk_serial(&cid->fskd, buf, &mylen, &b);
00302 
00303       if (mylen < 0) {
00304          ast_log(LOG_ERROR, "fsk_serial made mylen < 0 (%d)\n", mylen);
00305          return -1;
00306       }
00307 
00308       buf += (olen - mylen);
00309 
00310       if (res < 0) {
00311          ast_log(LOG_NOTICE, "fsk_serial failed\n");
00312          return -1;
00313       }
00314 
00315       if (res == 1) {
00316          b2 = b;
00317          b  &= 0x7f;
00318 
00319          /* crc checksum calculation */
00320          if (cid->sawflag > 1)
00321             cid->crc = calc_crc(cid->crc, (unsigned char) b2);
00322 
00323          /* Ignore invalid bytes */
00324          if (b > 0xff)
00325             continue;
00326 
00327          /* skip DLE if needed */
00328          if (cid->sawflag > 0) {
00329             if (cid->sawflag != 5 && cid->skipflag == 0 && b == 0x10) {
00330                cid->skipflag = 1 ;
00331                continue ;
00332             }
00333          }
00334          if (cid->skipflag == 1)
00335             cid->skipflag = 0 ;
00336 
00337          /* caller id retrieval */
00338          switch (cid->sawflag) {
00339          case 0: /* DLE */
00340             if (b == 0x10) {
00341                cid->sawflag = 1;
00342                cid->skipflag = 0;
00343                cid->crc = 0;
00344             }
00345             break;
00346          case 1: /* SOH */
00347             if (b == 0x01) 
00348                cid->sawflag = 2;
00349             break ;
00350          case 2: /* HEADER */
00351             if (b == 0x07) 
00352                cid->sawflag = 3;
00353             break;
00354          case 3: /* STX */
00355             if (b == 0x02) 
00356                cid->sawflag = 4;
00357             break;
00358          case 4: /* SERVICE TYPE */
00359             if (b == 0x40) 
00360                cid->sawflag = 5;
00361             break;
00362          case 5: /* Frame Length */
00363             cid->sawflag = 6;
00364             break;   
00365          case 6: /* NUMBER TYPE */
00366             cid->sawflag = 7;
00367             cid->pos = 0;
00368             cid->rawdata[cid->pos++] = b;
00369             break;
00370          case 7:  /* NUMBER LENGTH */
00371             cid->sawflag = 8;
00372             cid->len = b;
00373             if ((cid->len+2) >= sizeof(cid->rawdata)) {
00374                ast_log(LOG_WARNING, "too long caller id string\n") ;
00375                return -1;
00376             }
00377             cid->rawdata[cid->pos++] = b;
00378             break;
00379          case 8:  /* Retrieve message */
00380             cid->rawdata[cid->pos++] = b;
00381             cid->len--;
00382             if (cid->len<=0) {
00383                cid->rawdata[cid->pos] = '\0';
00384                cid->sawflag = 9;
00385             }
00386             break;
00387          case 9:  /* ETX */
00388             cid->sawflag = 10;
00389             break;
00390          case 10: /* CRC Checksum 1 */
00391             cid->sawflag = 11;
00392             break;
00393          case 11: /* CRC Checksum 2 */
00394             cid->sawflag = 12;
00395             if (cid->crc != 0) {
00396                ast_log(LOG_WARNING, "crc checksum error\n") ;
00397                return -1;
00398             } 
00399             /* extract caller id data */
00400             for (x = 0; x < cid->pos;) {
00401                switch (cid->rawdata[x++]) {
00402                case 0x02: /* caller id  number */
00403                   cid->number[0] = '\0';
00404                   cid->name[0] = '\0';
00405                   cid->flags = 0;
00406                   res = cid->rawdata[x++];
00407                   ast_copy_string(cid->number, &cid->rawdata[x], res+1);
00408                   x += res;
00409                   break;
00410                case 0x21: /* additional information */
00411                   /* length */
00412                   x++; 
00413                   /* number type */
00414                                     switch (cid->rawdata[x]) { 
00415                   case 0x00: /* unknown */
00416                   case 0x01: /* international number */
00417                   case 0x02: /* domestic number */
00418                   case 0x03: /* network */
00419                   case 0x04: /* local call */
00420                   case 0x06: /* short dial number */
00421                   case 0x07: /* reserved */
00422                   default:   /* reserved */
00423                      if (option_debug > 1)
00424                         ast_log(LOG_DEBUG, "cid info:#1=%X\n", cid->rawdata[x]);
00425                      break ;
00426                   }
00427                   x++;