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

📄 hfc_usb.c

📁 h内核
💻 C
📖 第 1 页 / 共 4 页
字号:
	{		hfc->b_if[i].ifc.priv = &hfc->fifos[HFCUSB_B1_TX+i*2];		hfc->b_if[i].ifc.l2l1 = hfc_usb_l2l1;		p_b_if[i] = &hfc->b_if[i];	}		hfc->protocol = 2;  /* default EURO ISDN, should be a module_param */	hisax_register(&hfc->d_if, p_b_if, "hfc_usb", hfc->protocol);		for (i=0; i<4; i++)		hfc->fifos[i].hif=&p_b_if[i/2]->ifc;	for (i=4; i<8; i++)		hfc->fifos[i].hif=&hfc->d_if.ifc;	// 3 (+1) INT IN + 3 ISO OUT	if(hfc->cfg_used == CNF_3INT3ISO || hfc->cfg_used == CNF_4INT3ISO)	{		start_int_fifo(hfc->fifos + HFCUSB_D_RX);	// Int IN D-fifo		if(hfc->fifos[HFCUSB_PCM_RX].pipe) start_int_fifo(hfc->fifos + HFCUSB_PCM_RX);	// E-fifo		start_int_fifo(hfc->fifos + HFCUSB_B1_RX);	// Int IN B1-fifo		start_int_fifo(hfc->fifos + HFCUSB_B2_RX);	// Int IN B2-fifo	}	// 3 (+1) ISO IN + 3 ISO OUT	if(hfc->cfg_used==CNF_3ISO3ISO || hfc->cfg_used==CNF_4ISO3ISO)	{		start_isoc_chain(hfc->fifos + HFCUSB_D_RX, ISOC_PACKETS_D, rx_iso_complete,16);		if(hfc->fifos[HFCUSB_PCM_RX].pipe) start_isoc_chain(hfc->fifos + HFCUSB_PCM_RX, ISOC_PACKETS_D, rx_iso_complete,16);		start_isoc_chain(hfc->fifos + HFCUSB_B1_RX, ISOC_PACKETS_B, rx_iso_complete,16);		start_isoc_chain(hfc->fifos + HFCUSB_B2_RX, ISOC_PACKETS_B, rx_iso_complete,16);	}	start_isoc_chain(hfc->fifos + HFCUSB_D_TX, ISOC_PACKETS_D, tx_iso_complete,1);	start_isoc_chain(hfc->fifos + HFCUSB_B1_TX, ISOC_PACKETS_B, tx_iso_complete,1);	start_isoc_chain(hfc->fifos + HFCUSB_B2_TX, ISOC_PACKETS_B, tx_iso_complete,1);	handle_led(hfc,LED_POWER_ON);	return(0);}	/* usb_init *//****************************************//* data defining the devices to be used *//****************************************/// static __devinitdata const struct usb_device_id hfc_usb_idtab[3] = {static struct usb_device_id hfc_usb_idtab[] = {	{USB_DEVICE(0x7b0, 0x0007)},	/* Billion USB TA 2 */	{USB_DEVICE(0x742, 0x2008)},	/* Stollmann USB TA */	{USB_DEVICE(0x959, 0x2bd0)},	/* Colognechip USB eval TA */	{USB_DEVICE(0x8e3, 0x0301)},	/* OliTec ISDN USB */	{USB_DEVICE(0x675, 0x1688)},	/* DrayTec ISDN USB */	{USB_DEVICE(0x7fa, 0x0846)},    /* Bewan ISDN USB TA */	{}				/* end with an all-zeroes entry */};MODULE_AUTHOR("Peter Sprenger (sprenger@moving-byters.de)/Martin Bachem (info@colognechip.com)");MODULE_DESCRIPTION("HFC I4L USB driver");MODULE_DEVICE_TABLE(usb, hfc_usb_idtab);MODULE_LICENSE("GPL");#define EP_NUL 1    // Endpoint at this position not allowed#define EP_NOP 2	// all type of endpoints allowed at this position#define EP_ISO 3	// Isochron endpoint mandatory at this position#define EP_BLK 4	// Bulk endpoint mandatory at this position#define EP_INT 5	// Interrupt endpoint mandatory at this position// this array represents all endpoints possible in the HCF-USB// the last 2 entries are the configuration number and the minimum interval for Interrupt endpointsint validconf[][18]={	// INT in, ISO out config	{EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NOP,EP_INT,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_NUL,EP_NUL,CNF_4INT3ISO,2},	{EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NUL,EP_NUL,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_NUL,EP_NUL,CNF_3INT3ISO,2},	// ISO in, ISO out config	{EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_NOP,EP_ISO,CNF_4ISO3ISO,2},	{EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_NUL,EP_NUL,CNF_3ISO3ISO,2},	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}       // EOL element};// string description of chosen configchar *conf_str[]={	"4 Interrupt IN + 3 Isochron OUT",	"3 Interrupt IN + 3 Isochron OUT",	"4 Isochron IN + 3 Isochron OUT",	"3 Isochron IN + 3 Isochron OUT"};/*************************************************//* function called to probe a new plugged device *//*************************************************/static int hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id){	struct usb_device *dev= interface_to_usbdev(intf);	hfcusb_data *context;	struct usb_host_interface *iface = intf->cur_altsetting;	struct usb_host_interface *iface_used = NULL;	struct usb_host_endpoint *ep;	int ifnum = iface->desc.bInterfaceNumber;	int i, idx, alt_idx, probe_alt_setting, vend_idx, cfg_used, *vcf, attr, cfg_found, cidx, ep_addr;	int cmptbl[16],small_match,iso_packet_size,packet_size,alt_used=0;//        usb_show_device(dev);//	usb_show_device_descriptor(&dev->descriptor);//	usb_show_interface_descriptor(&iface->desc);	vend_idx=0xffff;	for(i=0;vdata[i].vendor;i++) {		if (le16_to_cpu(dev->descriptor.idVendor) == vdata[i].vendor && 		    le16_to_cpu(dev->descriptor.idProduct) == vdata[i].prod_id)			vend_idx = i;	}	#ifdef VERBOSE_USB_DEBUG		printk(KERN_INFO "HFC-USB: probing interface(%d) actalt(%d) minor(%d)\n",		ifnum, iface->desc.bAlternateSetting, intf->minor);#endif	if (vend_idx != 0xffff) {#ifdef VERBOSE_USB_DEBUG		printk(KERN_INFO "HFC-USB: found vendor idx:%d  name:%s\n",vend_idx,vdata[vend_idx].vend_name);#endif		/* if vendor and product ID is OK, start probing a matching alternate setting ... */		alt_idx = 0;		small_match=0xffff;		// default settings		iso_packet_size=16;		packet_size=64;		while (alt_idx < intf->num_altsetting) {			iface = intf->altsetting + alt_idx;			probe_alt_setting = iface->desc.bAlternateSetting;			cfg_used=0;#ifdef VERBOSE_USB_DEBUG			printk(KERN_INFO "HFC-USB: test alt_setting %d\n", probe_alt_setting);#endif			// check for config EOL element			while (validconf[cfg_used][0]) {				cfg_found=TRUE;				vcf=validconf[cfg_used];				ep = iface->endpoint;	/* first endpoint descriptor */#ifdef VERBOSE_USB_DEBUG				printk(KERN_INFO "HFC-USB: (if=%d alt=%d cfg_used=%d)\n",					ifnum, probe_alt_setting, cfg_used);#endif				// copy table				memcpy(cmptbl,vcf,16*sizeof(int));				// check for all endpoints in this alternate setting				for (i=0; i < iface->desc.bNumEndpoints; i++) {					ep_addr = ep->desc.bEndpointAddress;					idx = ((ep_addr & 0x7f)-1)*2;	/* get endpoint base */					if (ep_addr & 0x80)						idx++;					attr = ep->desc.bmAttributes;					if (cmptbl[idx] == EP_NUL) {						printk(KERN_INFO "HFC-USB: cfg_found=FALSE in idx:%d  attr:%d  cmptbl[%d]:%d\n",							idx, attr, idx, cmptbl[idx]);						cfg_found = FALSE;					}					if (attr == USB_ENDPOINT_XFER_INT && cmptbl[idx] == EP_INT)						cmptbl[idx] = EP_NUL;					if (attr == USB_ENDPOINT_XFER_BULK && cmptbl[idx] == EP_BLK)						cmptbl[idx] = EP_NUL;					if (attr == USB_ENDPOINT_XFER_ISOC && cmptbl[idx] == EP_ISO)						cmptbl[idx] = EP_NUL;					// check if all INT endpoints match minimum interval					if (attr == USB_ENDPOINT_XFER_INT && ep->desc.bInterval < vcf[17]) {#ifdef VERBOSE_USB_DEBUG						if (cfg_found)							printk(KERN_INFO "HFC-USB: Interrupt Endpoint interval < %d found - skipping config\n",								vcf[17]);#endif						cfg_found = FALSE;					}					ep++;				}				for (i = 0; i < 16; i++) {					// printk(KERN_INFO "HFC-USB: cmptbl[%d]:%d\n", i, cmptbl[i]);					// all entries must be EP_NOP or EP_NUL for a valid config					if (cmptbl[i] != EP_NOP && cmptbl[i] != EP_NUL)						cfg_found = FALSE;				}				// we check for smallest match, to provide configuration priority				// configurations with smaller index have higher priority				if (cfg_found) {					if (cfg_used < small_match) {						small_match = cfg_used;						alt_used = probe_alt_setting;						iface_used = iface;					}#ifdef VERBOSE_USB_DEBUG					printk(KERN_INFO "HFC-USB: small_match=%x %x\n", small_match, alt_used);#endif				}				cfg_used++;			}			alt_idx++;		}		/* (alt_idx < intf->num_altsetting) */#ifdef VERBOSE_USB_DEBUG		printk(KERN_INFO "HFC-USB: final small_match=%x alt_used=%x\n",small_match, alt_used);#endif		// yiipiee, we found a valid config		if (small_match != 0xffff) {			iface = iface_used;			if (!(context = kmalloc(sizeof(hfcusb_data), GFP_KERNEL)))				return(-ENOMEM);  /* got no mem */			memset(context, 0, sizeof(hfcusb_data));	/* clear the structure */			ep = iface->endpoint;	/* first endpoint descriptor */			vcf = validconf[small_match];			for (i = 0; i < iface->desc.bNumEndpoints; i++) {				ep_addr = ep->desc.bEndpointAddress;				idx = ((ep_addr & 0x7f)-1)*2;	/* get endpoint base */				if (ep_addr & 0x80)					idx++;				cidx = idx & 7;				attr = ep->desc.bmAttributes;				// only initialize used endpoints				if (vcf[idx] != EP_NOP && vcf[idx] != EP_NUL) {					switch (attr) {						case USB_ENDPOINT_XFER_INT:							context->fifos[cidx].pipe = usb_rcvintpipe(dev, ep->desc.bEndpointAddress);							context->fifos[cidx].usb_transfer_mode = USB_INT;							packet_size = le16_to_cpu(ep->desc.wMaxPacketSize); // remember max packet size#ifdef VERBOSE_USB_DEBUG							printk (KERN_INFO "HFC-USB: Interrupt-In Endpoint found %d ms(idx:%d cidx:%d)!\n",								ep->desc.bInterval, idx, cidx);#endif							break;						case USB_ENDPOINT_XFER_BULK:							if (ep_addr & 0x80)								context->fifos[cidx].pipe = usb_rcvbulkpipe(dev, ep->desc.bEndpointAddress);							else								context->fifos[cidx].pipe = usb_sndbulkpipe(dev, ep->desc.bEndpointAddress);							context->fifos[cidx].usb_transfer_mode = USB_BULK;							packet_size = le16_to_cpu(ep->desc.wMaxPacketSize); // remember max packet size#ifdef VERBOSE_USB_DEBUG							printk (KERN_INFO "HFC-USB: Bulk Endpoint found (idx:%d cidx:%d)!\n",								idx, cidx);#endif							break;						case USB_ENDPOINT_XFER_ISOC:							if (ep_addr & 0x80)								context->fifos[cidx].pipe = usb_rcvisocpipe(dev, ep->desc.bEndpointAddress);							else								context->fifos[cidx].pipe = usb_sndisocpipe(dev, ep->desc.bEndpointAddress);							context->fifos[cidx].usb_transfer_mode = USB_ISOC;							iso_packet_size = le16_to_cpu(ep->desc.wMaxPacketSize); // remember max packet size#ifdef VERBOSE_USB_DEBUG							printk (KERN_INFO "HFC-USB: ISO Endpoint found (idx:%d cidx:%d)!\n",								idx, cidx);#endif							break;						default:							context->fifos[cidx].pipe = 0;	/* reset data */					}	/* switch attribute */					if (context->fifos[cidx].pipe) {						context->fifos[cidx].fifonum = cidx;						context->fifos[cidx].hfc = context;						context->fifos[cidx].usb_packet_maxlen = le16_to_cpu(ep->desc.wMaxPacketSize);						context->fifos[cidx].intervall = ep->desc.bInterval;						context->fifos[cidx].skbuff = NULL;#ifdef VERBOSE_USB_DEBUG						printk (KERN_INFO "HFC-USB: fifo%d pktlen %d interval %d\n",							context->fifos[cidx].fifonum,							context->fifos[cidx].usb_packet_maxlen,							context->fifos[cidx].intervall);#endif					}				}				ep++;			}			// now share our luck			context->dev = dev;						/* save device */			context->if_used = ifnum;					/* save used interface */			context->alt_used = alt_used;					/* and alternate config */			context->ctrl_paksize = dev->descriptor.bMaxPacketSize0;	/* control size */			context->cfg_used=vcf[16];					// store used config			context->vend_idx=vend_idx;					// store found vendor			context->packet_size=packet_size;			context->iso_packet_size=iso_packet_size;			/* create the control pipes needed for register access */			context->ctrl_in_pipe = usb_rcvctrlpipe(context->dev, 0);			context->ctrl_out_pipe = usb_sndctrlpipe(context->dev, 0);			context->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL);			printk(KERN_INFO "HFC-USB: detected \"%s\" configuration: %s (if=%d alt=%d)\n",				vdata[vend_idx].vend_name, conf_str[small_match], context->if_used, context->alt_used);			/* init the chip and register the driver */			if (usb_init(context))			{				if (context->ctrl_urb) {					usb_unlink_urb(context->ctrl_urb);					usb_free_urb(context->ctrl_urb);					context->ctrl_urb = NULL;				}				kfree(context);				return(-EIO);			}			usb_set_intfdata(intf, context);			return(0);		} 	}	return(-EIO);}/****************************************************//* function called when an active device is removed *//****************************************************/static void hfc_usb_disconnect(struct usb_interface *intf){	hfcusb_data *context = usb_get_intfdata(intf);	int i;	printk(KERN_INFO "HFC-USB: device disconnect\n");		usb_set_intfdata(intf, NULL);	if (!context)		return;	if (timer_pending(&context->t3_timer))		del_timer(&context->t3_timer);	if (timer_pending(&context->t4_timer))		del_timer(&context->t4_timer);	if (timer_pending(&context->led_timer))		del_timer(&context->led_timer);	hisax_unregister(&context->d_if);	/* tell all fifos to terminate */	for(i = 0; i < HFCUSB_NUM_FIFOS; i++) {		if(context->fifos[i].usb_transfer_mode == USB_ISOC) {			if(context->fifos[i].active > 0) {	    			stop_isoc_chain(&context->fifos[i]);#ifdef VERBOSE_USB_DEBUG		    		printk (KERN_INFO "HFC-USB: hfc_usb_disconnect: stopping ISOC chain Fifo no %i\n", i);#endif 			}		} else {			if(context->fifos[i].active > 0) {				context->fifos[i].active = 0;#ifdef VERBOSE_USB_DEBUG				printk (KERN_INFO "HFC-USB: hfc_usb_disconnect: unlinking URB for Fifo no %i\n", i);#endif			}			if (context->fifos[i].urb) {				usb_unlink_urb(context->fifos[i].urb);				usb_free_urb(context->fifos[i].urb);				context->fifos[i].urb = NULL;			}		}		context->fifos[i].active = 0;	}	if (context->ctrl_urb) {		usb_unlink_urb(context->ctrl_urb);		usb_free_urb(context->ctrl_urb);		context->ctrl_urb = NULL;	}	kfree(context);		/* free our structure again */}				/* hfc_usb_disconnect *//************************************//* our driver information structure *//************************************/static struct usb_driver hfc_drv = {	.owner =	THIS_MODULE,	.name =		"hfc_usb",	.id_table = 	hfc_usb_idtab,	.probe =	hfc_usb_probe,	.disconnect =	hfc_usb_disconnect,};static void __exit hfc_usb_exit(void){#ifdef VERBOSE_USB_DEBUG	printk ("HFC-USB: calling \"hfc_usb_exit\" ...\n");#endif	usb_deregister(&hfc_drv);	/* release our driver */	printk(KERN_INFO "HFC-USB module removed\n");}static int __init hfc_usb_init(void){	printk ("HFC-USB: driver module revision %s loaded\n", hfcusb_revision);	if(usb_register(&hfc_drv))	{		printk(KERN_INFO "HFC-USB: Unable to register HFC-USB module at usb stack\n");		return(-1);		   /* unable to register */	}	return(0);}module_init(hfc_usb_init);module_exit(hfc_usb_exit);

⌨️ 快捷键说明

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