/*****************************************************************************/

/*
 *      trx.h  --  Transceiver control master include file.
 *
 *      Copyright (C) 2000-2001
 *          Thomas Sailer (t.sailer@alumni.ethz.ch)
 *
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 2 of the License, or
 *      (at your option) any later version.
 *
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  Please note that the GPL allows you to use the driver, NOT the radio.
 *  In order to use the radio, you need a license from the communications
 *  authority of your country.
 *
 *  History:
 *   0.1  19.09.2000  Created
 *
 */

/*****************************************************************************/

#ifndef _TRX_H
#define _TRX_H

/* --------------------------------------------------------------------- */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "sysdeps.h"
#include "trxapi.h"
#include "usbdrv.h"
#include "list.h"

#if defined(ORBITIPC)
#include "trxctrl.h"
#endif

#if !defined(WIN32)
#include <pthread.h>
#endif

#if defined(HAVE_SYS_SOCKET_H) && !defined(WIN32)
#include <sys/socket.h>
#endif

#ifdef HAVE_LINUX_IF_H
#include <linux/if.h>
#endif

#if defined(HAVE_DIRECTX)
#include <directx.h>
#endif

#if defined(HAVE_WINDOWS_H)
#include <windows.h>
#endif

#if defined(WIN32)
#include "flexdrv.h"
#endif

/* ---------------------------------------------------------------------- */

#define BAYCOMUSB_VENDORID         0xbac0
#define BAYCOMUSB_PRODUCTID_EMPTY  0x6134
#define BAYCOMUSB_PRODUCTID_FPGALD 0x6135
#define BAYCOMUSB_PRODUCTID_MODEM  0x6136
#define BAYCOMUSB_PRODUCTID_AUDIO  0x6137

/* --------------------------------------------------------------------- */


#if defined(WIN32)

#define IORREGHKEY     HKEY_LOCAL_MACHINE
#define IORREGPATH     "SOFTWARE\\FlexNet\\Transceivers"

#define SERVICENAME        "baycomusb_server"
#define SERVICEDISPLAYNAME "Baycom USBFLEX Modem"

#define USECRITICALSECT

#else

#define IORIDPATH "/var/hamradio/transceivers"
#define NETIFMUXDEV  "/dev/baycomusb"

#endif

/* --------------------------------------------------------------------- */

#if defined(WIN32)
#define NUMTXPACKETS         32
#define NUMRXPACKETS         32
#else
#define MAXFLEN             512

#define NUMTXPACKETS         16
#define NUMRXPACKETS          1
#endif
#define NUMAUDIOURB           4
#define NUMFRAMESPERURB      32
#define AUDIOSAMPLINGRATE 16000
#define AUDIOBUFSIZE      16384
#define INTERRUPT_INTERVAL   10  /* poll interrupt pipe every 10ms */
#define UARTTXDELAY           4

#define AUDIOOVERLAP         32
#define AUDIOFILTERLEN       8U
#define AUDIONUMFILTER      32U
#define AUDIOFILTERIDX(x)    (((x) >> 11U) & 31U)
#define AUDIOFILTERSAMPLE(x) ((x)>>16)
#define AUDIOSRCPHASEFRAC    16
#define AUDIOSRCPHASEMASK    ((1<<AUDIOSRCPHASEFRAC)-1)

#define AUDIOSRCMAXRATIO      4

#define AUDIOSRCMINPHINC     ((1<<AUDIOSRCPHASEFRAC)/AUDIOSRCMAXRATIO)
#define AUDIOSRCMAXPHINC     ((1<<AUDIOSRCPHASEFRAC)*AUDIOSRCMAXRATIO)

/* --------------------------------------------------------------------- */

struct trx_thread_state {
	/* corba stuff; must be the first items! */
#if defined(ORBITIPC)
	POA_Trx_Control servant;
	PortableServer_POA poa;
	char ior[256];
#endif

