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

📄 wcusb.c

📁 This a SOFTWARE pbx DRIVER
💻 C
📖 第 1 页 / 共 3 页
字号:
		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 prepare_transfer_urbs(struct wc_usb_pvt *p){	int x;	/* Endpoint 6 is the wave-in device */	unsigned int readpipe = usb_rcvisocpipe(p->dev, 0x06);	/* Endpoint 7 is the wave-out device */	unsigned int 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;#ifdef LINUX26		p->dataread[x].urb.transfer_flags = URB_ISO_ASAP;#else		p->dataread[x].urb.transfer_flags = USB_ISO_ASAP;#endif				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;#ifdef LINUX26		p->datawrite[x].urb.transfer_flags = URB_ISO_ASAP;#else		p->datawrite[x].urb.transfer_flags = USB_ISO_ASAP;#endif		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 begin_transfer(struct wc_usb_pvt *p){	int x;	p->urbcount = 4;	p->flags |= FLAG_RUNNING;	for (x = 0; x < 2; x++) {#ifdef LINUX26		if (usb_submit_urb(&p->dataread[x].urb, GFP_KERNEL)) #else		if (usb_submit_urb(&p->dataread[x].urb)) #endif		{			printk(KERN_ERR "wcusb: Read submit failed\n");			return -1;		}#ifdef LINUX26		if (usb_submit_urb(&p->datawrite[x].urb, GFP_KERNEL))#else		if (usb_submit_urb(&p->datawrite[x].urb)) #endif				{			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 struct wc_usb_pvt *wc_detect_device(struct usb_device *dev, struct wc_usb_pvt *orig){	struct wc_usb_pvt *p;		p = orig;	if (!p) {		p = kmalloc(sizeof(struct wc_usb_pvt), GFP_KERNEL);		if (!p) {			printk("wcusb: kmalloc failed\n");			return NULL;		}		memset(p, 0, sizeof(struct wc_usb_pvt));	}	p->dev = dev;#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		printk("wcusb: wc_detect_device\n");	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 NULL;		}		memset(d, 0, sizeof(struct wc_keypad_data));		p->pvt_data = d;		d->count = 0;		d->running = 1;		d->tone = NULL;		return p;	} else {		p->pvt_data = NULL;		p->devclass = WC_PROSLIC;	}	printk("Second exit\n");	return p;}static int wc_set_zaptel(struct wc_usb_pvt *p){	int x;	for (x = 0; x < WC_MAX_IFACES; x++)		if (!ifaces[x]) break;	if (x >= WC_MAX_IFACES) {		printk("wcusb: Too many interfaces\n");		return -1;	}	sprintf(p->span.name, "WCUSB/%d", x);	sprintf(p->span.desc,"%s %d", p->span.name, x);        sprintf(p->chan.name, "WCUSB/%d/%d", x, 0);        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;	ifaces[x] = p;    p->pos = x;    p->span.flags = ZT_FLAG_RBS;    init_waitqueue_head(&p->span.maintq);    p->span.pvt = p;    p->chan.pvt = p;		/* Set the stream to just pass the data from the device uninhibited */	p->sample = STREAM_NORMAL;	if (zt_register(&p->span, 0)) {		printk("wcusb: Unable to register span %s\n", p->span.name);		return -1;	}	return 0;}	#ifdef LINUX26static int wc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)#elsestatic void *wc_usb_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id)#endif{	struct wc_usb_pvt *p = NULL;	struct wc_usb_desc *d = (struct wc_usb_desc *)id->driver_info;#ifdef LINUX26	struct usb_device *dev = interface_to_usbdev(intf);#endif		int x;	for (x=0;x<WC_MAX_IFACES;x++) {		/* Find first dead or empty space */		p = ifaces[x];		if (!p) {			if (debug)				printk("Device slot %d is free\n", x);			break;		}		if (p->dead) {			if (debug)				printk("Device slot %d can be revived\n", x);			break;		}		if (debug)			printk("Device slot %d is still in use\n", x);	}	if (!(p = wc_detect_device(dev, p))) {		printk("wcusb: No wcusb devices found\n");#ifdef LINUX26		return -ENODEV;#else		return NULL;#endif			}#ifndef LINUX26	if (usb_set_configuration(dev, dev->config[0].bConfigurationValue) < 0) {		printk("wcusb: set_configuration failed (ConfigValue 0x%x)\n", dev->config[0].bConfigurationValue);		return NULL;	}#endif	if (init_hardware(p)) {		printk("wcusb: Hardware intialization failed.\n");		goto cleanup;	}	if (prepare_transfer_urbs(p)) {		printk("wcusb: problem preparing the urbs for transfer\n");		goto cleanup;	}		if (d->flags & FLAG_FLIP_RELAYS) {		flip_relays(p, 1);	}	if (!p->dead && wc_set_zaptel(p)) {		printk("wcusb: Error in starting the zaptel stuff\n");		goto cleanup;	}	if (begin_transfer(p)) {		printk("wcusb: Something went wrong when starting the transfer\n");		goto cleanup;	}	if (p->dead)		printk("wcusb: Rekindling a %s (%s)\n", d->name, p->span.name);	else		printk("wcusb: Found a %s (%s)\n", d->name, p->span.name);		/* Reset deadness */	p->dead = 0;	/* Clear alarms */	p->span.alarms = 0;	zt_alarm_notify(&p->span);#ifdef LINUX26	usb_set_intfdata(intf, p);	return 0;#else	return p;#endif			cleanup:	printk("cleanup\n");	if (p) {		if (p->pvt_data) {			kfree(p->pvt_data);		}		kfree(p);	}#ifdef LINUX26	return -ENODEV;#else	return NULL;#endif	}#ifdef LINUX26static void wc_usb_disconnect(struct usb_interface *intf)#elsestatic void wc_usb_disconnect(struct usb_device *dev, void *ptr)#endif{	/* Doesn't handle removal if we're in use right */#ifdef LINUX26	struct wc_usb_pvt *p = usb_get_intfdata(intf);#else	struct wc_usb_pvt *p = ptr;#endif		if (p) {		StopTransmit(p);		p->dev = NULL;		if (!p->usecount) {			zt_unregister(&p->span);			if (p->pvt_data)				kfree(p->pvt_data);			ifaces[p->pos] = NULL;			kfree(p);		} 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");#ifdef LINUX26	usb_set_intfdata(intf, NULL);#endif			return;}static struct usb_device_id wc_dev_ids[] = {          /* This needs to be a USB audio device, and it needs to be made by us and have the right device ID */	{ 		match_flags: (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS | USB_DEVICE_ID_MATCH_DEVICE),		bInterfaceClass: USB_CLASS_AUDIO,		bInterfaceSubClass: 1,		idVendor: 0x06e6,		idProduct: 0x831c,            /* Product ID / Chip configuration (you can't change this) */		driver_info: (unsigned long)&wcusb,	},	{ 		match_flags: (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS | USB_DEVICE_ID_MATCH_DEVICE),		bInterfaceClass: USB_CLASS_AUDIO,		bInterfaceSubClass: 1,		idVendor: 0x06e6,		idProduct: 0x831e,		driver_info: (unsigned long)&wcusb2,	},	{ 		match_flags: (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS | USB_DEVICE_ID_MATCH_DEVICE),		bInterfaceClass: USB_CLASS_AUDIO,		bInterfaceSubClass: 1,		idVendor: 0x06e6,		idProduct: 0xb210,		driver_info: (unsigned long)&wc_usb_phone,	},	{ }     /* Terminating Entry */};static struct usb_driver wc_usb_driver ={#ifdef LINUX26	owner: THIS_MODULE,#else		fops: NULL,	minor: 0,#endif		name: "wcusb",	probe: wc_usb_probe,	disconnect: wc_usb_disconnect,	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("Matthew Fredrickson <creslin@linux-support.net>");MODULE_DESCRIPTION("Wildcard USB FXS Interface driver");#ifdef MODULE_LICENSEMODULE_LICENSE("GPL");#endifMODULE_DEVICE_TABLE(usb, wc_dev_ids);module_init(wc_init);module_exit(wc_cleanup);

⌨️ 快捷键说明

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