Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 1 Nov 2009 21:48:18 +0000 (UTC)
From:      Andrew Thompson <thompsa@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r198776 - head/sys/dev/usb
Message-ID:  <200911012148.nA1LmI6R036292@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: thompsa
Date: Sun Nov  1 21:48:18 2009
New Revision: 198776
URL: http://svn.freebsd.org/changeset/base/198776

Log:
  - Add usb_fill_bulk_urb() and usb_bulk_msg() linux compat functions [1]
  - Don't write actual length if the actual length pointer is NULL [2]
  - correct Linux Compatibility error codes for short isochronous IN transfers
    and make status field signed.
  
  Submitted by:	Leunam Elebek [1], Manuel Gebele [2]

Modified:
  head/sys/dev/usb/usb_compat_linux.c
  head/sys/dev/usb/usb_compat_linux.h

Modified: head/sys/dev/usb/usb_compat_linux.c
==============================================================================
--- head/sys/dev/usb/usb_compat_linux.c	Sun Nov  1 21:44:37 2009	(r198775)
+++ head/sys/dev/usb/usb_compat_linux.c	Sun Nov  1 21:48:18 2009	(r198776)
@@ -624,10 +624,11 @@ usb_start_wait_urb(struct urb *urb, usb_
 done:
 	if (do_unlock)
 		mtx_unlock(&Giant);
-	if (err) {
-		*p_actlen = 0;
-	} else {
-		*p_actlen = urb->actual_length;
+	if (p_actlen != NULL) {
+		if (err)
+			*p_actlen = 0;
+		else
+			*p_actlen = urb->actual_length;
 	}
 	return (err);
 }
@@ -1362,8 +1363,17 @@ usb_linux_isoc_callback(struct usb_xfer 
 
 			for (x = 0; x < urb->number_of_packets; x++) {
 				uipd = urb->iso_frame_desc + x;
+				if (uipd->length > xfer->frlengths[x]) {
+					if (urb->transfer_flags & URB_SHORT_NOT_OK) {
+						/* XXX should be EREMOTEIO */
+						uipd->status = -EPIPE;
+					} else {
+						uipd->status = 0;
+					}
+				} else {
+					uipd->status = 0;
+				}
 				uipd->actual_length = xfer->frlengths[x];
-				uipd->status = 0;
 				if (!xfer->flags.ext_buffer) {
 					usbd_copy_out(xfer->frbuffers, offset,
 					    USB_ADD_BYTES(urb->transfer_buffer,
@@ -1385,8 +1395,8 @@ usb_linux_isoc_callback(struct usb_xfer 
 		if (xfer->actlen < xfer->sumlen) {
 			/* short transfer */
 			if (urb->transfer_flags & URB_SHORT_NOT_OK) {
-				urb->status = -EPIPE;	/* XXX should be
-							 * EREMOTEIO */
+				/* XXX should be EREMOTEIO */
+				urb->status = -EPIPE;
 			} else {
 				urb->status = 0;
 			}
@@ -1482,6 +1492,7 @@ tr_setup:
 		/* Set zero for "actual_length" */
 		for (x = 0; x < urb->number_of_packets; x++) {
 			urb->iso_frame_desc[x].actual_length = 0;
+			urb->iso_frame_desc[x].status = urb->status;
 		}
 
 		/* call callback */
@@ -1663,3 +1674,58 @@ setup_bulk:
 		goto tr_setup;
 	}
 }
+
+/*------------------------------------------------------------------------*
+ *	usb_fill_bulk_urb
+ *------------------------------------------------------------------------*/
+void
+usb_fill_bulk_urb(struct urb *urb, struct usb_device *udev,
+    struct usb_host_endpoint *uhe, void *buf,
+    int length, usb_complete_t callback, void *arg)
+{
+	urb->dev = udev;
+	urb->endpoint = uhe;
+	urb->transfer_buffer = buf;
+	urb->transfer_buffer_length = length;
+	urb->complete = callback;
+	urb->context = arg;
+}
+
+/*------------------------------------------------------------------------*
+ *	usb_bulk_msg
+ *
+ * NOTE: This function can also be used for interrupt endpoints!
+ *
+ * Return values:
+ *    0: Success
+ * Else: Failure
+ *------------------------------------------------------------------------*/
+int
+usb_bulk_msg(struct usb_device *udev, struct usb_host_endpoint *uhe,
+    void *data, int len, uint16_t *pactlen, usb_timeout_t timeout)
+{
+	struct urb *urb;
+	int err;
+
+	if (uhe == NULL)
+		return (-EINVAL);
+	if (len < 0)
+		return (-EINVAL);
+
+	err = usb_setup_endpoint(udev, uhe, 4096 /* bytes */);
+	if (err)
+		return (err);
+
+	urb = usb_alloc_urb(0, 0);
+	if (urb == NULL)
+		return (-ENOMEM);
+
+        usb_fill_bulk_urb(urb, udev, uhe, data, len,
+	    usb_linux_wait_complete, NULL);
+
+	err = usb_start_wait_urb(urb, timeout, pactlen);
+
+	usb_free_urb(urb);
+
+	return (err);
+}

Modified: head/sys/dev/usb/usb_compat_linux.h
==============================================================================
--- head/sys/dev/usb/usb_compat_linux.h	Sun Nov  1 21:44:37 2009	(r198775)
+++ head/sys/dev/usb/usb_compat_linux.h	Sun Nov  1 21:48:18 2009	(r198776)
@@ -217,7 +217,7 @@ struct usb_iso_packet_descriptor {
 					 * packets are usually back to back) */
 	uint16_t length;		/* expected length */
 	uint16_t actual_length;
-	uint16_t status;
+	 int16_t status;		/* transfer status */
 };
 
 /*
@@ -299,6 +299,11 @@ void	usb_set_intfdata(struct usb_interfa
 void	usb_linux_register(void *arg);
 void	usb_linux_deregister(void *arg);
 
+void	usb_fill_bulk_urb(struct urb *, struct usb_device *,
+	    struct usb_host_endpoint *, void *, int, usb_complete_t, void *);
+int	usb_bulk_msg(struct usb_device *, struct usb_host_endpoint *,
+	    void *, int, uint16_t *, usb_timeout_t);
+
 #define	interface_to_usbdev(intf) (intf)->linux_udev
 #define	interface_to_bsddev(intf) (intf)->linux_udev
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200911012148.nA1LmI6R036292>