	/* private stuff */
	struct list_head device_list;
	struct usbdevice *usbdev;
	char serial[16];

#if defined(WIN32)
	HANDLE hshmem;
	HANDLE hmutex;
	HANDLE hevent;
	HANDLE hflxtxevent;
	HANDLE hflxrxevent;
	int devidx;
	int globalidx;
	/* old win32 stuff */
	char iorrname[10];

#else
	pthread_mutex_t mutex;
	int devnr, busnr;
	int netif_fd;
	char ifname[IFNAMSIZ];
	char iorfname[1024];
#if defined(USERMODEDRV)

#define KISSINBUF_SIZE    (2*MAXFLEN+8)

	int netif_fdmaster;
	unsigned int slottime;

        struct {
                int ioerr;
                unsigned iframelen, ibufptr;
                unsigned char ibuf[KISSINBUF_SIZE];
        } kiss;

        struct {
                unsigned int kiss_in;
                unsigned int kiss_inerr;
                unsigned int kiss_out;
                unsigned int kiss_outerr;
                unsigned int pkt_in;
                unsigned int pkt_out;
        } stat;
#endif
#endif

	/* buffering */
#if defined(WIN32) || defined(USERMODEDRV)

	/*  1 URB for control */
	/*  1 URB for interrupt input */
	/* tx URBs for transmit packets */
	/* tx URBs for receive packets */
	/* some URBs for Audio IO */

#define URBSTATE_UNUSED     0
#define URBSTATE_FILLED     1
#define URBSTATE_INPROGRESS 2
#define URBSTATE_DONE       3
#define URBSTATE_CORBASEND  4

	unsigned int netif_opened;

	struct {
		unsigned int urbstate;
		unsigned int nexttime;
		struct usbdevfs_urb urb;
		unsigned char buf[20];
	} iurb;

	struct {
		unsigned int urbstate;
		unsigned int starttime;
		struct usbdevfs_urb urb;
		union {
			struct usb_control_request creq;
			unsigned char buf[16];
		} buf;
	} curb;

	union {
		/* packet IO */
		struct {
			unsigned int rxurbptr;

			struct {
				unsigned int urbstate;
				struct usbdevfs_urb urb;
				union {
					unsigned char buf[MAXFLEN];
#if defined(WIN32)
					L1FRAME frame;
					unsigned char buf2[sizeof(L1FRAME)+2];
#endif
				} b;
			} rxurb[NUMRXPACKETS], txurb[NUMTXPACKETS];
		} p;
		/* audio IO */
		struct {
			struct {
				unsigned int urbstate;
				struct usbdevfs_urb urb;
				struct usbdevfs_iso_packet_desc isodesc[NUMFRAMESPERURB];
				signed char buf[NUMFRAMESPERURB*(AUDIOSAMPLINGRATE/1000)];
			} inurb[NUMAUDIOURB], outurb[NUMAUDIOURB];
#if defined(WIN32)
#if defined(HAVE_DIRECTX)
			struct {
				/* low level driver specific data */
				LPDIRECTSOUND dsplay;
				LPDIRECTSOUNDCAPTURE dsrec;
				LPDIRECTSOUNDBUFFER playbuf;
				LPDIRECTSOUNDCAPTUREBUFFER recbuf;
				DWORD playbufsz, recbufsz, playptr, recptr;
			} io;
#endif
#else
			struct {
				/* low level driver specific data */
				int fdin, fdout;
				unsigned int inzerosamples;
			} io;
#endif
			struct {
				/* samling rates */
				unsigned int srateusb, sratedspin, sratedspout;
			} p;

			struct {
				/* sampling rate conversion state */
				int16_t sample[AUDIOOVERLAP];
				/* sampling rate converter */
				unsigned int ph, phinc;
				/* power meter */
				unsigned int pwrcnt;
				unsigned int pwracc;
				/* freqency generators */
				unsigned int ph0, ph1, freq0, freq1;
				/* power for display */
				float sigpwr;
				/* filter */
				int16_t filter[AUDIONUMFILTER][AUDIOFILTERLEN];
				/* audio buffer */
				unsigned int aptr;
				int8_t abuf[AUDIOBUFSIZE];
			} isrc;

