/*---------------------------------------------------------------------------*\
	vtmodule.h
	Common header file for all modules connecting to the vtcore module
	Author: Ben Kramer, 25 October 2005
	        Ron Lee, 8 Jun 2006
\*---------------------------------------------------------------------------*/

#ifndef __VTMODULE__
#define __VTMODULE__

#include <linux/cdev.h>

#include "linringbuf.h"


#define PCI_VENDOR_ID_VOICETRONIX	0x5654

#define FRAME 8             // Frame size for real time data
#define ID_DATA_MAXSIZE 31  // Maximum length for descriptive text

/* Channel states */
#define CH_IDLE		0
#define CH_OFFHOOK	1
#define CH_MONITOR	2

/* Channel Codecs */
#define VT_LINEAR       1
#define VT_MULAW        2
#define VT_ALAW         3


#define BRIDGEBUF_SIZE  8			// Must be a power of 2.
#define BRIDGEBUF_MAX   (BRIDGEBUF_SIZE - 1)
#define BRIDGEBUF_LAG   1
// XXX Revisit this.
// This adds 4ms of delay which, when added to other delays, can be the
// difference between confortable side tone and an annoying echo.  If we
// are more than 1ms behind, then we are sort of deep in the merde anyhow,
// so hopefully the above will be enough.
//#define BRIDGEBUF_LAG   (BRIDGEBUF_SIZE / 2)

struct bridge {
	short       buffer[FRAME * BRIDGEBUF_SIZE];
	int         in;
	int         out;
	int	    active;
	spinlock_t  lock;
	//XXX Back ref to channel?  See VT_IOC_LISTEN.
};

/* Channel structure */
struct channel {
	int             porttype;
	int             state;
	int             codec;
	const char     *country;
	struct bridge  *bridgetx;
	struct bridge   bridgerx;
	unsigned char   txbuf[FRAME];
	unsigned char   rxbuf[FRAME];
	void           *txfifo;
	void           *rxfifo;
	int             tx_empty;
	void           *echocan;

	spinlock_t	    tap_read_lock;
	lring_buf	    tap_buf;
	wait_queue_head_t   tap_wait;

	int		    tap_buf_state;
	int		    tap_state;

	struct bridge	    tap_bridge;
	u16		    tap_frame[FRAME];

	struct proc_dir_entry *procfs_root;

#ifdef FIFOSTATS
	int    max_rxfifo;
	int    min_rxfifo;
	int    total_rxfifo;
	int    rxfifo_samples;
#endif
};

// Flags to indicate the state of the tap buffer.
#define TAP_BUF_UNUSED	0
#define TAP_BUF_INIT	1
#define TAP_BUF_ACTIVE	2

// Flags to indicate the state of the latest tap frame.
#define TAP_WRITE_HALF	1
#define TAP_READ_HALF	2

struct vtboard {
	struct module  *owner;
	int             boardnum;                // index into the vtcore board list
	const char     *name;                    // descriptive board name
	char            serial[ID_DATA_MAXSIZE+1]; // Unique board id
	int             maxports;                // maximum number of ports onboard

	//XXX We must hold the module lock to access any of these
	struct channel *chans;                  // pointer to [maxports] channels

//	void *frametxbuf;
//	void *framerxbuf;
//	void *rxmsgq;
	void *txmsgq;

	int (*ioctl)(struct vtboard *board, int port, unsigned int cmd, void *data, int length);

	// The set_ functions should all return 0 on success or errno on
	// failure.  The get functions should set the err parameter to 0
	// on success or errno on failure.
	int (*set_country)(struct vtboard *board, int port, const char *country);
	// gain = 0 - 0xff, 0x80 = 0dB
	int (*set_playgain)(struct vtboard *board, int port, int gain);
	int (*get_playgain)(struct vtboard *board, int port, int *err);
	int (*set_recgain)(struct vtboard *board, int port, int gain);
	int (*get_recgain)(struct vtboard *board, int port, int *err);
	// hook = CH_IDLE, CH_MONITOR, CH_OFFHOOK
	int (*set_hook)(struct vtboard *board, int port, int hook);
	int (*get_hook)(struct vtboard *board, int port, int *err);
	//XXX this is wrong:
	// ring = 0 - off, 1 - ring once, 2 - ring until answered
	int (*set_ring)(struct vtboard *board, int port, int ring);
	int (*get_ring)(struct vtboard *board, int port, int *err);
	// polarity = 1 is forward, -1 is reverse
	int (*set_polarity)(struct vtboard *board, int port, int polarity);
	int (*get_polarity)(struct vtboard *board, int port, int *err);
	int (*get_linevolt)(struct vtboard *board, int port, int *err);

	dev_t                  tap_dev;
	struct cdev            tap_cdev;

	struct proc_dir_entry *procfs_root;
};

/* output:    is to be transmited out the card
 * input:     what was just received on the card
 * reference: what we were about to transmit out the card
 * samples:   the number of linear samples in each array
 */
struct vtecho {
	struct module *owner;
	char desc[ID_DATA_MAXSIZE+1];
	void (*vtecho_open)(struct channel *chan);
	void (*vtecho_proc)(struct channel *chan, short *output, short *input,
						short *reference, int samples);
	void (*vtecho_close)(struct channel *chan);
};

int vt_board_register(struct vtboard *board);
void vt_board_unregister(struct vtboard *board);
void vt_echo_register(struct vtecho *ec);
void vt_echo_unregister(struct vtecho *ec);

void vt_write(struct vtboard *board);
void vt_read(struct vtboard *board);
int vt_send_event(struct vtboard *board, char *mess, int size);

const struct file_operations vt_int_proc_fops;
const struct file_operations vt_string_proc_fops;
void vt_create_board_proc_const_int(struct vtboard *board, const char *node, long val);

#endif
