⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wcfxsusb.c

📁 This a SOFTWARE pbx DRIVER
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Wildcard S100U USB FXS Interface Zapata Telephony Driver * * Written by Mark Spencer <markster@linux-support.net> *            Matthew Fredrickson <creslin@linux-support.net> * * Copyright (C) 2001, Linux Support Services, Inc. * * All rights reserved. * * 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.  * *//* Save power at the expense of not always being able to transmit on hook.  If   this is set, we only transit on hook for some time after a ring    (POWERSAVE_TIMEOUT) */#define PROSLIC_POWERSAVE#define POWERSAVE_TIME 4000#include <linux/kernel.h>#include <linux/errno.h>#include <linux/module.h>#include <linux/pci.h>#include <linux/init.h>#include <linux/usb.h>#include <linux/errno.h>#include <linux/version.h>#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,19)#define USB2420#endif#ifdef STANDALONE_ZAPATA#include "zaptel.h"#else#include <linux/zaptel.h>#endif /* STANDALONE_ZAPATA */#include "wcfxsusb.h"#include "proslic.h"#ifdef DEBUG_WILDCARD#define DPRINTK(x) printk x#else#define DPRINTK(x)#endif// Function prototypesstatic int readProSlicDirectReg(struct usb_device *dev, unsigned char address, unsigned char* data);static int initializeIndirectRegisters(struct usb_device *dev);static int verifyIndirectRegisters(struct usb_device *dev);static int writeProSlicDirectReg(struct usb_device *dev, unsigned char address, unsigned char data);static int writeProSlicInDirectReg(struct usb_device *dev, unsigned char address, unsigned short data);static int readProSlicInDirectReg(struct usb_device *dev, unsigned char address, unsigned short *data);static int writeProSlicInDirectReg(struct usb_device *dev, unsigned char address, unsigned short data);static alpha  indirect_regs[] ={{0,"DTMF_ROW_0_PEAK",0x55C2},{1,"DTMF_ROW_1_PEAK",0x51E6},{2,"DTMF_ROW2_PEAK",0x4B85},{3,"DTMF_ROW3_PEAK",0x4937},{4,"DTMF_COL1_PEAK",0x3333},{5,"DTMF_FWD_TWIST",0x0202},{6,"DTMF_RVS_TWIST",0x0202},{7,"DTMF_ROW_RATIO_TRES",0x0198},{8,"DTMF_COL_RATIO_TRES",0x0198},{9,"DTMF_ROW_2ND_ARM",0x0611},{10,"DTMF_COL_2ND_ARM",0x0202},{11,"DTMF_PWR_MIN_TRES",0x00E5},{12,"DTMF_OT_LIM_TRES",0x0A1C},{13,"OSC1_COEF",0x6D40},{14,"OSC1X",0x0470},{15,"OSC1Y",0x0000},{16,"OSC2_COEF",0x4A80},{17,"OSC2X",0x0830},{18,"OSC2Y",0x0000},{19,"RING_V_OFF",0x0000},{20,"RING_OSC",0x7EF0},{21,"RING_X",0x0160},{22,"RING_Y",0x0000},{23,"PULSE_ENVEL",0x2000},{24,"PULSE_X",0x2000},{25,"PULSE_Y",0x0000},//{26,"RECV_DIGITAL_GAIN",0x4000},	// playback volume set lower{26,"RECV_DIGITAL_GAIN",0x2000},	// playback volume set lower{27,"XMIT_DIGITAL_GAIN",0xc000 /* was 0x4000 */ },{28,"LOOP_CLOSE_TRES",0x1000},{29,"RING_TRIP_TRES",0x3600},{30,"COMMON_MIN_TRES",0x1000},{31,"COMMON_MAX_TRES",0x0200},{32,"PWR_ALARM_Q1Q2",0x0550},{33,"PWR_ALARM_Q3Q4",0x2600},{34,"PWR_ALARM_Q5Q6",0x1B80},{35,"LOOP_CLOSURE_FILTER",0x8000},{36,"RING_TRIP_FILTER",0x0320},{37,"TERM_LP_POLE_Q1Q2",0x0100},{38,"TERM_LP_POLE_Q3Q4",0x0100},{39,"TERM_LP_POLE_Q5Q6",0x0010},{40,"CM_BIAS_RINGING",0x0C00},{41,"DCDC_MIN_V",0x0C00},{42,"DCDC_XTRA",0x1000},};#define WCUSB_SPORT0				0x26#define WCUSB_SPORT1				0x27#define WCUSB_SPORT2				0x28#define WCUSB_SPORT_CTRL		0x29#define WC_AUX0	0x1#define WC_AUX1 0x2#define WC_AUX2 0x4#define WC_AUX3 0x8#define CONTROL_TIMEOUT_MS		(500)		/* msec */#define CONTROL_TIMEOUT_JIFFIES ((CONTROL_TIMEOUT_MS * HZ) / 1000)#define REQUEST_NORMAL 4#define FLAG_RUNNING	(1 << 0)static int debug = 0;struct stinky_urb {#ifdef USB2420	struct urb urb;	struct iso_packet_descriptor isoframe[1];#else	urb_t urb;	iso_packet_descriptor_t isoframe[1];#endif};typedef enum {	STREAM_NORMAL,	STREAM_DTMF,} stream_t;typedef enum {	STATE_WCREAD_WRITEREG,	STATE_WCREAD_READRES,	STATE_WCWRITE_WRITEREG,	STATE_WCWRITE_WRITERES,} control_state_t;typedef enum {	WC_KEYPAD,	WC_PROSLIC,} dev_type_t;typedef enum {	STATE_FOR_LOOP_1_OUT,	STATE_FOR_LOOP_2_IN,	STATE_FOR_LOOP_PROC_DATA,	STATE_FOR_LOOP_CLEAR_DIGIT,} keypad_state_t;struct wc_keypad_data {	/* Keypad state monitoring variables */	keypad_state_t state;#ifdef USB2420	struct urb urb;#else	urb_t urb;#endif	int running;	char data;	char data12;	char tmp;	int scanned_event;	int i;	int count;	/* DTMF tone generation stuff for zaptel */	struct zt_tone_state ts;	struct zt_tone *tone;};#define WC_IO_READ	(1 << 0)#define WC_IO_WRITE	(1 << 1)#define IO_READY(x)	(((x) & (WC_IO_READ | WC_IO_WRITE)) == \			      (WC_IO_READ | WC_IO_WRITE))struct wc_usb_pvt {	struct usb_device *dev;	dev_type_t devclass;	unsigned int readpipe;	unsigned int writepipe;	int usecount;	int dead;	int hardwareflags;	struct zt_span span;	struct zt_chan chan;	struct stinky_urb dataread[2];	struct stinky_urb datawrite[2];	int iostate;	/* Whether reads/writes are complete */#ifdef USB2420	struct urb *pendingurb;	/* Pending URB for transmission */	struct urb 		control;	struct usb_ctrlrequest	dr;#else	urb_t *pendingurb;	/* Pending URB for transmission */	urb_t 		control;	devrequest	dr;#endif	control_state_t controlstate;	int urbcount;	int flags;	int timer;	int lowpowertimer;	int idletxhookstate;	int hookstate;	__u8 newtxhook;	__u8 txhook;	int pos;	unsigned char auxstatus;	unsigned char wcregindex;	unsigned char wcregbuf[4];	unsigned char wcregval;	short readchunk[ZT_MAX_CHUNKSIZE * 2];	short writechunk[ZT_MAX_CHUNKSIZE * 2];	stream_t sample;	void *pvt_data;};struct wc_usb_desc {	char *name;	int flags;};#define FLAG_FLIP_RELAYS	(1 << 0)static struct wc_usb_desc wcusb = { "Wildcard S100U USB FXS Interface" };static struct wc_usb_desc wcusb2 = { "Wildcard S110U USB FXS Interface", FLAG_FLIP_RELAYS };static struct wc_usb_desc wc_usb_phone = { "Wildcard Phone Test driver" };static struct wc_usb_pvt *ifaces[WC_MAX_IFACES];static void wcusb_check_keypad(struct wc_usb_pvt *p);static int set_aux_ctrl(struct wc_usb_pvt *p, char auxpins, int on);static int Wcusb_WriteWcRegs(struct usb_device *dev, unsigned char index, 					  unsigned char *data, int len){	unsigned int pipe = usb_sndctrlpipe(dev, 0);	int requesttype;	int res;	requesttype = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;	res = usb_control_msg(dev, pipe, REQUEST_NORMAL, requesttype, 							0, index, data, len, CONTROL_TIMEOUT_JIFFIES);	if (res == -ETIMEDOUT) {		printk("wcusb: timeout on vendor write\n");		return -1;	} else if (res < 0) {		printk("wcusb: Error executing control: status=%d\n", le32_to_cpu(res));		return -1;	}	return 0;}					  static int Wcusb_ReadWcRegs(struct usb_device *dev, unsigned char index, 					  unsigned char *data, int len){	unsigned int pipe = usb_rcvctrlpipe(dev, 0);	int requesttype;	int res;	requesttype = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE;	res = usb_control_msg(dev, pipe, REQUEST_NORMAL, requesttype, 							0, index, data, len, CONTROL_TIMEOUT_JIFFIES);	if (res == -ETIMEDOUT) {		printk("wcusb: timeout on vendor write\n");		return -1;	} else if (res < 0) {		printk("wcusb: Error executing control: status=%d\n", le32_to_cpu(res));		return -1;	} else {		DPRINTK(("wcusb: Executed read, result = %d (data = %04x)\n", le32_to_cpu(res), (int) *data));	}	return 0;}					  #ifdef USB2420static int wcusb_async_read(struct wc_usb_pvt *p, unsigned char index, unsigned char *data, int len, int state, void (*complete)(struct urb *urb));static int wcusb_async_write(struct wc_usb_pvt *p, unsigned char index, unsigned char *data, int len, int state, void (*complete)(struct urb *urb));static void wcusb_async_control(struct urb *urb);#elsestatic int wcusb_async_read(struct wc_usb_pvt *p, unsigned char index, unsigned char *data, int len, int state, void (*complete)(urb_t *urb));static int wcusb_async_write(struct wc_usb_pvt *p, unsigned char index, unsigned char *data, int len, int state, void (*complete)(urb_t *urb));static void wcusb_async_control(urb_t *urb);#endifstatic void proslic_read_direct_async(struct wc_usb_pvt *p, unsigned char address){	p->wcregindex = address;	p->wcregbuf[0] = address | 0x80;	p->wcregbuf[1] = 0;	p->wcregbuf[2] = 0;	p->wcregbuf[3] = 0x67;	wcusb_async_write(p, WCUSB_SPORT0, p->wcregbuf, 4, STATE_WCREAD_WRITEREG, wcusb_async_control);}static void proslic_write_direct_async(struct wc_usb_pvt *p, unsigned char address, unsigned char val){	p->wcregindex = address;	p->wcregbuf[0] = address & 0x7f;	p->wcregbuf[1] = val;	p->wcregbuf[2] = 0;	p->wcregbuf[3] = 0x27;	wcusb_async_write(p, WCUSB_SPORT0, p->wcregbuf, 4, STATE_WCWRITE_WRITERES, wcusb_async_control);}#ifdef USB2420static void wcusb_async_control(struct urb *urb)#elsestatic void wcusb_async_control(urb_t *urb)#endif{	struct wc_usb_pvt *p = urb->context;	p->urbcount--;	if (urb->status) {		printk("Error in transfer...\n");		p->timer = 50;		return;	}	if (!(p->flags & FLAG_RUNNING)) {		return;	}	switch (p->controlstate) {	case STATE_WCREAD_WRITEREG:		/* We've written the register to sport0, now read form sport 1 */		wcusb_async_read(p, WCUSB_SPORT1, &p->wcregval, 1, STATE_WCREAD_READRES, wcusb_async_control);		return;	case STATE_WCREAD_READRES:		switch(p->wcregindex) {		case 68:			if (!p->hookstate && (p->wcregval & 1)) {				p->hookstate = 1;				if (debug)					printk("Going off hook...\n");				zt_hooksig(&p->chan, ZT_RXSIG_OFFHOOK);			} else if (p->hookstate && !(p->wcregval & 1)) {				p->hookstate = 0;				if (debug)					printk("Going on hook...\n");				zt_hooksig(&p->chan, ZT_RXSIG_ONHOOK);			}			/* Set outgoing hook state if necessary */			if (p->txhook != p->newtxhook) {				if (debug)					printk("Really setting hook state to %d\n", p->newtxhook);				p->txhook = p->newtxhook;				proslic_write_direct_async(p, 64, p->newtxhook);			} else				p->timer = 50;			break;		case 64:			if (debug)				printk("Read hook state as %02x\n", p->wcregval);			p->timer = 50;			break;		default:			printk("dunno what to do with read/regindex %d\n", p->wcregindex);			p->wcregindex = 0;		}		return;	case STATE_WCWRITE_WRITERES:		switch(p->wcregindex) {		case 64:			if (debug) {				printk("Hook transition complete to %d\n", ((char *)(urb->transfer_buffer))[1]);#ifdef BOOST_RINGER			}			if (p->txhook == 4) {				/* Ringing -- boost battery to 96V */				proslic_write_direct_async(p, 74, 0x3f);			} else {				/* Leave battery at default 75V */				proslic_write_direct_async(p, 74, 0x32);			}			break;		case 74:			if (debug) {				printk("Battery set to -%dV\n", ((char *)(urb->transfer_buffer))[1] * 3 / 2);#endif				proslic_read_direct_async(p, 64);			} else				p->timer = 50;			break;		default:			printk("dunno what to do with write/regindex %d\n", p->wcregindex);			p->wcregindex = 0;		}		return;	default:		printk("async control in unknown state %d\n", p->controlstate);	}}#ifdef USB2420static void keypad_check_done(struct urb *urb)#elsestatic void keypad_check_done(urb_t *urb)#endif{	struct wc_usb_pvt *p = urb->context;	struct wc_keypad_data *d = p->pvt_data;	static char aux_pattern[] = {0x1e, 0x1d, 0x17, 0xf};	char digit = 'z';	p->urbcount--;	if (!d->running) {		printk("Stopping stream (check_done)\n");		return;	}	if (urb->status) {		printk("status %d\n", urb->status);	}	if (debug) printk("i is %d\n", d->i);	switch (d->state) {loop_start:		case STATE_FOR_LOOP_1_OUT:			if (debug) printk("data12 is %x\n", d->data12);			if(d->i < sizeof(aux_pattern) / sizeof(char)) {				d->tmp = aux_pattern[d->i] | (d->data12 & 0xe0);				d->state = STATE_FOR_LOOP_2_IN;				if (debug) printk("tmp is %x\n", d->tmp);				wcusb_async_write(p, 0x12, &d->tmp, 1, 0, keypad_check_done);				return;			} else {				goto func_end;			}		case STATE_FOR_LOOP_2_IN:			d->state = STATE_FOR_LOOP_PROC_DATA;			wcusb_async_read(p, 0xc0, &d->data, 1, 0, keypad_check_done);			return;		case STATE_FOR_LOOP_PROC_DATA:			d->state = STATE_FOR_LOOP_CLEAR_DIGIT;			if(debug) printk("data is %x\n", d->data);			if ((d->data & 0x1f) != 0x1f) {				if(d->data == 0xe && aux_pattern[d->i] == 0x1e) { digit = '1';}				else if(d->data == 0xd && aux_pattern[d->i] == 0x1e) { digit = '2';}				else if(d->data == 0xb && aux_pattern[d->i] == 0x1e) { digit = '3';}				else if(d->data == 0x7 && aux_pattern[d->i] == 0x1e) {					p->hookstate = 0; /* On||Off */ 					zt_hooksig(&p->chan, ZT_RXSIG_ONHOOK);				}				else if(d->data == 0xe && aux_pattern[d->i] == 0x1d) { digit = '4';}				else if(d->data == 0xd && aux_pattern[d->i] == 0x1d) { digit = '5';}				else if(d->data == 0xb && aux_pattern[d->i] == 0x1d) { digit = '6';}				else if(d->data == 0x7 && aux_pattern[d->i] == 0x1d) {					p->hookstate = 1;/* Dial */					zt_hooksig(&p->chan, ZT_RXSIG_OFFHOOK);				}				else if(d->data == 0xe && aux_pattern[d->i] == 0x17) { digit = '7';}				else if(d->data == 0xd && aux_pattern[d->i] == 0x17) { digit = '8';}				else if(d->data == 0xb && aux_pattern[d->i] == 0x17) { digit = '9';}				else if(d->data == 0x7 && aux_pattern[d->i] == 0x17) d->scanned_event = 15; /* ReDial */					else if(d->data == 0xe && aux_pattern[d->i] == 0xf) { digit = '*';}/* '*' */				else if(d->data == 0xd && aux_pattern[d->i] == 0xf) { digit = '0';}				else if(d->data == 0xb && aux_pattern[d->i] == 0xf) { digit = '#';} /* '#' */				else if(d->data == 0x7 && aux_pattern[d->i] == 0xf) d->scanned_event = 16; /* Volume? */				else {					(d->i)++;					if (debug) printk("Scanned event %d; data = %x\n", d->scanned_event, d->data);					goto loop_start;				}			} else {				if(debug) printk("Hit new if\n");				goto func_end;			}			if (debug) printk("wcusb: got digit %d\n", d->scanned_event);			if (digit != 'z') {				d->tone = zt_dtmf_tone(digit, 0);				if (!d->tone) {					printk("wcusb: Didn't get a tone structure\n");					goto func_end;				}				zt_init_tone_state(&d->ts, d->tone);				p->sample = STREAM_DTMF;			}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -