Esempio n. 1
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;

	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);
}
Esempio n. 2
0
static int
start_isoc_chain(usb_fifo * fifo, int num_packets_per_urb,
		 usb_complete_t complete, int packet_size)
{
	int i, k, errcode;

	DBG(HFCUSB_DBG_INIT, "HFC-S USB: starting ISO-URBs for fifo:%d\n",
	    fifo->fifonum);

	
	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;

			
			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));
				
				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: usb_submit_urb URB nr:%d, error(%i): '%s'\n",
			       i, errcode, symbolic(urb_errlist, errcode));
	}
	return (fifo->active);
}
Esempio n. 3
0
int
st5481_setup_isocpipes(struct urb* urb[2], struct usb_device *dev, 
			   unsigned int pipe, int num_packets,
			   int packet_size, int buf_size,
			   usb_complete_t complete, void *context)
{
	int j, retval;
	unsigned char *buf;

	for (j = 0; j < 2; j++) {
		retval = -ENOMEM;
		urb[j] = usb_alloc_urb(num_packets, GFP_KERNEL);
		if (!urb[j])
			goto err;

		// Allocate memory for 2000bytes/sec (16Kb/s)
		buf = kmalloc(buf_size, GFP_KERNEL);
		if (!buf)
			goto err;
			
		// Fill the isochronous URB
		fill_isoc_urb(urb[j], dev, pipe, buf, 
			      num_packets, packet_size, complete,
			      context);
	}
	return 0;

 err:
	for (j = 0; j < 2; j++) {
		if (urb[j]) {
			if (urb[j]->transfer_buffer)
				kfree(urb[j]->transfer_buffer);
			urb[j]->transfer_buffer = NULL;
			usb_free_urb(urb[j]);
			urb[j] = NULL;
		}
	}
	return retval;
}
Esempio n. 4
0
static void
tx_iso_complete(struct urb *urb)
{
	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;

	fifon = fifo->fifonum;
	status = urb->status;

	tx_offset = 0;

	/* ISO transfer only partially completed,
	   look at individual frame status for details */
	if (status == -EXDEV) {
		DBG(HFCUSB_DBG_VERBOSE_USB, "HFC-S USB: tx_iso_complete with -EXDEV"
		    ", urb->status %d, fifonum %d\n",
		    status, fifon);

		for (k = 0; k < iso_packets[fifon]; ++k) {
			errcode = urb->iso_frame_desc[k].status;
			if (errcode)
				DBG(HFCUSB_DBG_VERBOSE_USB, "HFC-S USB: tx_iso_complete "
				    "packet %i, status: %i\n",
				    k, errcode);
		}

		// clear status, so go on with ISO transfers
		status = 0;
	}

	if (fifo->active && !status) {
		transp_mode = 0;
		if (fifon < 4 && hfc->b_mode[fifon / 2] == L1_MODE_TRANS)
			transp_mode = 1;

		/* is FifoFull-threshold set for our channel? */
		threshbit = (hfc->threshold_mask & (1 << fifon));
		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 = 0;

		/* 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 = 1;
				}

				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 = 1;
				fifo->hif->l1l2(fifo->hif,
						PH_DATA | CONFIRM,
						(void *) (unsigned long) fifo->skbuff->
						truesize);
				if (fifo->skbuff && fifo->delete_flg) {
					dev_kfree_skb_any(fifo->skbuff);
					fifo->skbuff = NULL;
					fifo->delete_flg = 0;
				}
				frame_complete = 0;
			}
		}
		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: error(%i): '%s', fifonum=%d\n",
			       status, symbolic(urb_errlist, status), fifon);
		}
	}
}
Esempio n. 5
0
static void
tx_iso_complete(struct urb *urb)
{
	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;

	fifon = fifo->fifonum;
	status = urb->status;

	tx_offset = 0;

	
	if (status == -EXDEV) {
		DBG(HFCUSB_DBG_VERBOSE_USB, "HFC-S USB: tx_iso_complete with -EXDEV"
		    ", urb->status %d, fifonum %d\n",
		    status, fifon);

		for (k = 0; k < iso_packets[fifon]; ++k) {
			errcode = urb->iso_frame_desc[k].status;
			if (errcode)
				DBG(HFCUSB_DBG_VERBOSE_USB, "HFC-S USB: tx_iso_complete "
				       "packet %i, status: %i\n",
				       k, errcode);
		}

		
		status = 0;
	}

	if (fifo->active && !status) {
		transp_mode = 0;
		if (fifon < 4 && hfc->b_mode[fifon / 2] == L1_MODE_TRANS)
			transp_mode = 1;

		
		threshbit = (hfc->threshold_mask & (1 << fifon));
		num_isoc_packets = iso_packets[fifon];

		
		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 = 0;

		
		for (k = 0; k < num_isoc_packets; ++k) {
			if (fifo->skbuff) {
				len = fifo->skbuff->len;
				
				fifo->bit_line -= sink;
				current_len = (0 - fifo->bit_line) / 8;
				
				if (current_len > 14)
					current_len = 14;
				current_len =
				    (len <=
				     current_len) ? len : current_len;
				
				fifo->bit_line += current_len * 8;

				context_iso_urb->buffer[tx_offset] = 0;
				if (current_len == len) {
					if (!transp_mode) {
						
						context_iso_urb->
						    buffer[tx_offset] = 1;
						
						fifo->bit_line += 32;
					}
					frame_complete = 1;
				}

				memcpy(context_iso_urb->buffer +
				       tx_offset + 1, fifo->skbuff->data,
				       current_len);
				skb_pull(fifo->skbuff, current_len);

				
				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;	

				if (fifo->bit_line < BITLINE_INF) {
					fifo->bit_line = BITLINE_INF;
				}
			}

			if (frame_complete) {
				fifo->delete_flg = 1;
				fifo->hif->l1l2(fifo->hif,
						PH_DATA | CONFIRM,
						(void *) (unsigned long) fifo->skbuff->
						truesize);
				if (fifo->skbuff && fifo->delete_flg) {
					dev_kfree_skb_any(fifo->skbuff);
					fifo->skbuff = NULL;
					fifo->delete_flg = 0;
				}
				frame_complete = 0;
			}
		}
		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: error(%i): '%s', fifonum=%d\n",
			       status, symbolic(urb_errlist, status), fifon);
		}
	}
}
Esempio n. 6
0
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;
	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 */