			struct {
				/* sampling rate conversion state */
				int16_t sample[AUDIOOVERLAP];
				/* sampling rate converter */
				unsigned int ph, phinc;
				/* power meter */
				unsigned int pwrcnt, pwrcnt2;
				unsigned int pwracc1;
				int pwracc2, pwracc3;
				float pwracc4;
				/* power for display */
				float sigpwr;
				float noisepwr;
				/* filter */
				int16_t filter[AUDIONUMFILTER][AUDIOFILTERLEN];
				/* audio buffer */
				unsigned int aptr;
				int8_t abuf[AUDIOBUFSIZE];
			} osrc;
		} a;
	} du;

	struct {
		unsigned char rfsquelch;
		unsigned char audiosquelch;
	} audioparam;

#endif

	/* transceiver state */
	unsigned int mode, bitraterx, bitratetx, txdmul;
	unsigned int rxdiv, txdiv;
	unsigned int newrxdiv, newtxdiv;
	unsigned int dcd, ptt, uarttxempty;
	unsigned int rssi, flags;
	unsigned int t7fport, leds;
	unsigned int flexnetlock;

	/* adapter configuration */
	struct {
	        struct trxapi_baycomusb_adapter_config adapt;
		struct trxapi_modem_disconnect_config mdisc;
#if !defined(WIN32)
		struct trxapi_channel_access_config chacc;
		struct trxapi_interface_config intf;
#else
		struct {
			unsigned long txdelay;
			unsigned int fulldup;
		} chacc;
#endif
		struct {
			trxapi_frequency_t rx;
			trxapi_frequency_t tx;
		} freq;
       	} cfg;

	struct txuartfifo {
		unsigned int rd, wr;
		unsigned char buf[512];
	} tfifo;

        struct rxuartfifo {
                unsigned int wr;
                unsigned char buf[512];
        } rfifo;



};

#define FLG_RELOADMODEM          (1 << 0)
#define FLG_RECONFINTF           (1 << 1)
#define FLG_RECONFCHACC          (1 << 2)
#define FLG_SETMDISCDIR          (1 << 3)
#define FLG_SETMDISCOUT          (1 << 4)
#define FLG_SETT7FPORT           (1 << 5)
#define FLG_SETFREQ              (1 << 6)
#define FLG_MANUALPTT            (1 << 7)
#define FLG_SETPTT               (1 << 8)
#define FLG_CLRPTT               (1 << 9)
#define FLG_INHIBITSETPTT        (1 << 10)
#define FLG_T7FERROR             (1 << 11)
#define FLG_SETLEDS              (1 << 12)
#define FLG_MODEMERROR           (1 << 13)
#define FLG_SAVECONFIG           (1 << 14)

#define MODE_NONE       0
#define MODE_FSK        1
#define MODE_EXTERNAL   2
#define MODE_AFSK       3
#define MODE_AUDIO      4
#define MODE_BSCAN      5
#define MODE_DEAD    (~0)

#define RSSI_MIN     (-143.0)
#define RSSI_MAX     (-58.0)

extern int polldevice(struct trx_thread_state *state);

/*
 * in server.c
 */

#if defined(WIN32)
extern void init_shmem_object(struct trx_thread_state *state);
extern void destroy_shmem_object(struct trx_thread_state *state);
#else
extern inline void init_shmem_object(struct trx_thread_state *state) {}
extern inline void destroy_shmem_object(struct trx_thread_state *state) {}
#endif

#if defined(ORBITIPC)
extern CORBA_ORB orb;
extern PortableServer_POA poa;

extern void init_object(struct trx_thread_state *state);
extern void destroy_object(struct trx_thread_state *state);
extern int server_init1(int *argc, char **argv);
extern int server_init2(void);
#else
extern inline void init_object(struct trx_thread_state *state) {}
extern inline void destroy_object(struct trx_thread_state *state) {}
extern inline int server_init1(int *argc, char **argv) { return 0; }
extern inline int server_init2(void) { return 0; }
#endif

/*
 * in main*.c
 */

