From 93820c7b1970ab51552deeb444964b900522d5b0 Mon Sep 17 00:00:00 2001 From: kpfleming Date: Fri, 23 Jun 2006 15:11:45 +0000 Subject: add infrastructure for zaptel transcoders git-svn-id: http://svn.digium.com/svn/zaptel/trunk@1162 5390a7c7-147a-4af0-8ec9-7488f05a26cb --- zaptel.h | 206 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 178 insertions(+), 28 deletions(-) (limited to 'zaptel.h') diff --git a/zaptel.h b/zaptel.h index 55542f3..d8aae5e 100644 --- a/zaptel.h +++ b/zaptel.h @@ -34,15 +34,18 @@ #include "zconfig.h" #include #include +#include +#include + #ifdef CONFIG_ZAPATA_NET #include #endif + #ifdef CONFIG_ZAPATA_PPP #include #include #include #endif -#include #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) #define LINUX26 @@ -56,7 +59,9 @@ #include "ecdis.h" #include "fasthdlc.h" -#endif + +#endif /* __KERNEL__ */ + #ifdef CONFIG_DEVFS_FS #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) #include @@ -65,7 +70,6 @@ //#warning "Zaptel doesn't support DEVFS in post 2.4 kernels. Disabling DEVFS in zaptel" #endif #endif /* CONFIG_DEVFS_FS */ -#include #ifndef ELAST #define ELAST 500 @@ -635,6 +639,11 @@ struct zt_versioninfo { */ #define ZT_SETPOLARITY _IOW (ZT_CODE, 92, int) +/* + * Transcoder operations + */ +#define ZT_TRANSCODE_OP _IOWR(ZT_CODE, 93, int) + /* * Startup or Shutdown a span */ @@ -664,8 +673,59 @@ struct zt_versioninfo { #define ZT_TONEDETECT_ON (1 << 0) /* Detect tones */ #define ZT_TONEDETECT_MUTE (1 << 1) /* Mute audio in received channel */ +#define ZT_TRANSCODE_MAGIC 0x74a9c0de + +/* Operations */ +#define ZT_TCOP_RESET 1 /* Reset the channel state / codec selection */ +#define ZT_TCOP_TRANSCODE 2 /* Begin transcoding a block */ +#define ZT_TCOP_GETINFO 3 /* Get information (use zt_transcode_info) */ + +typedef struct zt_transcode_info { + unsigned int op; + unsigned int tcnum; + char name[80]; + unsigned int srcfmts; + unsigned int dstfmts; +} ZT_TRANSCODE_INFO; + +#define ZT_TCCONF_USETS (1 << 0) /* Use/update timestamp field */ +#define ZT_TCCONF_USESEQ (1 << 1) /* Use/update seqno field */ + +#define ZT_TCSTAT_DSTRDY (1 << 0) /* Destination data is ready */ +#define ZT_TCSTAT_DSTBUSY (1 << 1) /* Destination data is outstanding */ + +#define __ZT_TRANSCODE_BUFSIZ 16384 +#define ZT_TRANSCODE_HDRLEN 256 +#define ZT_TRANSCODE_BUFSIZ ((__ZT_TRANSCODE_BUFSIZ) - (ZT_TRANSCODE_HDRLEN)) +#define ZT_TRANSCODE_DSTOFFSET (((ZT_TRANSCODE_BUFSIZ) / 2) + ZT_TRANSCODE_HDRLEN) +#define ZT_TRANSCODE_SRCOFFSET (((ZT_TRANSCODE_BUFSIZ) / 2) + ZT_TRANSCODE_HDRLEN) + +typedef struct zt_transcode_header { + unsigned int srcfmt; /* See formats.h -- use TCOP_RESET when you change */ + unsigned int srcoffset; /* In bytes -- written by user */ + unsigned int srclen; /* In bytes -- written by user */ + unsigned int srctimestamp; /* In samples -- written by user (only used if ZT_TCCONF_USETS is set) */ + unsigned int srcseqno; /* In units -- written by user (only used if ZT_TCCONF_USESEQ is set) */ + + unsigned int dstfmt; /* See formats.h -- use TCOP_RESET when you change */ + unsigned int dstoffset; /* In bytes -- written by user */ + unsigned int dsttimestamp; /* In samples -- read by user */ + unsigned int dstseqno; /* In units -- read by user (only used if ZT_TCCONF_USESEQ is set) */ + unsigned int dstlen; /* In bytes -- read by user */ + unsigned int dstsamples; /* In timestamp units -- read by user */ + + unsigned int magic; /* Magic value -- ZT_TRANSCODE_MAGIC, read by user */ + unsigned int config; /* Read/write by user */ + unsigned int status; /* Read/write by user */ + + /* XXX: fix this to automatically calculate somehow */ + unsigned char userhdr[ZT_TRANSCODE_HDRLEN - (sizeof(unsigned int) * 14)]; /* Storage for user parameters */ + unsigned char srcdata[ZT_TRANSCODE_BUFSIZ / 2]; /* Storage of source data */ + unsigned char dstdata[ZT_TRANSCODE_BUFSIZ / 2]; /* Storage of destination data */ +} ZT_TRANSCODE_HEADER; + struct zt_ring_cadence { - int ringcadence [ZT_MAX_CADENCE]; + int ringcadence[ZT_MAX_CADENCE]; }; struct zt_tone_def_header { @@ -1321,6 +1381,33 @@ struct zt_span { #endif }; +struct zt_transcoder_channel { + void *pvt; + struct zt_transcoder *parent; + wait_queue_head_t ready; + int errorstatus; + int offset; + unsigned int flags; + unsigned int srcfmt; + unsigned int dstfmt; + struct zt_transcode_header *tch; +}; + +#define ZT_TC_FLAG_BUSY (1 << 0) +#define ZT_TC_FLAG_TRANSIENT (1 << 1) + + +struct zt_transcoder { + struct zt_transcoder *next; + char name[80]; + int numchannels; + unsigned int srcfmts; + unsigned int dstfmts; + int (*operation)(struct zt_transcoder_channel *channel, int op); + /* Transcoder channels */ + struct zt_transcoder_channel channels[0]; +}; + #define ZT_WATCHDOG_NOINTS (1 << 0) #define ZT_WATCHDOG_INIT 1000 @@ -1354,67 +1441,100 @@ struct zt_dynamic_driver { }; /* Receive a dynamic span message */ -extern void zt_dynamic_receive(struct zt_span *span, unsigned char *msg, int msglen); +void zt_dynamic_receive(struct zt_span *span, unsigned char *msg, int msglen); /* Register a dynamic driver */ -extern int zt_dynamic_register(struct zt_dynamic_driver *driver); +int zt_dynamic_register(struct zt_dynamic_driver *driver); /* Unregister a dynamic driver */ -extern void zt_dynamic_unregister(struct zt_dynamic_driver *driver); +void zt_dynamic_unregister(struct zt_dynamic_driver *driver); /* Receive on a span. The zaptel interface will handle all the calculations for all member channels of the span, pulling the data from the readchunk buffer */ -extern int zt_receive(struct zt_span *span); +int zt_receive(struct zt_span *span); /* Prepare writechunk buffers on all channels for this span */ -extern int zt_transmit(struct zt_span *span); +int zt_transmit(struct zt_span *span); /* Abort the buffer currently being receive with event "event" */ -extern void zt_hdlc_abort(struct zt_chan *ss, int event); +void zt_hdlc_abort(struct zt_chan *ss, int event); /* Indicate to zaptel that the end of frame was received and rotate buffers */ -extern void zt_hdlc_finish(struct zt_chan *ss); +void zt_hdlc_finish(struct zt_chan *ss); /* Put a chunk of data into the current receive buffer */ -extern void zt_hdlc_putbuf(struct zt_chan *ss, unsigned char *rxb, int bytes); +void zt_hdlc_putbuf(struct zt_chan *ss, unsigned char *rxb, int bytes); /* Get a chunk of data from the current transmit buffer. Returns -1 if no data * is left to send, 0 if there is data remaining in the current message to be sent * and 1 if the currently transmitted message is now done */ -extern int zt_hdlc_getbuf(struct zt_chan *ss, unsigned char *bufptr, unsigned int *size); +int zt_hdlc_getbuf(struct zt_chan *ss, unsigned char *bufptr, unsigned int *size); /* Register a span. Returns 0 on success, -1 on failure. Pref-master is non-zero if we should have preference in being the master device */ -extern int zt_register(struct zt_span *span, int prefmaster); +int zt_register(struct zt_span *span, int prefmaster); + +/* Allocate / free memory for a transcoder */ +struct zt_transcoder *zt_transcoder_alloc(int numchans); +void zt_transcoder_free(struct zt_transcoder *ztc); + +/* Register a transcoder */ +int zt_transcoder_register(struct zt_transcoder *tc); + +/* Unregister a transcoder */ +int zt_transcoder_unregister(struct zt_transcoder *tc); + +/* Alert a transcoder */ +int zt_transcoder_alert(struct zt_transcoder_channel *ztc); + +/* Sanity check values */ +static inline int zt_tc_sanitycheck(struct zt_transcode_header *zth, unsigned int outbytes) +{ + if (zth->dstoffset >= sizeof(zth->dstdata)) + return 0; + if (zth->dstlen >= sizeof(zth->dstdata)) + return 0; + if (outbytes >= sizeof(zth->dstdata)) + return 0; + if ((zth->dstoffset + zth->dstlen + outbytes) >= sizeof(zth->dstdata)) + return 0; + if (zth->srcoffset >= sizeof(zth->srcdata)) + return 0; + if (zth->srclen >= sizeof(zth->srcdata)) + return 0; + if ((zth->srcoffset + zth->srclen) > sizeof(zth->srcdata)) + return 0; + return 1; +} /* Unregister a span */ -extern int zt_unregister(struct zt_span *span); +int zt_unregister(struct zt_span *span); /* Gives a name to an LBO */ -extern char *zt_lboname(int lbo); +char *zt_lboname(int lbo); /* Tell Zaptel about changes in received rbs bits */ -extern void zt_rbsbits(struct zt_chan *chan, int bits); +void zt_rbsbits(struct zt_chan *chan, int bits); /* Tell Zaptel abou changes in received signalling */ -extern void zt_hooksig(struct zt_chan *chan, zt_rxsig_t rxsig); +void zt_hooksig(struct zt_chan *chan, zt_rxsig_t rxsig); /* Queue an event on a channel */ -extern void zt_qevent_nolock(struct zt_chan *chan, int event); +void zt_qevent_nolock(struct zt_chan *chan, int event); /* Queue an event on a channel, locking it first */ -extern void zt_qevent_lock(struct zt_chan *chan, int event); +void zt_qevent_lock(struct zt_chan *chan, int event); /* Notify a change possible change in alarm status */ -extern void zt_alarm_notify(struct zt_span *span); +void zt_alarm_notify(struct zt_span *span); /* Initialize a tone state */ -extern void zt_init_tone_state(struct zt_tone_state *ts, struct zt_tone *zt); +void zt_init_tone_state(struct zt_tone_state *ts, struct zt_tone *zt); /* Get a given DTMF or MF tone struct, suitable for zt_tone_nextsample. Set 'mf' to 0 for DTMF or 1 for MFv1 */ -extern struct zt_tone *zt_dtmf_tone(char digit, int mf); +struct zt_tone *zt_dtmf_tone(char digit, int mf); /* Echo cancel a receive and transmit chunk for a given channel. This should be called by the low-level driver as close to the interface @@ -1422,23 +1542,25 @@ extern struct zt_tone *zt_dtmf_tone(char digit, int mf); AT THE ZAPTEL LEVEL. zt_ec_chunk will not echo cancel if it should not be doing so. rxchunk is modified in-place */ -extern void zt_ec_chunk(struct zt_chan *chan, unsigned char *rxchunk, const unsigned char *txchunk); -extern void zt_ec_span(struct zt_span *span); +void zt_ec_chunk(struct zt_chan *chan, unsigned char *rxchunk, const unsigned char *txchunk); +void zt_ec_span(struct zt_span *span); + +extern struct file_operations *zt_transcode_fops; /* Don't use these directly -- they're not guaranteed to be there. */ extern short __zt_mulaw[256]; extern short __zt_alaw[256]; #ifdef CONFIG_CALC_XLAW -extern u_char __zt_lineartoulaw(short a); -extern u_char __zt_lineartoalaw(short a); +u_char __zt_lineartoulaw(short a); +u_char __zt_lineartoalaw(short a); #else extern u_char __zt_lin2mu[16384]; extern u_char __zt_lin2a[16384]; #endif /* Used by dynamic zaptel -- don't use directly */ -extern void zt_set_dynamic_ioctl(int (*func)(unsigned int cmd, unsigned long data)); +void zt_set_dynamic_ioctl(int (*func)(unsigned int cmd, unsigned long data)); /* Used privately by zaptel. Avoid touching directly */ struct zt_tone { @@ -1604,6 +1726,34 @@ struct zt_radio_param { #define ZT_RADPAR_REMCOMMAND 17 /* Remote conrtol write data block & do cmd */ +/* Data formats for capabilities and frames alike (from Asterisk) */ +/*! G.723.1 compression */ +#define ZT_FORMAT_G723_1 (1 << 0) +/*! GSM compression */ +#define ZT_FORMAT_GSM (1 << 1) +/*! Raw mu-law data (G.711) */ +#define ZT_FORMAT_ULAW (1 << 2) +/*! Raw A-law data (G.711) */ +#define ZT_FORMAT_ALAW (1 << 3) +/*! ADPCM (G.726, 32kbps) */ +#define ZT_FORMAT_G726 (1 << 4) +/*! ADPCM (IMA) */ +#define ZT_FORMAT_ADPCM (1 << 5) +/*! Raw 16-bit Signed Linear (8000 Hz) PCM */ +#define ZT_FORMAT_SLINEAR (1 << 6) +/*! LPC10, 180 samples/frame */ +#define ZT_FORMAT_LPC10 (1 << 7) +/*! G.729A audio */ +#define ZT_FORMAT_G729A (1 << 8) +/*! SpeeX Free Compression */ +#define ZT_FORMAT_SPEEX (1 << 9) +/*! iLBC Free Compression */ +#define ZT_FORMAT_ILBC (1 << 10) +/*! Maximum audio format */ +#define ZT_FORMAT_MAX_AUDIO (1 << 15) +/*! Maximum audio mask */ +#define ZT_FORMAT_AUDIO_MASK ((1 << 16) - 1) + #define ZT_RADPAR_DEEMP 18 /* Audio De-empahsis (on or off) */ #define ZT_RADPAR_PREEMP 19 /* Audio Pre-empahsis (on or off) */ -- cgit v1.2.3