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

📄 hfc_usb.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
	if (state >= 7) {		if (timer_pending(&hfc->t4_timer))			del_timer(&hfc->t4_timer);#ifdef CONFIG_HISAX_DEBUG		DBG(ISDN_DBG, "HFC-S USB: T4 deactivated");#endif	}	if (state == 7 && !hfc->l1_activated) {		hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,				   PH_ACTIVATE | INDICATION, NULL);#ifdef CONFIG_HISAX_DEBUG		DBG(ISDN_DBG, "HFC-S USB: PH_ACTIVATE | INDICATION sent");#endif		hfc->l1_activated = TRUE;		handle_led(hfc, LED_S0_ON);	} else if (state <= 3 /* && activated */ ) {		if (old_state == 7 || old_state == 8) {#ifdef CONFIG_HISAX_DEBUG			DBG(ISDN_DBG, "HFC-S USB: T4 activated");#endif			if (!timer_pending(&hfc->t4_timer)) {				hfc->t4_timer.expires =				    jiffies + (HFC_TIMER_T4 * HZ) / 1000;				add_timer(&hfc->t4_timer);			}		} else {			hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,					   PH_DEACTIVATE | INDICATION,					   NULL);#ifdef CONFIG_HISAX_DEBUG			DBG(ISDN_DBG,			    "HFC-S USB: PH_DEACTIVATE | INDICATION sent");#endif			hfc->l1_activated = FALSE;			handle_led(hfc, LED_S0_OFF);		}	}	hfc->l1_state = state;}/* prepare iso urb */static voidfill_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);	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 = 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 intstart_isoc_chain(usb_fifo * fifo, int num_packets_per_urb,		 usb_complete_t complete, int packet_size){	int i, k, errcode;	printk(KERN_INFO "HFC-S USB: starting ISO-chain for Fifo %i\n",	       fifo->fifonum);	/* 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);			if (!(fifo->iso[i].purb)) {				printk(KERN_INFO				       "alloc urb for fifo %i failed!!!",				       fifo->fifonum);			}			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;				}			} else {				printk(KERN_INFO				       "HFC-S USB: ISO Buffer size to small!\n");			}		}		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-S USB: %s  URB nr:%d\n",			       symbolic(urb_errlist, errcode), i);		};	}	return (fifo->active);}/* stops running iso chain and frees their pending urbs */static voidstop_isoc_chain(usb_fifo * fifo){	int i;	for (i = 0; i < 2; i++) {		if (fifo->iso[i].purb) {#ifdef CONFIG_HISAX_DEBUG			DBG(USB_DBG,			    "HFC-S USB: Stopping iso chain for fifo %i.%i",			    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 URB */static 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 voidtx_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;	int frame_complete, transp_mode, fifon, status;	__u8 threshbit;	__u8 threshtable[8] = { 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80 };	fifon = fifo->fifonum;	status = urb->status;	tx_offset = 0;	if (fifo->active && !status) {		transp_mode = 0;		if (fifon < 4 && hfc->b_mode[fifon / 2] == L1_MODE_TRANS)			transp_mode = TRUE;		/* is FifoFull-threshold set for our channel? */		threshbit = threshtable[fifon] & hfc->threshold_mask;		num_isoc_packets = iso_packets[fifon];		/* predict dataflow to avoid fifo overflow */		if (fifon >= HFCUSB_D_TX) {			sink = (threshbit) ? SINK_DMIN : SINK_DMAX;		} else {			sink = (threshbit) ? SINK_MIN : SINK_MAX;		}		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 next Iso Packets */		for (k = 0; k < num_isoc_packets; ++k) {			if (fifo->skbuff) {				len = fifo->skbuff->len;				/* we lower data margin every msec */				fifo->bit_line -= sink;				current_len = (0 - fifo->bit_line) / 8;				/* maximum 15 byte for every ISO packet makes our life easier */				if (current_len > 14)					current_len = 14;				current_len =				    (len <=				     current_len) ? len : current_len;				/* how much bit do we put on the line? */				fifo->bit_line += current_len * 8;				context_iso_urb->buffer[tx_offset] = 0;				if (current_len == len) {					if (!transp_mode) {						/* here frame completion */						context_iso_urb->						    buffer[tx_offset] = 1;						/* add 2 byte flags and 16bit CRC at end of ISDN frame */						fifo->bit_line += 32;					}					frame_complete = TRUE;				}				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);			} else {				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;				}			}			if (frame_complete) {				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);					fifo->skbuff = NULL;					fifo->delete_flg = FALSE;				}				frame_complete = FALSE;			}		}		errcode = usb_submit_urb(urb, GFP_ATOMIC);		if (errcode < 0) {			printk(KERN_INFO			       "HFC-S USB: error submitting ISO URB: %d \n",			       errcode);		}	} else {		if (status && !hfc->disc_flag) {			printk(KERN_INFO			       "HFC-S USB: tx_iso_complete : urb->status %s (%i), fifonum=%d\n",			       symbolic(urb_errlist, status), status,			       fifon);		}	}}				/* tx_iso_complete *//*****************************************************//* receive completion routine for all ISO tx fifos   *//*****************************************************/static voidrx_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, maxlen,	    status;	unsigned int iso_status;	__u8 *buf;	static __u8 eof[8];#ifdef CONFIG_HISAX_DEBUG	__u8 i;#endif	fifon = fifo->fifonum;	status = urb->status;	if (urb->status == -EOVERFLOW) {#ifdef CONFIG_HISAX_DEBUG		DBG(USB_DBG,		    "HFC-USB: ignoring USB DATAOVERRUN  for fifo  %i \n",		    fifon);#endif		status = 0;	}	if (fifo->active && !status) {		num_isoc_packets = iso_packets[fifon];		maxlen = fifo->usb_packet_maxlen;		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;			iso_status = urb->iso_frame_desc[k].status;#ifdef CONFIG_HISAX_DEBUG			if (iso_status && !hfc->disc_flag)				DBG(USB_DBG,				    "HFC-S USB: ISO packet failure - status:%x",				    iso_status);			if ((fifon == 5) && (debug > 1)) {				printk(KERN_INFO				       "HFC-S USB: ISO-D-RX lst_urblen:%2d "				       "act_urblen:%2d max-urblen:%2d "				       "EOF:0x%0x DATA: ",				       fifo->last_urblen, len, maxlen,				       eof[5]);				for (i = 0; i < len; i++)					printk("%.2x ", buf[i]);				printk("\n");			}#endif			if (fifo->last_urblen != maxlen) {				/* the threshold mask is in the 2nd status byte */				hfc->threshold_mask = buf[1];				/* care for L1 state only for D-Channel				   to avoid overlapped iso completions */				if (fifon == 5) {					/* the S0 state is in the upper half					   of the 1st status byte */					state_handler(hfc, buf[0] >> 4);				}				eof[fifon] = buf[0] & 1;				if (len > 2)					collect_rx_frame(fifo, buf + 2,							 len - 2,							 (len <							  maxlen) ?							 eof[fifon] : 0);			} else {				collect_rx_frame(fifo, buf, len,						 (len <						  maxlen) ? eof[fifon] :						 0);			}			fifo->last_urblen = len;		}		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-S USB: error submitting ISO URB: %d \n",			       errcode);		}	} else {		if (status && !hfc->disc_flag) {			printk(KERN_INFO			       "HFC-S USB: rx_iso_complete : "			       "urb->status %d, fifonum %d\n",			       status, fifon);		}	}}				/* rx_iso_complete *//*****************************************************//* collect data from interrupt or isochron in        *//*****************************************************/static voidcollect_rx_frame(usb_fifo * fifo, __u8 * data, int len, int finish){	hfcusb_data *hfc = fifo->hfc;	int transp_mode, fifon;#ifdef CONFIG_HISAX_DEBUG	int i;#endif	fifon = fifo->fifonum;	transp_mode = 0;	if (fifon < 4 && hfc->b_mode[fifon / 2] == L1_MODE_TRANS)		transp_mode = TRUE;	if (!fifo->skbuff) {		fifo->skbuff = dev_alloc_skb(fifo->max_size + 3);		if (!fifo->skbuff) {			printk(KERN_INFO			       "HFC-S USB: cannot allocate buffer (dev_alloc_skb) fifo:%d\n",			       fifon);			return;		}	}	if (len) {		if (fifo->skbuff->len + len < fifo->max_size) {			memcpy(skb_put(fifo->skbuff, len), data, len);		} else {#ifdef CONFIG_HISAX_DEBUG			printk(KERN_INFO "HFC-S USB: ");			for (i = 0; i < 15; i++)				printk("%.2x ",				       fifo->skbuff->data[fifo->skbuff->							  len - 15 + i]);			printk("\n");#endif			printk(KERN_INFO			       "HCF-USB: got frame exceeded fifo->max_size:%d on fifo:%d\n",			       fifo->max_size, fifon);		}	}	if (transp_mode && fifo->skbuff->len >= 128) {		fifo->hif->l1l2(fifo->hif, PH_DATA | INDICATION,				fifo->skbuff);		fifo->skbuff = NULL;		return;	}	/* we have a complete hdlc packet */	if (finish) {		if ((!fifo->skbuff->data[fifo->skbuff->len - 1])		    && (fifo->skbuff->len > 3)) {			/* remove CRC & status */			skb_trim(fifo->skbuff, fifo->skbuff->len - 3);			if (fifon == HFCUSB_PCM_RX) {				fifo->hif->l1l2(fifo->hif,

⌨️ 快捷键说明

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