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

📄 wcfxsusb.c

📁 This a SOFTWARE pbx DRIVER
💻 C
📖 第 1 页 / 共 3 页
字号:
			break;		case STREAM_DTMF:			for (x = 0; x < ZT_CHUNKSIZE; x++) {				p->chan.readchunk[x] = wc_dtmf(p);			}			break;	}	/* Work with Zaptel now */	/* XXX Might be able to optimize this some XXX */	zt_ec_chunk(&p->chan, p->chan.readchunk, p->chan.writechunk);	zt_receive(&p->span);	zt_transmit(&p->span);	/* Fill in transmission info  */	for (x = 0; x < ZT_CHUNKSIZE; x++) {		ochunk[x] = ZT_MULAW(cpu_to_le16(p->chan.writechunk[x]));	}	/* Transmit the pending outgoing urb */	if (usb_submit_urb(out)) {		printk("wcusb: 'write' urb failed\n");	} else {		p->urbcount++;	}	/* Readsubmit read URB */	if (usb_submit_urb(in)) {		printk("wcusb: 'read' urb failed\n");	} else		p->urbcount++;	/* Clear I/O state */	p->iostate = 0;}static void wcusb_read_complete(struct urb *q){	struct wc_usb_pvt *p = q->context;	/* Decrement number of outstanding URB's */	p->urbcount--;	if (!p->flags & FLAG_RUNNING) {		/* Stop sending URBs since we're not running anymore */		return;	}	/* Prepare for retransmission */	q->dev = p->dev;	if (p->iostate & WC_IO_READ) {		static int notify=0;		if (!notify)			printk("Already ready to read?\n");		notify++;	}	/* Note that our read is now complete */	p->iostate |= WC_IO_READ;	if (IO_READY(p->iostate)) {		/* Transmit side is complete, lets go */		wcusb_do_io(p, p->pendingurb, q);	} else {		/* Let the transmission side know we're		   ready to go again */		p->pendingurb = q;	}	if (p->timer && !--p->timer) {		if (p->devclass == WC_KEYPAD) {			if(debug) printk("Checking keypad\n");			wcusb_check_keypad(p);		} else {			wcusb_check_interrupt(p);		}	}#ifdef PROSLIC_POWERSAVE	if (p->devclass != WC_KEYPAD) {		if (p->lowpowertimer && !--p->lowpowertimer) {			/* Switch back into low power mode */			p->idletxhookstate = 1;			if (p->txhook == 2)				p->newtxhook = p->idletxhookstate;		}	}#endif		return;}static void wcusb_write_complete(struct urb *q){	struct wc_usb_pvt *p = q->context;	/* Decrement counter */	p->urbcount--;	if (!p->flags & FLAG_RUNNING) {		/* Stop sending URBs since we're not running anymore */		return;	}	if (p->iostate & WC_IO_WRITE) {		static int notify=0;		if (!notify)			printk("Already ready to write?\n");		notify++;	}	/* Prepare for retransmission */	p->iostate |= WC_IO_WRITE;	q->dev = p->dev;		if (IO_READY(p->iostate)) {		/* Receive is already done, lets go */		wcusb_do_io(p, q, p->pendingurb);	} else {		/* Let the receive side know we're		   ready to go again */		p->pendingurb = q;	}}static int StopTransmit(struct wc_usb_pvt *p){	p->flags &= ~FLAG_RUNNING;	if (p->devclass == WC_KEYPAD) {		struct wc_keypad_data *d = p->pvt_data;		d->running = 0;	}	while(p->urbcount) {		schedule_timeout(1);	}	printk("ending transmit\n");	return 0;}static int flip_relays(struct wc_usb_pvt *p, int onoff){    unsigned char ctl;    unsigned char data;    /* Read data */    if (wcinp(p->dev, 0x12, &data))	return -1;    /* Read control */    if (wcinp(p->dev, 0x13, &ctl))	return -1;    /* Setup values properly -- Pins AUX3 & AUX4 control the relays */    ctl |= 0x18;    if (onoff) {	data |= 0x18;    } else {	data &= 0xe7;    }    if (wcoutp(p->dev, 0x12, data))	return -1;    if (wcoutp(p->dev, 0x13, ctl))	return -1;    return 0;}static int InitPrivate(struct wc_usb_pvt *p){	int x;	unsigned int readpipe;	unsigned int writepipe;	/* Endpoint 6 is the wave-in device */	readpipe = usb_rcvisocpipe(p->dev, 0x06);	/* Endpoint 7 is the wave-out device */	writepipe = usb_sndisocpipe(p->dev, 0x07);	for (x=0;x<2;x++) {		p->dataread[x].urb.dev = p->dev;		p->dataread[x].urb.pipe = readpipe;		p->dataread[x].urb.transfer_flags = USB_ISO_ASAP;		p->dataread[x].urb.number_of_packets = 1;		p->dataread[x].urb.context = p;		p->dataread[x].urb.complete = wcusb_read_complete;		p->dataread[x].urb.iso_frame_desc[0].length = ZT_CHUNKSIZE * 2;		p->dataread[x].urb.iso_frame_desc[0].offset = 0;		p->dataread[x].urb.transfer_buffer = p->readchunk + ZT_CHUNKSIZE * x;		p->dataread[x].urb.transfer_buffer_length = ZT_CHUNKSIZE * 2;		p->datawrite[x].urb.dev = p->dev;		p->datawrite[x].urb.pipe = writepipe;		p->datawrite[x].urb.transfer_flags = USB_ISO_ASAP;		p->datawrite[x].urb.number_of_packets = 1;		p->datawrite[x].urb.context = p;		p->datawrite[x].urb.complete = wcusb_write_complete;		p->datawrite[x].urb.iso_frame_desc[0].length = ZT_CHUNKSIZE * 2;		p->datawrite[x].urb.iso_frame_desc[0].offset = 0;		p->datawrite[x].urb.transfer_buffer = p->writechunk + ZT_CHUNKSIZE * x;		p->datawrite[x].urb.transfer_buffer_length = ZT_CHUNKSIZE * 2;	}	return 0;}static int InitTransfer(struct wc_usb_pvt *p){	int x;	p->urbcount = 4;	p->flags |= FLAG_RUNNING;	for (x=0;x<2;x++) {		if (usb_submit_urb(&p->dataread[x].urb)) {			printk(KERN_ERR "wcusb: Read submit failed\n");			return -1;		}		if (usb_submit_urb(&p->datawrite[x].urb)) {			printk(KERN_ERR "wcusb: Write submit failed\n");			return -1;		}	}	/* Start checking for interrupts */	wcusb_check_interrupt(p);	return 0;}static int wc_usb_hooksig(struct zt_chan *chan, zt_txsig_t txsig){	struct wc_usb_pvt *p = chan->pvt;	switch (p->devclass) {		case WC_PROSLIC:#ifdef PROSLIC_POWERSAVE			if (p->txhook == 4) {				/* Switching out of ring...  Be sure we idle at 2, not 1 at least				    for a bit so we can transmit caller*ID */				p->idletxhookstate = 2;				p->lowpowertimer = POWERSAVE_TIME;			}#endif					p->txhook = -1;			switch(txsig) {				case ZT_TXSIG_ONHOOK:					switch(chan->sig) {						case ZT_SIG_FXOKS:						case ZT_SIG_FXOLS:							p->newtxhook = p->idletxhookstate;							break;						case ZT_SIG_FXOGS:							p->newtxhook = 3;							break;					}				break;				case ZT_TXSIG_OFFHOOK:					p->newtxhook = p->idletxhookstate;					break;				case ZT_TXSIG_START:					p->newtxhook = 4;					break;				case ZT_TXSIG_KEWL:					p->newtxhook = 0;					break;			}		case WC_KEYPAD:			switch (txsig) {				case ZT_TXSIG_ONHOOK:					break;				case ZT_TXSIG_OFFHOOK:					break;				case ZT_TXSIG_START:					break;				case ZT_TXSIG_KEWL:					break;			}			break;	}	return 0;}static int wc_usb_open(struct zt_chan *chan){	struct wc_usb_pvt *p = chan->pvt;	if (p->dead)		return -1;	switch (p->devclass) {		case WC_KEYPAD:			p->hookstate = 0;			zt_hooksig(&p->chan, ZT_RXSIG_ONHOOK);			break;		default:			break;	}#ifndef LINUX26	MOD_INC_USE_COUNT;#endif	p->usecount++;	return 0;}static int wc_usb_close(struct zt_chan *chan){	struct wc_usb_pvt *p = chan->pvt;	p->usecount--;	if (!p->usecount && p->dead) {		/* Someone unplugged us while we were running, so now		   that the program exited, we can release our resources */		zt_unregister(&p->span);		ifaces[p->pos] = NULL;		if (p->pvt_data)			kfree(p->pvt_data);		kfree(p);	}#ifndef LINUX26	MOD_DEC_USE_COUNT;#endif	return 0;}static int init_device_pvt(struct wc_usb_pvt *p){	struct usb_device *dev = p->dev;	if (dev->descriptor.idProduct == 0xb210) {		struct wc_keypad_data *d = kmalloc(sizeof(struct wc_keypad_data), GFP_KERNEL);		printk("wcusb: Found a WC Keyed Phone\n");		p->devclass = WC_KEYPAD;		if (!d) {			printk("wcusb: kmalloc failed in init_device_pvt\n");			return -1;		}		memset(d, 0, sizeof(struct wc_keypad_data));		p->pvt_data = d;		d->count = 0;		d->running = 1;		d->tone = NULL;		return 0;	} else {		p->pvt_data = NULL;		p->devclass = WC_PROSLIC;	}	return 0;}	static void *wc_usb_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id){	struct usb_config_descriptor *config = dev->actconfig;	struct wc_usb_pvt *p=NULL;	struct wc_usb_desc *d = (struct wc_usb_desc *)id->driver_info;#if 0	char auxcon = 0;#endif	int x;	for (x=0;x<WC_MAX_IFACES;x++)		if (!ifaces[x]) break;	if (x >= WC_MAX_IFACES) {		printk("Too many interfaces\n");		goto fail;	}	p = kmalloc(sizeof(struct wc_usb_pvt), GFP_KERNEL);	if (!p)		goto fail;	memset(p, 0, sizeof(struct wc_usb_pvt));	p->hardwareflags = d->flags;	sprintf(p->span.name, "WCUSB/%d", x);	sprintf(p->span.desc,"%s %d", d->name, x);	sprintf(p->chan.name, "WCUSB/%d/%d", x, 0);#if 0	/* Make them choose with zaptel.conf */	p->chan.sig = ZT_SIG_FXOKS;					/* Assume FXOKS signalling for starters */#endif	p->chan.sigcap = ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS;	/* We're capabable of both FXOKS and FXOLS */	p->chan.chanpos = 1;	p->span.deflaw = ZT_LAW_MULAW;	p->span.chans = &p->chan;	p->span.channels = 1;	p->span.hooksig = wc_usb_hooksig;	p->span.open = wc_usb_open;	p->span.close = wc_usb_close;	p->dev = dev;	p->pos = x;	p->span.flags = ZT_FLAG_RBS;	init_waitqueue_head(&p->span.maintq);	p->span.pvt = p;	p->chan.pvt = p;#ifdef PROSLIC_POWERSAVE	/* By default we can't send on hook */	p->idletxhookstate = 1;#else	/* By default we can always send on hook */	p->idletxhookstate = 2;	#endif		ifaces[x] = p;	p->sample = STREAM_NORMAL;	if (init_device_pvt(p)) {		printk(KERN_ERR "wcusb: init_device_pvt failed\n");		goto fail;	}		if (usb_set_configuration(dev, dev->config[0].bConfigurationValue) < 0) {		printk(KERN_ERR "wcusb: set_configuration failed (ConfigValue 0x%x)\n", config->bConfigurationValue);		goto fail;	}	if (InitHardware(p)) {		printk(KERN_ERR "wcusb: Hardware initialization failed\n");		goto fail;	}	if (InitPrivate(p)) {		printk(KERN_ERR "wcusb: Unable to initialize private data structure\n");		goto fail;	}	if (p->hardwareflags & FLAG_FLIP_RELAYS) {		flip_relays(p, 1);	}	if (zt_register(&p->span, 0)) {		printk("Unable to register span %s\n", p->span.name);		goto fail;	}	if (InitTransfer(p)) {		printk(KERN_ERR "wcusb: Unable to begin data flow\n");		goto fail;	}	printk("wcusb: Found a %s\n", d->name);#if 0	wcinp(p->dev, 0x13, &auxcon);	printk("Register 0x13 is set to %x\n",auxcon);#endif		return p;fail:	if (x < WC_MAX_IFACES)		ifaces[x] = NULL;	if (p) {		if (p->pvt_data) {			kfree(p->pvt_data);		}		kfree(p);	}	return NULL;}static void wc_usb_disconnect(struct usb_device *dev, void *ptr){	/* Doesn't handle removal if we're in use right */	struct wc_usb_pvt *p = ptr;	if (ptr) {		StopTransmit(p);		if (!p->usecount) {			zt_unregister(&p->span);			ifaces[p->pos] = NULL;			if (p->pvt_data)				kfree(p->pvt_data);			kfree(ptr);		} else {			/* Generate alarm and note that we're dead */			p->span.alarms = ZT_ALARM_RED;			zt_alarm_notify(&p->span);			p->dead = 1;		}	}	printk("wcusb: Removed a Wildcard device\n");	return;}static struct usb_driver wc_usb_driver ={	name: "wcusb",	probe: wc_usb_probe,	disconnect: wc_usb_disconnect,	fops: NULL,	minor: 0,	id_table: wc_dev_ids,};static int __init wc_init (void) {	int res;	res = usb_register(&wc_usb_driver);	if (res)		return res;	printk("Wildcard USB FXS Interface driver registered\n");	return 0;}	  static void __exit wc_cleanup(void){	usb_deregister(&wc_usb_driver);}MODULE_AUTHOR("Mark Spencer <markster@linux-support.net>");MODULE_DESCRIPTION("Wildcard USB FXS Interface driver");#ifdef MODULE_LICENSEMODULE_LICENSE("GPL");#endifMODULE_PARM(debug, "i");MODULE_DEVICE_TABLE(usb, wc_dev_ids);module_init(wc_init);module_exit(wc_cleanup);

⌨️ 快捷键说明

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