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

📄 hfc_usb.c

📁 h内核
💻 C
📖 第 1 页 / 共 4 页
字号:
		case LED_S0_OFF:				   led_state&=~vdata[hfc->vend_idx].led_bits[1];				break;		case LED_B1_ON:					hfc->led_b_active|=1;				break;		case LED_B1_OFF:					hfc->led_b_active&=~1;				break;		case LED_B1_DATA:				   hfc->led_new_data|=1;				break;		case LED_B2_ON:				   hfc->led_b_active|=2;				break;		case LED_B2_OFF:					hfc->led_b_active&=~2;				break;		case LED_B2_DATA:				   hfc->led_new_data|=2;				break;	}		write_led(hfc,led_state);}/********************************//* called when timer t3 expires *//********************************/static void l1_timer_expire_t3(hfcusb_data * hfc){    //printk (KERN_INFO "HFC-USB: l1_timer_expire_t3\n");	hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_DEACTIVATE | INDICATION,NULL);#ifdef VERBOSE_USB_DEBUG	printk(KERN_INFO "PH_DEACTIVATE | INDICATION sent\n");#endif	hfc->l1_activated=FALSE;	handle_led(hfc,LED_S0_OFF);}/********************************//* called when timer t4 expires *//********************************/static void l1_timer_expire_t4(hfcusb_data * hfc){    //printk (KERN_INFO "HFC-USB: l1_timer_expire_t4\n");	hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_DEACTIVATE | INDICATION,NULL);#ifdef VERBOSE_USB_DEBUG	printk(KERN_INFO "PH_DEACTIVATE | INDICATION sent\n");#endif	hfc->l1_activated=FALSE;	handle_led(hfc,LED_S0_OFF);}/*****************************//* handle S0 state changes   *//*****************************/static void state_handler(hfcusb_data * hfc,__u8 state){	__u8 old_state;	old_state=hfc->l1_state;	// range check	if(state==old_state || state<1 || state>8) return;#ifdef VERBOSE_ISDN_DEBUG	printk(KERN_INFO "HFC-USB: new S0 state:%d old_state:%d\n",state,old_state);#endif	if(state<4 || state==7 || state==8)	{        if(timer_pending(&hfc->t3_timer)) del_timer(&hfc->t3_timer);		//printk(KERN_INFO "HFC-USB: T3 deactivated\n");	}	if(state>=7)	{        if(timer_pending(&hfc->t4_timer)) del_timer(&hfc->t4_timer);		//printk(KERN_INFO "HFC-USB: T4 deactivated\n");	}	if(state==7 && !hfc->l1_activated)	{		hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_ACTIVATE | INDICATION,NULL);		//printk(KERN_INFO "HFC-USB: PH_ACTIVATE | INDICATION sent\n");		hfc->l1_activated=TRUE;		handle_led(hfc,LED_S0_ON);	}	else	if(state<=3 /* && activated*/)	{		if(old_state==7 || old_state==8)		{			//printk(KERN_INFO "HFC-USB: T4 activated\n");			hfc->t4_timer.expires = jiffies + (HFC_TIMER_T4 * HZ) / 1000;			if(!timer_pending(&hfc->t4_timer)) add_timer(&hfc->t4_timer);		}		else		{			hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_DEACTIVATE | INDICATION,NULL);			//printk(KERN_INFO "HFC-USB: PH_DEACTIVATE | INDICATION sent\n");			hfc->l1_activated=FALSE;			handle_led(hfc,LED_S0_OFF);		}	}	hfc->l1_state=state;}/* prepare iso urb */static void fill_isoc_urb(struct urb *urb, struct usb_device *dev, unsigned int pipe, void *buf,	int num_packets, int packet_size, int interval, usb_complete_t complete, void *context){	int k;	spin_lock_init(&urb->lock);	// do we really need spin_lock_init ?	urb->dev = dev;	urb->pipe = pipe;	urb->complete = complete;	urb->number_of_packets = num_packets;	urb->transfer_buffer_length = packet_size * num_packets;	urb->context = context;	urb->transfer_buffer = buf;	urb->transfer_flags = 0;	urb->transfer_flags = URB_ISO_ASAP;	urb->actual_length = 0;	urb->interval = interval;	for (k = 0; k < num_packets; k++) {		urb->iso_frame_desc[k].offset = packet_size * k;		urb->iso_frame_desc[k].length = packet_size;		urb->iso_frame_desc[k].actual_length = 0;	}}/* allocs urbs and start isoc transfer with two pending urbs to avoid gaps in the transfer chain */static int start_isoc_chain(usb_fifo * fifo, int num_packets_per_urb,usb_complete_t complete,int packet_size){	int i, k, errcode;#ifdef VERBOSE_USB_DEBUG	printk(KERN_INFO "HFC-USB: starting ISO-chain for Fifo %i\n",  fifo->fifonum);#endif	// allocate Memory for Iso out Urbs	for (i = 0; i < 2; i++) {		if (!(fifo->iso[i].purb)) {			fifo->iso[i].purb = usb_alloc_urb(num_packets_per_urb, GFP_KERNEL);			fifo->iso[i].owner_fifo = (struct usb_fifo *) fifo;			// Init the first iso			if (ISO_BUFFER_SIZE >= (fifo->usb_packet_maxlen * num_packets_per_urb))			{				fill_isoc_urb(fifo->iso[i].purb, fifo->hfc->dev, fifo->pipe, fifo->iso[i].buffer,					num_packets_per_urb, fifo->usb_packet_maxlen, fifo->intervall,					complete, &fifo->iso[i]);				memset(fifo->iso[i].buffer, 0, sizeof(fifo->iso[i].buffer));				// defining packet delimeters in fifo->buffer				for(k = 0; k < num_packets_per_urb; k++)				{					fifo->iso[i].purb->iso_frame_desc[k].offset = k*packet_size;					fifo->iso[i].purb->iso_frame_desc[k].length = packet_size;				}			}		}		fifo->bit_line = BITLINE_INF;		errcode = usb_submit_urb(fifo->iso[i].purb, GFP_KERNEL);		fifo->active = (errcode >= 0) ? 1 : 0;		if(errcode < 0)		{			printk(KERN_INFO "HFC-USB: error submitting ISO URB: %i.%i \n",  errcode, i);		};	}	// errcode = (usb_submit_urb(fifo->iso[0].purb, GFP_KERNEL));	return(fifo->active);}/* stops running iso chain and frees their pending urbs */static void stop_isoc_chain(usb_fifo * fifo){	int i;	for(i = 0; i < 2; i++)	{		if(fifo->iso[i].purb)		{#ifdef VERBOSE_USB_DEBUG			printk(KERN_INFO "HFC-USB: Stopping iso chain for fifo %i.%i\n", fifo->fifonum, i);#endif			usb_unlink_urb(fifo->iso[i].purb);			usb_free_urb(fifo->iso[i].purb);			fifo->iso[i].purb = NULL;		}	}	if (fifo->urb) {		usb_unlink_urb(fifo->urb);		usb_free_urb(fifo->urb);		fifo->urb = NULL;	}	fifo->active = 0;}// defines how much ISO packets are handled in one URBstatic int iso_packets[8]={ISOC_PACKETS_B,ISOC_PACKETS_B,ISOC_PACKETS_B,ISOC_PACKETS_B,	                       ISOC_PACKETS_D,ISOC_PACKETS_D,ISOC_PACKETS_D,ISOC_PACKETS_D};/*****************************************************//* transmit completion routine for all ISO tx fifos *//*****************************************************/static void tx_iso_complete(struct urb *urb, struct pt_regs *regs){	iso_urb_struct *context_iso_urb = (iso_urb_struct *) urb->context;	usb_fifo *fifo = context_iso_urb->owner_fifo;	hfcusb_data *hfc = fifo->hfc;	int k, tx_offset, num_isoc_packets, sink, len, current_len,errcode,frame_complete,transp_mode,fifon;	__u8 threshbit;	__u8 threshtable[8] = { 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};	fifon=fifo->fifonum;	tx_offset=0;	// very weird error code when using ohci drivers, for now : ignore this error ...  (MB)	if(urb->status == -EOVERFLOW)	{		urb->status = 0;#ifdef VERBOSE_USB_DEBUG		printk(KERN_INFO "HFC-USB: ignoring USB DATAOVERRUN  for fifo  %i \n",fifon);#endif	}	if(fifo->active && !urb->status)	{		transp_mode=0;		if(fifon<4 && hfc->b_mode[fifon/2]==L1_MODE_TRANS) transp_mode=TRUE;		threshbit = threshtable[fifon] & hfc->threshold_mask;	// is threshold set for our channel?		num_isoc_packets=iso_packets[fifon];		if(fifon >= HFCUSB_D_TX)		{			sink = (threshbit) ? SINK_DMIN : SINK_DMAX;	// how much bit go to the sink for D-channel?		}		else		{			sink = (threshbit) ? SINK_MIN : SINK_MAX;	// how much bit go to the sink for B-channel?		}		// prepare ISO Urb		fill_isoc_urb(urb, fifo->hfc->dev, fifo->pipe,context_iso_urb->buffer, num_isoc_packets,			fifo->usb_packet_maxlen, fifo->intervall, tx_iso_complete, urb->context);		memset(context_iso_urb->buffer, 0, sizeof(context_iso_urb->buffer));		frame_complete=FALSE;		// Generate Iso Packets		for(k = 0; k < num_isoc_packets; ++k)		{			if(fifo->skbuff)			{				len = fifo->skbuff->len;	// remaining length				fifo->bit_line -= sink;	// we lower data margin every msec				current_len = (0 - fifo->bit_line) / 8;				if(current_len > 14) current_len = 14;	// maximum 15 byte for every ISO packet makes our life easier				current_len = (len <= current_len) ? len : current_len;				fifo->bit_line += current_len * 8;	// how much bit do we put on the line?				context_iso_urb->buffer[tx_offset] = 0;				if(current_len == len)				{					if(!transp_mode)					{						context_iso_urb->buffer[tx_offset] = 1;	// here frame completion						fifo->bit_line += 32;	// add 2 byte flags and 16bit CRC at end of ISDN frame					}					frame_complete = TRUE;				}				// copy bytes from buffer into ISO_URB				memcpy(context_iso_urb->buffer+tx_offset+1,fifo->skbuff->data,current_len);				skb_pull(fifo->skbuff,current_len);				// define packet delimeters within the URB buffer				urb->iso_frame_desc[k].offset = tx_offset;				urb->iso_frame_desc[k].length = current_len + 1;				tx_offset += (current_len + 1);				// printk(KERN_INFO "HFC-USB: fifonum:%d,%d bytes to send, %d bytes ISO packet,bitline:%d,sink:%d,threshbit:%d,threshmask:%x\n",fifon,len,current_len,fifo->bit_line,sink,threshbit,hfc->threshold_mask);				if(!transp_mode)				{					if(fifon==HFCUSB_B1_TX) handle_led(hfc,LED_B1_DATA);					if(fifon==HFCUSB_B2_TX) handle_led(hfc,LED_B2_DATA);				}			}			else			{				// we have no more data - generate 1 byte ISO packets				urb->iso_frame_desc[k].offset = tx_offset++;				urb->iso_frame_desc[k].length = 1;				fifo->bit_line -= sink;	// we lower data margin every msec				if(fifo->bit_line < BITLINE_INF)				{					fifo->bit_line = BITLINE_INF;					//printk (KERN_INFO "HFC-USB: BITLINE_INF underrun\n");				}			}			if(frame_complete)			{				// delete the buffer only once, here or in hfc_usb_l2l1() in a PH_DATA|REQUEST				fifo->delete_flg=TRUE;				fifo->hif->l1l2(fifo->hif,PH_DATA|CONFIRM,(void*)fifo->skbuff->truesize);				if(fifo->skbuff && fifo->delete_flg)				{					dev_kfree_skb_any(fifo->skbuff);					//printk(KERN_INFO "HFC-USB: skbuff=NULL on fifo:%d\n",fifo->fifonum);					fifo->skbuff = NULL;					fifo->delete_flg=FALSE;				}				frame_complete=FALSE;			}        }		errcode = usb_submit_urb(urb, GFP_ATOMIC);		if(errcode < 0)		{			printk(KERN_INFO "HFC-USB: error submitting ISO URB: %i \n",  errcode);		}	}	else	{		if(urb->status)		{			printk(KERN_INFO "HFC-USB: tx_iso_complete : urb->status %i, fifonum %i\n",  urb->status,fifon);		}	}}				/* tx_iso_complete *//*****************************************************//* receive completion routine for all ISO tx fifos   *//*****************************************************/static void rx_iso_complete(struct urb *urb, struct pt_regs *regs){	iso_urb_struct *context_iso_urb = (iso_urb_struct *) urb->context;	usb_fifo *fifo = context_iso_urb->owner_fifo;	hfcusb_data *hfc = fifo->hfc;	int k, len, errcode, offset, num_isoc_packets,fifon;	__u8 *buf;	fifon=fifo->fifonum;	// very weird error code when using ohci drivers, for now : ignore this error ...  (MB)	if(urb->status == -EOVERFLOW)	{		urb->status = 0;#ifdef VERBOSE_USB_DEBUG		printk(KERN_INFO "HFC-USB: ignoring USB DATAOVERRUN  for fifo  %i \n",fifon);#endif	}	if(fifo->active && !urb->status)	{		num_isoc_packets=iso_packets[fifon];		// Generate D-Channel Iso Packets		for(k = 0; k < num_isoc_packets; ++k)		{			len=urb->iso_frame_desc[k].actual_length;			offset=urb->iso_frame_desc[k].offset;			buf=context_iso_urb->buffer+offset;			if(fifo->last_urblen!=fifo->usb_packet_maxlen)			{				// the threshold mask is in the 2nd status byte				hfc->threshold_mask=buf[1];				// the S0 state is in the upper half of the 1st status byte				state_handler(hfc,buf[0] >> 4);				// if we have more than the 2 status bytes -> collect data				if(len>2) collect_rx_frame(fifo,buf+2,len-2,buf[0]&1);			}			else collect_rx_frame(fifo,buf,len,0);			fifo->last_urblen=len;        }		// prepare ISO Urb		fill_isoc_urb(urb, fifo->hfc->dev, fifo->pipe,context_iso_urb->buffer, num_isoc_packets,			fifo->usb_packet_maxlen, fifo->intervall, rx_iso_complete, urb->context);		errcode = usb_submit_urb(urb, GFP_ATOMIC);		if(errcode < 0)		{			printk(KERN_INFO "HFC-USB: error submitting ISO URB: %i \n",  errcode);		}	}	else	{		if(urb->status)		{			printk(KERN_INFO "HFC-USB: rx_iso_complete : urb->status %i, fifonum %i\n",  urb->status,fifon);		}	}

⌨️ 快捷键说明

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