extern void acquire_orbit_mutex(void);
extern void release_orbit_mutex(void);
extern void acquire_trxdata_mutex(struct trx_thread_state *state);
extern void release_trxdata_mutex(struct trx_thread_state *state);

extern int check_quit(void);
extern int reopen_usbdev(struct trx_thread_state *state);

extern void netif_close(struct trx_thread_state *state);
extern int netif_open(struct trx_thread_state *state);


/*
 * in cfgadapt.c
 */

extern int adapter_init_getserial(struct trx_thread_state *state);
extern int adapter_finalinit(struct trx_thread_state *state);
extern int adapter_reset(struct usbdevice *dev);

/*
 * in cfg*.c
 */

extern int config_load(const char *name);
extern int config_save(void);
extern void config_loaddevice(struct trx_thread_state *state);
extern void config_savedevice(struct trx_thread_state *state);


/*
 * in audio*.c
 */

extern void audio_globalinit(void);
extern struct trxapi_baycomusb_adapter_audio_devs *audio_get_device_list(void);
extern void audio_open(struct trx_thread_state *state);
extern void audio_close(struct trx_thread_state *state);
extern void audio_input(struct trx_thread_state *state, const signed char *samples, unsigned int nrsamples);
extern void audio_output(struct trx_thread_state *state, signed char *samples, unsigned int nrsamples);

extern void audioproc_init(struct trx_thread_state *state);
extern unsigned int audioproc_convertinput_isamples(struct trx_thread_state *state, unsigned int osamples);
extern void audioproc_convertinput(struct trx_thread_state *state, unsigned int inum, unsigned int onum, const int16_t *ibuf, signed char *obuf);
extern int audioproc_adjustinput(struct trx_thread_state *state, unsigned int usbdelay);
extern unsigned int audioproc_convertoutput(struct trx_thread_state *state, unsigned int inum, const signed char *ibuf, int16_t *obuf);
extern int audioproc_adjustoutput(struct trx_thread_state *state, unsigned int dspdelay);

extern int audioproc_drvinit(const char *config);
extern void audioproc_ptt(int ptt);

extern void audioproc_1750(int on);
extern void audioproc_dtmf(int ch);
extern void audioproc_setsquelch(int sq);
extern int audioproc_getsquelch(void);


extern const int16_t costab[512];
#define COS(x) costab[((x)>>7)&0x1ff]
#define SIN(x) COS((x)+0xc000)
 
#define SNDLATENCY    (AUDIOSAMPLINGRATE/4)   /* approx 1/4 seconds */

/*
 * common.c
 */

extern void addrxfifo(struct trx_thread_state *ctrl, const unsigned char *rp, unsigned int rlen);
extern unsigned int getrxfifo(struct trx_thread_state *ctrl, unsigned int *ptr, unsigned char *p, unsigned int len);
extern int addtxfifo(struct trx_thread_state *ctrl, const unsigned char *tp, unsigned int tlen);
extern int checkreload_adapt(struct trx_thread_state *servant, struct trxapi_baycomusb_adapter_config *cfg);
extern int checkreload_mdisc(struct trx_thread_state *servant, struct trxapi_modem_disconnect_config *cfg);
extern void trx_thread(struct trx_thread_state *state);
extern int getuartline(struct trx_thread_state *ctrl, unsigned int *ptr, unsigned char *buf, size_t bufsz, unsigned int timeout);

/*
 * mainwin32.c
 */

#if defined(WIN32)

#define MAXUSBMODEMS   8

#define BAYUSBSIGNATURE  "baycomusbv1"

struct win32_global_state {
	char signature[16];
	unsigned int processid;
	struct {
		HANDLE hshmem;
	} modem[MAXUSBMODEMS];
};




/* KB Q164787 */
extern void CALLBACK server_entry_cmdline(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
extern int server_entry_parse_argv(int argc, char *argv[]);
extern int server_entry_run(void);
extern void server_entry_quit(void);
#endif


/* --------------------------------------------------------------------- */
#endif /* _TRX_H */
