Logo Search packages:      
Sourcecode: dahdi-linux version File versions  Download package

kernel.h

Go to the documentation of this file.
/*
 * DAHDI Telephony Interface
 *
 * Written by Mark Spencer <markster@digium.com>
 * Based on previous works, designs, and architectures conceived and
 * written by Jim Dixon <jim@lambdatel.com>.
 *
 * Copyright (C) 2001 Jim Dixon / Zapata Telephony.
 * Copyright (C) 2001 - 2008 Digium, Inc.
 *
 * All rights reserved.
 *
 */

/*
 * See http://www.asterisk.org for more information about
 * the Asterisk project. Please do not directly contact
 * any of the maintainers of this project for assistance;
 * the project provides a web site, mailing lists and IRC
 * channels for your use.
 *
 * This program is free software, distributed under the terms of
 * the GNU General Public License Version 2 as published by the
 * Free Software Foundation. See the LICENSE file included with
 * this program for more details.
 */

/*!
 * \file
 * \brief DAHDI kernel interface definitions
 */

#ifndef _DAHDI_KERNEL_H
#define _DAHDI_KERNEL_H

#include <dahdi/user.h>
#include <dahdi/fasthdlc.h>

#include <dahdi/dahdi_config.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
#include <linux/config.h>
#endif
#include <linux/fs.h>
#include <linux/ioctl.h>

#ifdef CONFIG_DAHDI_NET 
#include <linux/hdlc.h>
#endif

#ifdef CONFIG_DAHDI_PPP
#include <linux/ppp_channel.h>
#include <linux/skbuff.h>
#include <linux/interrupt.h>
#endif

#include <linux/poll.h>

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
#define dahdi_pci_module pci_register_driver
#else
#define dahdi_pci_module pci_module_init
#endif

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
#define DAHDI_IRQ_HANDLER(a) static irqreturn_t a(int irq, void *dev_id)
#else
#define DAHDI_IRQ_HANDLER(a) static irqreturn_t a(int irq, void *dev_id, struct pt_regs *regs)
#endif

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
#define DAHDI_IRQ_SHARED IRQF_SHARED
#define DAHDI_IRQ_DISABLED IRQF_DISABLED
#define DAHDI_IRQ_SHARED_DISABLED IRQF_SHARED | IRQF_DISABLED
#else
#define DAHDI_IRQ_SHARED SA_SHIRQ
#define DAHDI_IRQ_DISABLED SA_INTERRUPT
#define DAHDI_IRQ_SHARED_DISABLED SA_SHIRQ | SA_INTERRUPT
#endif

#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16)
#ifndef dev_notice
#define dev_notice(dev, format, arg...)         \
        dev_printk(KERN_NOTICE , dev , format , ## arg)
#endif
#endif

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
#define dev_name(dev)         (dev)->bus_id
#define dev_set_name(dev, format, ...) \
      snprintf((dev)->bus_id, BUS_ID_SIZE, format, ## __VA_ARGS__);
#endif

/*! Default chunk size for conferences and such -- static right now, might make
   variable sometime.  8 samples = 1 ms = most frequent service interval possible
   for a USB device */
00097 #define DAHDI_CHUNKSIZE        8
#define DAHDI_MIN_CHUNKSIZE    DAHDI_CHUNKSIZE
#define DAHDI_DEFAULT_CHUNKSIZE      DAHDI_CHUNKSIZE
#define DAHDI_MAX_CHUNKSIZE    DAHDI_CHUNKSIZE
#define DAHDI_CB_SIZE          2

00103 #define RING_DEBOUNCE_TIME    2000  /*!< 2000 ms ring debounce time */

typedef struct
{
    int32_t gain;
    int32_t a1;
    int32_t a2;
    int32_t b1;
    int32_t b2;

    int32_t z1;
    int32_t z2;
} biquad2_state_t;

typedef struct
{
    biquad2_state_t notch;
    int notch_level;
    int channel_level;
    int tone_present;
    int tone_cycle_duration;
    int good_cycles;
    int hit;
} echo_can_disable_detector_state_t;

struct sf_detect_state {
      long  x1;
      long  x2;
      long  y1;
      long  y2;
      long  e1;
      long  e2;
      int   samps;
      int   lastdetect;
};

struct dahdi_tone_state {
      int v1_1;
      int v2_1;
      int v3_1;
      int v1_2;
      int v2_2;
      int v3_2;
      int modulate;
};

/*! \brief Conference queue structure */
00150 struct confq {
      u_char buffer[DAHDI_CHUNKSIZE * DAHDI_CB_SIZE];
      u_char *buf[DAHDI_CB_SIZE];
      int inbuf;
      int outbuf;
};

struct dahdi_chan;
struct dahdi_echocan_state;

/*! Features a DAHDI echo canceler (software or hardware) can provide to the DAHDI core. */
00161 struct dahdi_echocan_features {

      /*! Able to detect CED tone (2100 Hz with phase reversals) in the transmit direction.
       * If the echocan can detect this tone, it may report it it as an event (see
       * the events.CED_tx_detected field of dahdi_echocan_state), and if it will automatically
       * disable itself or its non-linear processor, then the NLP_automatic feature flag should also
       * be set so that the DAHDI core doesn't bother trying to do so.
      */
00169       u32 CED_tx_detect:1;

      /*! Able to detect CED tone (2100 Hz with phase reversals) in the receive direction.
       * If the echocan can detect this tone, it may report it it as an event (see
       * the events.CED_rx_detected field of dahdi_echocan_state), and if it will automatically
       * disable itself or its non-linear processor, then the NLP_automatic flag feature should also
       * be set so that the DAHDI core doesn't bother trying to do so.
      */
00177       u32 CED_rx_detect:1;

      /*! Able to detect CNG tone (1100 Hz) in the transmit direction. */
00180       u32 CNG_tx_detect:1;

      /*! Able to detect CNG tone (1100 Hz) in the receive direction. */
00183       u32 CNG_rx_detect:1;

      /*! If the echocan's NLP can be enabled and disabled without requiring destruction
       * and recreation of the state structure, this feature flag should be set and the
       * echocan_NLP_toggle field of the dahdi_echocan_ops structure should be filled with a
       * pointer to the function to perform that operation.
       */
00190       u32 NLP_toggle:1;

      /*! If the echocan will automatically disable itself (or even just its NLP) based on
       * detection of a CED tone in either direction, this feature flag should be set (along
       * with the tone detection feature flags).
       */
00196       u32 NLP_automatic:1;
};

/*! Operations (methods) that can be performed on a DAHDI echo canceler instance (state
 * structure) after it has been created, by either a software or hardware echo canceller.
 * The echo canceler must populate the owner field of the dahdi_echocan_state structure
 * with a pointer to the relevant operations structure for that instance.
 */
00204 struct dahdi_echocan_ops {

      /*! The name of the echocan that created this structure. */
00207       const char *name;

      /*! \brief Free an echocan state structure.
       * \param[in,out] ec Pointer to the state structure to free.
       *
       * \return Nothing.
       */
      void (*echocan_free)(struct dahdi_chan *chan, struct dahdi_echocan_state *ec);

      /*! \brief Process an array of audio samples through the echocan.
       * \param[in,out] ec Pointer to the state structure.
       * \param[in,out] isig The receive direction data (will be modified).
       * \param[in] iref The transmit direction data.
       * \param[in] size The number of elements in the isig and iref arrays.
       *
       * Note: This function can also return events in the events field of the
       * dahdi_echocan_state structure. If it can do so, then the echocan does
       * not need to provide the echocan_events function.
       *
       * \return Nothing.
       */
      void (*echocan_process)(struct dahdi_echocan_state *ec, short *isig, const short *iref, u32 size);

      /*! \brief Retrieve events from the echocan.
       * \param[in,out] ec Pointer to the state structure.
       *
       *
       * If any events have occurred, the events field of the dahdi_echocan_state
       * structure should be updated to include them.
       *
       * \return Nothing.
       */
      void (*echocan_events)(struct dahdi_echocan_state *ec);

      /*! \brief Feed a sample (and its position) for echocan training.
       * \param[in,out] ec Pointer to the state structure.
       * \param[in] pos The tap position to be 'trained'.
       * \param[in] val The receive direction sample for the specified tap position.
       *
       * \retval Zero if training should continue.
       * \retval Non-zero if training is complete.
       */
      int (*echocan_traintap)(struct dahdi_echocan_state *ec, int pos, short val);

      /*! \brief Enable or disable non-linear processing (NLP) in the echocan.
       * \param[in,out] ec Pointer to the state structure.
       * \param[in] enable Zero to disable, non-zero to enable.
       *
       * \return Nothing.
       */
      void (*echocan_NLP_toggle)(struct dahdi_echocan_state *ec, unsigned int enable);
};

/*! A factory for creating instances of software echo cancelers to be used on DAHDI channels. */
00261 struct dahdi_echocan_factory {

      /*! The name of the factory. */
00264       const char *name;

      /*! Pointer to the module that owns this factory; the module's reference count will be
       * incremented/decremented by the DAHDI core as needed.
       */
00269       struct module *owner;

      /*! \brief Function to create an instance of the echocan.
       * \param[in] ecp Structure defining parameters to be used for the instance creation.
       * \param[in] p Pointer to the beginning of an (optional) array of user-defined parameters.
       * \param[out] ec Pointer to the state structure that is created, if any.
       *
       * \retval Zero on success.
       * \retval Non-zero on failure (return value will be returned to userspace so it should be a
       * standard error number).
       */
      int (*echocan_create)(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
                        struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec);
};

/*! \brief Register an echo canceler factory with the DAHDI core.
 * \param[in] ec Pointer to the dahdi_echocan_factory structure to be registered.
 *
 * \retval Zero on success.
 * \retval Non-zero on failure (return value will be a standard error number).
 */
int dahdi_register_echocan_factory(const struct dahdi_echocan_factory *ec);

/*! \brief Unregister a previously-registered echo canceler factory from the DAHDI core.
 * \param[in] ec Pointer to the dahdi_echocan_factory structure to be unregistered.
 *
 * \return Nothing.
 */
void dahdi_unregister_echocan_factory(const struct dahdi_echocan_factory *ec);

enum dahdi_echocan_mode {
      __ECHO_MODE_MUTE = 1 << 8,
      ECHO_MODE_IDLE = 0,
      ECHO_MODE_PRETRAINING = 1 | __ECHO_MODE_MUTE,
      ECHO_MODE_STARTTRAINING = 2 | __ECHO_MODE_MUTE,
      ECHO_MODE_AWAITINGECHO = 3 | __ECHO_MODE_MUTE,
      ECHO_MODE_TRAINING = 4 | __ECHO_MODE_MUTE,
      ECHO_MODE_ACTIVE = 5,
      ECHO_MODE_FAX = 6,
};

/*! An instance of a DAHDI echo canceler (software or hardware). */
00311 struct dahdi_echocan_state {

      /*! Pointer to a dahdi_echocan_ops structure of operations that can be
       * performed on this instance.
       */
00316       const struct dahdi_echocan_ops *ops;

      /*! State data used by the DAHDI core's CED detector for the transmit
       * direction, if needed.
       */
00321       echo_can_disable_detector_state_t txecdis;

      /*! State data used by the DAHDI core's CED detector for the receive
       * direction, if needed.
       */
00326       echo_can_disable_detector_state_t rxecdis;

      /*! Features offered by the echo canceler that provided this instance. */
00329       struct dahdi_echocan_features features;

      struct {
            /*! The mode the echocan is currently in. */
00333             enum dahdi_echocan_mode mode;

            /*! The last tap position that was fed to the echocan's training function. */
00336             u32 last_train_tap;

            /*! How many samples to wait before beginning the training operation. */
00339             u32 pretrain_timer;
      } status;

      /*! This structure contains event flags, allowing the echocan to report
       * events that occurred as it processed the transmit and receive streams
       * of samples. Each call to the echocan_process operation for this
       * instance may report events, so the structure should be cleared before
       * calling that operation.
       */
00348       union dahdi_echocan_events {
            u32 all;
            struct {
                  /*! CED tone was detected in the transmit direction. If the
                   * echocan automatically disables its NLP when this occurs,
                   * it must also signal the NLP_auto_disabled event during the *same*
                   * call to echocan_process that reports the CED detection.
                   */
00356                   u32 CED_tx_detected:1;

                  /*! CED tone was detected in the receive direction. If the
                   * echocan automatically disables its NLP when this occurs,
                   * it must also signal the NLP_auto_disabled event during the *same*
                   * call to echocan_process that reports the CED detection.
                   */
00363                   u32 CED_rx_detected:1;

                  /*! CNG tone was detected in the transmit direction. */
00366                   u32 CNG_tx_detected:1;

                  /*! CNG tone was detected in the receive direction. */
00369                   u32 CNG_rx_detected:1;

                  /*! The echocan disabled its NLP automatically.
                   */
00373                   u32 NLP_auto_disabled:1;

                  /*! The echocan enabled its NLP automatically.
                   */
00377                   u32 NLP_auto_enabled:1;
            };
      } events;
};

struct dahdi_chan {
#ifdef CONFIG_DAHDI_NET
      /*! \note Must be first */
      struct dahdi_hdlc *hdlcnetdev;
#endif
#ifdef CONFIG_DAHDI_PPP
      struct ppp_channel *ppp;
      struct tasklet_struct ppp_calls;
      int do_ppp_wakeup;
      int do_ppp_error;
      struct sk_buff_head ppp_rq;
#endif
#ifdef BUFFER_DEBUG
      int statcount;
      int lastnumbufs;
#endif
      spinlock_t lock;
      char name[40];
      /* Specified by DAHDI */
      /*! \brief DAHDI channel number */
      int channo;
      int chanpos;
      unsigned long flags;
      long rxp1;
      long rxp2;
      long rxp3;
      int txtone;
      int tx_v2;
      int tx_v3;
      int v1_1;
      int v2_1;
      int v3_1;
      int toneflags;
      struct sf_detect_state rd;

      struct dahdi_chan *master;    /*!< Our Master channel (could be us) */
      /*! \brief Next slave (if appropriate) */
      int nextslave;

      u_char *writechunk;                                   /*!< Actual place to write to */
      u_char swritechunk[DAHDI_MAX_CHUNKSIZE];  /*!< Buffer to be written */
      u_char *readchunk;                                    /*!< Actual place to read from */
      u_char sreadchunk[DAHDI_MAX_CHUNKSIZE];   /*!< Preallocated static area */
      short *readchunkpreec;

      /*! Pointer to tx and rx gain tables */
      u_char *rxgain;
      u_char *txgain;
      
      /*! Whether or not we have allocated gains or are using the default */
      int gainalloc;

      /* Specified by driver, readable by DAHDI */
      void *pvt;              /*!< Private channel data */
      struct file *file;      /*!< File structure */
      
      
      struct dahdi_span *span;                  /*!< Span we're a member of */
      int         sig;              /*!< Signalling */
      int         sigcap;                 /*!< Capability for signalling */
      __u32       chan_alarms;            /*!< alarms status */

      /* Used only by DAHDI -- NO DRIVER SERVICEABLE PARTS BELOW */
      /* Buffer declarations */
      u_char            *readbuf[DAHDI_MAX_NUM_BUFS]; /*!< read buffer */
      int         inreadbuf;
      int         outreadbuf;
      wait_queue_head_t readbufq; /*!< read wait queue */

      u_char            *writebuf[DAHDI_MAX_NUM_BUFS]; /*!< write buffers */
      int         inwritebuf;
      int         outwritebuf;
      wait_queue_head_t writebufq; /*!< write wait queue */
      
      int         blocksize;  /*!< Block size */

      int         eventinidx;  /*!< out index in event buf (circular) */
      int         eventoutidx;  /*!< in index in event buf (circular) */
      unsigned int      eventbuf[DAHDI_MAX_EVENTSIZE];  /*!< event circ. buffer */
      wait_queue_head_t eventbufq; /*!< event wait queue */
      
      wait_queue_head_t txstateq;   /*!< waiting on the tx state to change */
      
      int         readn[DAHDI_MAX_NUM_BUFS];  /*!< # of bytes ready in read buf */
      int         readidx[DAHDI_MAX_NUM_BUFS];  /*!< current read pointer */
      int         writen[DAHDI_MAX_NUM_BUFS];  /*!< # of bytes ready in write buf */
      int         writeidx[DAHDI_MAX_NUM_BUFS];  /*!< current write pointer */
      
      int         numbufs;                /*!< How many buffers in channel */
      int         txbufpolicy;                  /*!< Buffer policy */
      int         rxbufpolicy;                  /*!< Buffer policy */
      int         txdisable;                    /*!< Disable transmitter */
      int   rxdisable;                    /*!< Disable receiver */
      
      
      /* Tone zone stuff */
      struct dahdi_zone *curzone;         /*!< Zone for selecting tones */
      int   tonezone;                     /*!< Tone zone for this channel */
      struct dahdi_tone *curtone;         /*!< Current tone we're playing (if any) */
      int         tonep;                              /*!< Current position in tone */
      struct dahdi_tone_state ts;         /*!< Tone state */

      /* Pulse dial stuff */
      int   pdialcount;             /*!< pulse dial count */

      /*! Ring cadence */
      int ringcadence[DAHDI_MAX_CADENCE];
      int firstcadencepos;                      /*!< Where to restart ring cadence */

      /* Digit string dialing stuff */
      int         digitmode;              /*!< What kind of tones are we sending? */
      char  txdialbuf[DAHDI_MAX_DTMF_BUF];
      int   dialing;
      int   afterdialingtimer;
      int         cadencepos;                   /*!< Where in the cadence we are */

      /* I/O Mask */    
      int         iomask;  /*! I/O Mux signal mask */
      wait_queue_head_t sel;  /*! thingy for select stuff */
      
      /* HDLC state machines */
      struct fasthdlc_state txhdlc;
      struct fasthdlc_state rxhdlc;
      int infcs;

      /* Conferencing stuff */
      int         confna;     /*! conference number (alias) */
      int         _confn;     /*! Actual conference number */
      int         confmode;  /*! conference mode */
      int         confmute; /*! conference mute mode */

      /* Incoming and outgoing conference chunk queues for
         communicating between DAHDI master time and
         other boards */
      struct confq confin;
      struct confq confout;

      short getlin[DAHDI_MAX_CHUNKSIZE];              /*!< Last transmitted samples */
      unsigned char getraw[DAHDI_MAX_CHUNKSIZE];            /*!< Last received raw data */
      short getlin_lastchunk[DAHDI_MAX_CHUNKSIZE];    /*!< Last transmitted samples from last chunk */
      short putlin[DAHDI_MAX_CHUNKSIZE];              /*!< Last received samples */
      unsigned char putraw[DAHDI_MAX_CHUNKSIZE];            /*!< Last received raw data */
      short conflast[DAHDI_MAX_CHUNKSIZE];                  /*!< Last conference sample -- base part of channel */
      short conflast1[DAHDI_MAX_CHUNKSIZE];           /*!< Last conference sample  -- pseudo part of channel */
      short conflast2[DAHDI_MAX_CHUNKSIZE];           /*!< Previous last conference sample -- pseudo part of channel */
      

      /*! The echo canceler module that should be used to create an
         instance when this channel needs one */
      const struct dahdi_echocan_factory *ec_factory;
      /*! The echo canceler module that owns the instance currently
         on this channel, if one is present */
      const struct dahdi_echocan_factory *ec_current;
      /*! The state data of the echo canceler instance in use */
      struct dahdi_echocan_state *ec_state;

      /* RBS timings  */
      int         prewinktime;  /*!< pre-wink time (ms) */
      int         preflashtime;     /*!< pre-flash time (ms) */
      int         winktime;  /*!< wink time (ms) */
      int         flashtime;  /*!< flash time (ms) */
      int         starttime;  /*!< start time (ms) */
      int         rxwinktime;  /*!< rx wink time (ms) */
      int         rxflashtime; /*!< rx flash time (ms) */
      int         debouncetime;  /*!< FXS GS sig debounce time (ms) */
      int         pulsebreaktime; /*!< pulse line open time (ms) */
      int         pulsemaketime;  /*!< pulse line closed time (ms) */
      int         pulseaftertime; /*!< pulse time between digits (ms) */

      /*! RING debounce timer */
      int   ringdebtimer;
      
      /*! RING trailing detector to make sure a RING is really over */
      int ringtrailer;

      /* PULSE digit receiver stuff */
      int   pulsecount;
      int   pulsetimer;

      /* RBS timers */
      int   itimerset;        /*!< what the itimer was set to last */
      int   itimer;
      int   otimer;
      
      /* RBS state */
      int gotgs;
      int txstate;
      int rxsig;
      int txsig;
      int rxsigstate;

      /* non-RBS rx state */
      int rxhooksig;
      int txhooksig;
      int kewlonhook;

      /*! Idle signalling if CAS signalling */
      int idlebits;

      int deflaw;       /*! 1 = mulaw, 2=alaw, 0=undefined */
      short *xlaw;
#ifdef      OPTIMIZE_CHANMUTE
      int chanmute;           /*!< no need for PCM data */
#endif
#ifdef CONFIG_CALC_XLAW
      unsigned char (*lineartoxlaw)(short a);
#else
      unsigned char *lin2x;
#endif
};

#ifdef CONFIG_DAHDI_NET
struct dahdi_hdlc {
      struct net_device *netdev;
      struct dahdi_chan *chan;
};
#endif

/*! Define the maximum block size */
00601 #define DAHDI_MAX_BLOCKSIZE   8192


00604 #define DAHDI_DEFAULT_WINKTIME      150   /*!< 150 ms default wink time */
00605 #define DAHDI_DEFAULT_FLASHTIME     750   /*!< 750 ms default flash time */

00607 #define DAHDI_DEFAULT_PREWINKTIME   50    /*!< 50 ms before wink */
00608 #define DAHDI_DEFAULT_PREFLASHTIME 50     /*!< 50 ms before flash */
00609 #define DAHDI_DEFAULT_STARTTIME 1500      /*!< 1500 ms of start */
00610 #define DAHDI_DEFAULT_RINGTIME 2000 /*!< 2000 ms of ring on (start, FXO) */
#if 0
#define DAHDI_DEFAULT_RXWINKTIME 250      /*!< 250ms longest rx wink */
#endif
00614 #define DAHDI_DEFAULT_RXWINKTIME 300      /*!< 300ms longest rx wink (to work with the Atlas) */
00615 #define DAHDI_DEFAULT_RXFLASHTIME 1250    /*!< 1250ms longest rx flash */
00616 #define DAHDI_DEFAULT_DEBOUNCETIME 600    /*!< 600ms of FXS GS signalling debounce */
00617 #define DAHDI_DEFAULT_PULSEMAKETIME 50    /*!< 50 ms of line closed when dial pulsing */
00618 #define DAHDI_DEFAULT_PULSEBREAKTIME 50   /*!< 50 ms of line open when dial pulsing */
00619 #define DAHDI_DEFAULT_PULSEAFTERTIME 750  /*!< 750ms between dial pulse digits */

00621 #define DAHDI_MINPULSETIME (15 * 8) /*!< 15 ms minimum */

#ifdef SHORT_FLASH_TIME
#define DAHDI_MAXPULSETIME (80 * 8) /*!< we need 80 ms, not 200ms, as we have a short flash */
#else
00626 #define DAHDI_MAXPULSETIME (200 * 8)      /*!< 200 ms maximum */
#endif

#define DAHDI_PULSETIMEOUT ((DAHDI_MAXPULSETIME / 8) + 50)

00631 #define DAHDI_RINGTRAILER (50 * 8)  /*!< Don't consider a ring "over" until it's been gone at least this
                                                         much time */

00634 #define DAHDI_LOOPCODE_TIME 10000         /*!< send loop codes for 10 secs */
00635 #define DAHDI_ALARMSETTLE_TIME      5000  /*!< allow alarms to settle for 5 secs */
00636 #define DAHDI_AFTERSTART_TIME 500         /*!< 500ms after start */

00638 #define DAHDI_RINGOFFTIME 4000            /*!< Turn off ringer for 4000 ms */
00639 #define DAHDI_KEWLTIME 500          /*!< 500ms for kewl pulse */
00640 #define DAHDI_AFTERKEWLTIME 300    /*!< 300ms after kewl pulse */

00642 #define DAHDI_MAX_PRETRAINING   1000      /*!< 1000ms max pretraining time */

#ifdef      FXSFLASH
#define DAHDI_FXSFLASHMINTIME 450   /*!< min 450ms */
#define DAHDI_FXSFLASHMAXTIME 550   /*!< max 550ms */
#endif


struct dahdi_chardev {
      const char *name;
      __u8 minor;
};

int dahdi_register_chardev(struct dahdi_chardev *dev);
int dahdi_unregister_chardev(struct dahdi_chardev *dev);

/*! \brief defines for transmit signalling */
00659 enum dahdi_txsig {
00660       DAHDI_TXSIG_ONHOOK,  /*!< On hook */
00661       DAHDI_TXSIG_OFFHOOK, /*!< Off hook */
00662       DAHDI_TXSIG_START,   /*!< Start / Ring */
00663       DAHDI_TXSIG_KEWL,     /*!< Drop battery if possible */
      /*! Leave this as the last entry */
00665       DAHDI_TXSIG_TOTAL,
};

enum dahdi_rxsig {
      DAHDI_RXSIG_ONHOOK,
      DAHDI_RXSIG_OFFHOOK,
      DAHDI_RXSIG_START,
      DAHDI_RXSIG_RING,
      DAHDI_RXSIG_INITIAL
};
      
enum {
      /* Span flags */
      DAHDI_FLAGBIT_REGISTERED= 0,
      DAHDI_FLAGBIT_RUNNING   = 1,
00680       DAHDI_FLAGBIT_RBS = 12, /*!< Span uses RBS signalling */

      /* Channel flags */
00683       DAHDI_FLAGBIT_DTMFDECODE= 2,  /*!< Channel supports native DTMF decode */
00684       DAHDI_FLAGBIT_MFDECODE  = 3,  /*!< Channel supports native MFr2 decode */
00685       DAHDI_FLAGBIT_ECHOCANCEL= 4,  /*!< Channel supports native echo cancellation */
00686       DAHDI_FLAGBIT_HDLC      = 5,  /*!< Perform HDLC */
00687       DAHDI_FLAGBIT_NETDEV    = 6,  /*!< Send to network */
00688       DAHDI_FLAGBIT_PSEUDO    = 7,  /*!< Pseudo channel */
00689       DAHDI_FLAGBIT_CLEAR     = 8,  /*!< Clear channel */
00690       DAHDI_FLAGBIT_AUDIO     = 9,  /*!< Audio mode channel */
00691       DAHDI_FLAGBIT_OPEN      = 10, /*!< Channel is open */
00692       DAHDI_FLAGBIT_FCS = 11, /*!< Calculate FCS */
      /* Reserve 12 for uniqueness with span flags */
00694       DAHDI_FLAGBIT_LINEAR    = 13, /*!< Talk to user space in linear */
00695       DAHDI_FLAGBIT_PPP = 14, /*!< PPP is available */
      DAHDI_FLAGBIT_T1PPP     = 15,
00697       DAHDI_FLAGBIT_SIGFREEZE = 16, /*!< Freeze signalling */
00698       DAHDI_FLAGBIT_NOSTDTXRX = 17, /*!< Do NOT do standard transmit and receive on every interrupt */
00699       DAHDI_FLAGBIT_LOOPED    = 18, /*!< Loopback the receive data from the channel to the transmit */
00700       DAHDI_FLAGBIT_MTP2      = 19, /*!< Repeats last message in buffer and also discards repeating messages sent to us */
00701       DAHDI_FLAGBIT_HDLC56    = 20, /*!< Sets the given channel (if in HDLC mode) to use 56K HDLC instead of 64K  */
};

/* map flagbits to flag masks */
#define     DAHDI_FLAG(x)     (1 << (DAHDI_FLAGBIT_ ## x))

/*! This is a redefinition of the flags from above to allow use of the 
 * legacy drivers that do not use the kernel atomic bit testing and 
 * changing routines.
 * 
 * See the above descriptions for DAHDI_FLAGBIT_....  for documentation 
 * about function. */
/* Span flags */
00714 #define DAHDI_FLAG_REGISTERED DAHDI_FLAG(REGISTERED)
#define DAHDI_FLAG_RUNNING    DAHDI_FLAG(RUNNING)
#define DAHDI_FLAG_RBS        DAHDI_FLAG(RBS)

/* Channel flags */
#define DAHDI_FLAG_DTMFDECODE DAHDI_FLAG(DTMFDECODE)
#define DAHDI_FLAG_MFDECODE   DAHDI_FLAG(MFDECODE)
#define DAHDI_FLAG_ECHOCANCEL DAHDI_FLAG(ECHOCANCEL)

#define DAHDI_FLAG_HDLC       DAHDI_FLAG(HDLC)
#define DAHDI_FLAG_NETDEV     DAHDI_FLAG(NETDEV)
#define DAHDI_FLAG_PSEUDO     DAHDI_FLAG(PSEUDO)
#define DAHDI_FLAG_CLEAR      DAHDI_FLAG(CLEAR)
#define DAHDI_FLAG_AUDIO      DAHDI_FLAG(AUDIO)

#define DAHDI_FLAG_OPEN       DAHDI_FLAG(OPEN)
#define DAHDI_FLAG_FCS        DAHDI_FLAG(FCS)
/* Reserve 12 for uniqueness with span flags */
#define DAHDI_FLAG_LINEAR     DAHDI_FLAG(LINEAR)
#define DAHDI_FLAG_PPP        DAHDI_FLAG(PPP)
#define DAHDI_FLAG_T1PPP      DAHDI_FLAG(T1PPP)
#define DAHDI_FLAG_SIGFREEZE  DAHDI_FLAG(SIGFREEZE)
#define DAHDI_FLAG_NOSTDTXRX  DAHDI_FLAG(NOSTDTXRX)
#define DAHDI_FLAG_LOOPED     DAHDI_FLAG(LOOPED)
#define DAHDI_FLAG_MTP2       DAHDI_FLAG(MTP2)
#define DAHDI_FLAG_HDLC56     DAHDI_FLAG(HDLC56)

struct dahdi_span {
      spinlock_t lock;
      void *pvt;              /*!< Private stuff */
      char name[40];                /*!< Span name */
      char desc[80];                /*!< Span description */
      const char *spantype;         /*!< span type in text form */
      const char *manufacturer;     /*!< span's device manufacturer */
      char devicetype[80];          /*!< span's device type */
      char location[40];            /*!< span device's location in system */
      int deflaw;             /*!< Default law (DAHDI_MULAW or DAHDI_ALAW) */
      int alarms;             /*!< Pending alarms on span */
      unsigned long flags;
      int irq;                /*!< IRQ for this span's hardware */
      int lbo;                /*!< Span Line-Buildout */
      int lineconfig;               /*!< Span line configuration */
      int linecompat;               /*!< Span line compatibility */
      int channels;                 /*!< Number of channels in span */
      int txlevel;                  /*!< Tx level */
      int rxlevel;                  /*!< Rx level */
      int syncsrc;                  /*!< current sync src (gets copied here) */
      unsigned int bpvcount;        /*!< BPV counter */
      unsigned int crc4count;         /*!< CRC4 error counter */
      unsigned int ebitcount;       /*!< current E-bit error count */
      unsigned int fascount;        /*!< current FAS error count */

      int maintstat;                /*!< Maintenance state */
      wait_queue_head_t maintq;     /*!< Maintenance queue */
      int mainttimer;               /*!< Maintenance timer */
      
      int irqmisses;                /*!< Interrupt misses */

      int timingslips;              /*!< Clock slips */

      struct dahdi_chan **chans;          /*!< Member channel structures */

      /*   ==== Span Callback Operations ====   */
      /*! Req: Set the requested chunk size.  This is the unit in which you must
         report results for conferencing, etc */
      int (*setchunksize)(struct dahdi_span *span, int chunksize);

      /*! Opt: Configure the span (if appropriate) */
      int (*spanconfig)(struct dahdi_span *span, struct dahdi_lineconfig *lc);
      
      /*! Opt: Start the span */
      int (*startup)(struct dahdi_span *span);
      
      /*! Opt: Shutdown the span */
      int (*shutdown)(struct dahdi_span *span);
      
      /*! Opt: Enable maintenance modes */
      int (*maint)(struct dahdi_span *span, int mode);

#ifdef      DAHDI_SYNC_TICK
      /*! Opt: send sync to spans */
      int (*sync_tick)(struct dahdi_span *span, int is_master);
#endif

      /* ====  Channel Callback Operations ==== */
      /*! Opt: Set signalling type (if appropriate) */
      int (*chanconfig)(struct dahdi_chan *chan, int sigtype);

      /*! Opt: Prepare a channel for I/O */
      int (*open)(struct dahdi_chan *chan);

      /*! Opt: Close channel for I/O */
      int (*close)(struct dahdi_chan *chan);
      
      /*! Opt: IOCTL */
      int (*ioctl)(struct dahdi_chan *chan, unsigned int cmd, unsigned long data);
      
      /*! Opt: Provide echo cancellation on a channel */
      int (*echocan_create)(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
                        struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec);

      /* Okay, now we get to the signalling.  You have several options: */

      /* Option 1: If you're a T1 like interface, you can just provide a
         rbsbits function and we'll assert robbed bits for you.  Be sure to 
         set the DAHDI_FLAG_RBS in this case.  */

      /*! Opt: If the span uses A/B bits, set them here */
      int (*rbsbits)(struct dahdi_chan *chan, int bits);
      
      /*! Option 2: If you don't know about sig bits, but do have their
         equivalents (i.e. you can disconnect battery, detect off hook,
         generate ring, etc directly) then you can just specify a
         sethook function, and we'll call you with appropriate hook states
         to set.  Still set the DAHDI_FLAG_RBS in this case as well */
      int (*hooksig)(struct dahdi_chan *chan, enum dahdi_txsig hookstate);
      
      /*! Option 3: If you can't use sig bits, you can write a function
         which handles the individual hook states  */
      int (*sethook)(struct dahdi_chan *chan, int hookstate);
      
      /*! Opt: Dacs the contents of chan2 into chan1 if possible */
      int (*dacs)(struct dahdi_chan *chan1, struct dahdi_chan *chan2);

      /*! Opt: Used to tell an onboard HDLC controller that there is data ready to transmit */
      void (*hdlc_hard_xmit)(struct dahdi_chan *chan);

      /* Used by DAHDI only -- no user servicable parts inside */
      int spanno;             /*!< Span number for DAHDI */
      int offset;             /*!< Offset within a given card */
      int lastalarms;         /*!< Previous alarms */
      /*! If the watchdog detects no received data, it will call the
         watchdog routine */
      int (*watchdog)(struct dahdi_span *span, int cause);
#ifdef CONFIG_DAHDI_WATCHDOG
      int watchcounter;
      int watchstate;
#endif      
};

struct dahdi_transcoder_channel {
      void *pvt;
      struct dahdi_transcoder *parent;
      wait_queue_head_t ready;
      __u32 built_fmts;
#define DAHDI_TC_FLAG_BUSY          1
#define DAHDI_TC_FLAG_CHAN_BUILT    2
#define DAHDI_TC_FLAG_NONBLOCK            3
#define DAHDI_TC_FLAG_DATA_WAITING  4
      unsigned long flags;
      u32 dstfmt;
      u32 srcfmt;
};

static inline int 
dahdi_tc_is_built(struct dahdi_transcoder_channel *dtc) {
      return test_bit(DAHDI_TC_FLAG_CHAN_BUILT, &dtc->flags);
}
static inline void
dahdi_tc_set_built(struct dahdi_transcoder_channel *dtc) {
      set_bit(DAHDI_TC_FLAG_CHAN_BUILT, &dtc->flags);
}
static inline void 
dahdi_tc_clear_built(struct dahdi_transcoder_channel *dtc) {
      clear_bit(DAHDI_TC_FLAG_CHAN_BUILT, &dtc->flags);
}
static inline int 
dahdi_tc_is_nonblock(struct dahdi_transcoder_channel *dtc) {
      return test_bit(DAHDI_TC_FLAG_NONBLOCK, &dtc->flags);
}
static inline void 
dahdi_tc_set_nonblock(struct dahdi_transcoder_channel *dtc) {
      set_bit(DAHDI_TC_FLAG_NONBLOCK, &dtc->flags);
}
static inline void 
dahdi_tc_clear_nonblock(struct dahdi_transcoder_channel *dtc) {
      clear_bit(DAHDI_TC_FLAG_NONBLOCK, &dtc->flags);
}
static inline int 
dahdi_tc_is_data_waiting(struct dahdi_transcoder_channel *dtc) {
      return test_bit(DAHDI_TC_FLAG_DATA_WAITING, &dtc->flags);
}
static inline int 
dahdi_tc_is_busy(struct dahdi_transcoder_channel *dtc) {
      return test_bit(DAHDI_TC_FLAG_BUSY, &dtc->flags);
}
static inline void 
dahdi_tc_set_busy(struct dahdi_transcoder_channel *dtc) {
      set_bit(DAHDI_TC_FLAG_BUSY, &dtc->flags);
}
static inline void 
dahdi_tc_clear_busy(struct dahdi_transcoder_channel *dtc) {
      clear_bit(DAHDI_TC_FLAG_BUSY, &dtc->flags);
}
static inline void 
dahdi_tc_set_data_waiting(struct dahdi_transcoder_channel *dtc) {
      set_bit(DAHDI_TC_FLAG_DATA_WAITING, &dtc->flags);
}
static inline void 
dahdi_tc_clear_data_waiting(struct dahdi_transcoder_channel *dtc) {
      clear_bit(DAHDI_TC_FLAG_DATA_WAITING, &dtc->flags);
}

struct dahdi_transcoder {
      struct list_head active_list_node;
      struct list_head registration_list_node;
      char name[80];
      int numchannels;
      unsigned int srcfmts;
      unsigned int dstfmts;
      struct file_operations fops;
      int (*allocate)(struct dahdi_transcoder_channel *channel);
      int (*release)(struct dahdi_transcoder_channel *channel);
      /* Transcoder channels */
      struct dahdi_transcoder_channel channels[0];
};

#define DAHDI_WATCHDOG_NOINTS       (1 << 0)

#define DAHDI_WATCHDOG_INIT               1000

#define DAHDI_WATCHSTATE_UNKNOWN          0
#define DAHDI_WATCHSTATE_OK               1
#define DAHDI_WATCHSTATE_RECOVERING 2
#define DAHDI_WATCHSTATE_FAILED           3


struct dahdi_dynamic_driver {
      /*! Driver name (e.g. Eth) */
      char name[20];

      /*! Driver description */
      char desc[80];

      /*! Create a new transmission pipe */
      void *(*create)(struct dahdi_span *span, char *address);

      /*! Destroy a created transmission pipe */
      void (*destroy)(void *tpipe);

      /*! Transmit a given message */
      int (*transmit)(void *tpipe, unsigned char *msg, int msglen);

      /*! Flush any pending messages */
      int (*flush)(void);

      struct dahdi_dynamic_driver *next;
};

/*! \brief Receive a dynamic span message */
void dahdi_dynamic_receive(struct dahdi_span *span, unsigned char *msg, int msglen);

/*! \brief Register a dynamic driver */
int dahdi_dynamic_register(struct dahdi_dynamic_driver *driver);

/*! \brief Unregister a dynamic driver */
void dahdi_dynamic_unregister(struct dahdi_dynamic_driver *driver);

/*! Receive on a span.  The DAHDI interface will handle all the calculations for
   all member channels of the span, pulling the data from the readchunk buffer */
int dahdi_receive(struct dahdi_span *span);

/*! Prepare writechunk buffers on all channels for this span */
int dahdi_transmit(struct dahdi_span *span);

/*! Abort the buffer currently being receive with event "event" */
void dahdi_hdlc_abort(struct dahdi_chan *ss, int event);

/*! Indicate to DAHDI that the end of frame was received and rotate buffers */
void dahdi_hdlc_finish(struct dahdi_chan *ss);

/*! Put a chunk of data into the current receive buffer */
void dahdi_hdlc_putbuf(struct dahdi_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 */
int dahdi_hdlc_getbuf(struct dahdi_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 */
int dahdi_register(struct dahdi_span *span, int prefmaster);

/*! Allocate / free memory for a transcoder */
struct dahdi_transcoder *dahdi_transcoder_alloc(int numchans);
void dahdi_transcoder_free(struct dahdi_transcoder *ztc);

/*! \brief Register a transcoder */
int dahdi_transcoder_register(struct dahdi_transcoder *tc);

/*! \brief Unregister a transcoder */
int dahdi_transcoder_unregister(struct dahdi_transcoder *tc);

/*! \brief Alert a transcoder */
int dahdi_transcoder_alert(struct dahdi_transcoder_channel *ztc);

/*! \brief Unregister a span */
int dahdi_unregister(struct dahdi_span *span);

/*! \brief Gives a name to an LBO */
char *dahdi_lboname(int lbo);

/*! \brief Tell DAHDI about changes in received rbs bits */
void dahdi_rbsbits(struct dahdi_chan *chan, int bits);

/*! \brief Tell DAHDI abou changes in received signalling */
void dahdi_hooksig(struct dahdi_chan *chan, enum dahdi_rxsig rxsig);

/*! \brief Queue an event on a channel */
void dahdi_qevent_nolock(struct dahdi_chan *chan, int event);

/*! \brief Queue an event on a channel, locking it first */
void dahdi_qevent_lock(struct dahdi_chan *chan, int event);

/*! \brief Notify a change possible change in alarm status on a channel */
void dahdi_alarm_channel(struct dahdi_chan *chan, int alarms);

/*! \brief Notify a change possible change in alarm status on a span */
void dahdi_alarm_notify(struct dahdi_span *span);

/*! \brief Initialize a tone state */
void dahdi_init_tone_state(struct dahdi_tone_state *ts, struct dahdi_tone *zt);

/*! \brief Get a given MF tone struct, suitable for dahdi_tone_nextsample. */
struct dahdi_tone *dahdi_mf_tone(const struct dahdi_chan *chan, char digit, int digitmode);

/* 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
   as possible.  ECHO CANCELLATION IS NO LONGER AUTOMATICALLY DONE
   AT THE DAHDI LEVEL.  dahdi_ec_chunk will not echo cancel if it should
   not be doing so.  rxchunk is modified in-place */

void dahdi_ec_chunk(struct dahdi_chan *chan, unsigned char *rxchunk, const unsigned char *txchunk);
void dahdi_ec_span(struct dahdi_span *span);

extern struct file_operations *dahdi_transcode_fops;

/* Don't use these directly -- they're not guaranteed to
   be there. */
extern short __dahdi_mulaw[256];
extern short __dahdi_alaw[256];
#ifdef CONFIG_CALC_XLAW
u_char __dahdi_lineartoulaw(short a);
u_char __dahdi_lineartoalaw(short a);
#else
extern u_char __dahdi_lin2mu[16384];
extern u_char __dahdi_lin2a[16384];
#endif

/*! \brief Used by dynamic DAHDI -- don't use directly */
void dahdi_set_dynamic_ioctl(int (*func)(unsigned int cmd, unsigned long data));

/*! \brief Used by DAHDI HPEC module -- don't use directly */
void dahdi_set_hpec_ioctl(int (*func)(unsigned int cmd, unsigned long data));

/*! \brief Used privately by DAHDI.  Avoid touching directly */
01071 struct dahdi_tone {
      int fac1;
      int init_v2_1;
      int init_v3_1;

      int fac2;
      int init_v2_2;
      int init_v3_2;

01080       int tonesamples;        /*!< How long to play this tone before 
                                 going to the next (in samples) */
      struct dahdi_tone *next;            /* Next tone in this sequence */

      int modulate;
};

static inline short dahdi_tone_nextsample(struct dahdi_tone_state *ts, struct dahdi_tone *zt)
{
      /* follow the curves, return the sum */

      int p;

      ts->v1_1 = ts->v2_1;
      ts->v2_1 = ts->v3_1;
      ts->v3_1 = (zt->fac1 * ts->v2_1 >> 15) - ts->v1_1;

      ts->v1_2 = ts->v2_2;
      ts->v2_2 = ts->v3_2;
      ts->v3_2 = (zt->fac2 * ts->v2_2 >> 15) - ts->v1_2;

      /* Return top 16 bits */
      if (!ts->modulate) return ts->v3_1 + ts->v3_2;
      /* we are modulating */
      p = ts->v3_2 - 32768;
      if (p < 0) p = -p;
      p = ((p * 9) / 10) + 1;
      return (ts->v3_1 * p) >> 15;

}

static inline short dahdi_txtone_nextsample(struct dahdi_chan *ss)
{
      /* follow the curves, return the sum */

      ss->v1_1 = ss->v2_1;
      ss->v2_1 = ss->v3_1;
      ss->v3_1 = (ss->txtone * ss->v2_1 >> 15) - ss->v1_1;
      return ss->v3_1;
}

/* These are the right functions to use.  */

#define DAHDI_MULAW(a) (__dahdi_mulaw[(a)])
#define DAHDI_ALAW(a) (__dahdi_alaw[(a)])
#define DAHDI_XLAW(a,c) (c->xlaw[(a)])

#ifdef CONFIG_CALC_XLAW
#define DAHDI_LIN2MU(a) (__dahdi_lineartoulaw((a)))
#define DAHDI_LIN2A(a) (__dahdi_lineartoalaw((a)))

#define DAHDI_LIN2X(a,c) ((c)->lineartoxlaw((a)))

#else
/* Use tables */
#define DAHDI_LIN2MU(a) (__dahdi_lin2mu[((unsigned short)(a)) >> 2])
#define DAHDI_LIN2A(a) (__dahdi_lin2a[((unsigned short)(a)) >> 2])

/* Manipulate as appropriate for x-law */
#define DAHDI_LIN2X(a,c) ((c)->lin2x[((unsigned short)(a)) >> 2])

#endif /* CONFIG_CALC_XLAW */

/* Data formats for capabilities and frames alike (from Asterisk) */
/*! G.723.1 compression */
01145 #define DAHDI_FORMAT_G723_1   (1 << 0)
/*! GSM compression */
01147 #define DAHDI_FORMAT_GSM            (1 << 1)
/*! Raw mu-law data (G.711) */
01149 #define DAHDI_FORMAT_ULAW           (1 << 2)
/*! Raw A-law data (G.711) */
01151 #define DAHDI_FORMAT_ALAW           (1 << 3)
/*! ADPCM (G.726, 32kbps) */
01153 #define DAHDI_FORMAT_G726           (1 << 4)
/*! ADPCM (IMA) */
01155 #define DAHDI_FORMAT_ADPCM          (1 << 5)
/*! Raw 16-bit Signed Linear (8000 Hz) PCM */
01157 #define DAHDI_FORMAT_SLINEAR  (1 << 6)
/*! LPC10, 180 samples/frame */
01159 #define DAHDI_FORMAT_LPC10          (1 << 7)
/*! G.729A audio */
01161 #define DAHDI_FORMAT_G729A          (1 << 8)
/*! SpeeX Free Compression */
01163 #define DAHDI_FORMAT_SPEEX          (1 << 9)
/*! iLBC Free Compression */
01165 #define DAHDI_FORMAT_ILBC           (1 << 10)
/*! Maximum audio format */
01167 #define DAHDI_FORMAT_MAX_AUDIO      (1 << 15)
/*! Maximum audio mask */
01169 #define DAHDI_FORMAT_AUDIO_MASK     ((1 << 16) - 1)

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
#define kzalloc(a, b) kcalloc(1, a, b)
#endif

#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
static inline void list_replace(struct list_head *old, struct list_head *new)
{
        new->next = old->next;
        new->next->prev = new;
        new->prev = old->prev;
        new->prev->next = new;
}
#endif

#ifndef DMA_BIT_MASK
#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1))
#endif

#endif /* _DAHDI_KERNEL_H */

Generated by  Doxygen 1.6.0   Back to index