Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=fea3409112a93581db18da4c4332c8bf8d68af6b
Commit:     fea3409112a93581db18da4c4332c8bf8d68af6b
Parent:     bdd016ba64d909329cb4bacacc8443901c00e112
Author:     Alan Stern <[EMAIL PROTECTED]>
AuthorDate: Mon Jul 30 17:06:16 2007 -0400
Committer:  Greg Kroah-Hartman <[EMAIL PROTECTED]>
CommitDate: Fri Oct 12 14:55:00 2007 -0700

    USB: add direction bit to urb->transfer_flags
    
    This patch (as945) adds a bit to urb->transfer_flags for recording the
    direction of the URB.  The bit is set/cleared automatically in
    usb_submit_urb() so drivers don't have to worry about it (although as
    a result, it isn't valid until the URB has been submitted).  Inline
    routines are added for easily checking an URB's direction.  They
    replace calls to usb_pipein in the DMA-mapping parts of hcd.c.
    
    For non-control endpoints, the direction is determined directly from
    the endpoint descriptor.  However control endpoints are
    bi-directional; for them the direction is determined from the
    bRequestType byte and the wLength value in the setup packet.
    
    Signed-off-by: Alan Stern <[EMAIL PROTECTED]>
    Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>
---
 drivers/usb/core/hcd.c |    4 ++--
 drivers/usb/core/urb.c |   18 ++++++++++++++++--
 include/linux/usb.h    |   30 ++++++++++++++++++++++++++++++
 3 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index cc5b1d3..bcbaedc 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -928,7 +928,7 @@ static void urb_unlink(struct usb_hcd *hcd, struct urb *urb)
                        dma_unmap_single (hcd->self.controller,
                                        urb->transfer_dma,
                                        urb->transfer_buffer_length,
-                                       usb_pipein (urb->pipe)
+                                       usb_urb_dir_in(urb)
                                            ? DMA_FROM_DEVICE
                                            : DMA_TO_DEVICE);
        }
@@ -1014,7 +1014,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
                                        hcd->self.controller,
                                        urb->transfer_buffer,
                                        urb->transfer_buffer_length,
-                                       usb_pipein (urb->pipe)
+                                       usb_urb_dir_in(urb)
                                            ? DMA_FROM_DEVICE
                                            : DMA_TO_DEVICE);
        }
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index ff53acb..1a64a6a 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -309,7 +309,21 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
         * and don't need to duplicate tests
         */
        xfertype = usb_endpoint_type(&ep->desc);
-       is_out = usb_pipeout(urb->pipe);
+       if (xfertype == USB_ENDPOINT_XFER_CONTROL) {
+               struct usb_ctrlrequest *setup =
+                               (struct usb_ctrlrequest *) urb->setup_packet;
+
+               if (!setup)
+                       return -ENOEXEC;
+               is_out = !(setup->bRequestType & USB_DIR_IN) ||
+                               !setup->wLength;
+       } else {
+               is_out = usb_endpoint_dir_out(&ep->desc);
+       }
+
+       /* Cache the direction for later use */
+       urb->transfer_flags = (urb->transfer_flags & ~URB_DIR_MASK) |
+                       (is_out ? URB_DIR_OUT : URB_DIR_IN);
 
        if (xfertype != USB_ENDPOINT_XFER_CONTROL &&
                        dev->state < USB_STATE_CONFIGURED)
@@ -363,7 +377,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
 
        /* enforce simple/standard policy */
        allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP |
-                       URB_NO_INTERRUPT);
+                       URB_NO_INTERRUPT | URB_DIR_MASK);
        switch (xfertype) {
        case USB_ENDPOINT_XFER_BULK:
                if (is_out)
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 818a1b4..9d08f5a 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -1021,6 +1021,8 @@ extern int usb_disabled(void);
 
 /*
  * urb->transfer_flags:
+ *
+ * Note: URB_DIR_IN/OUT is automatically set in usb_submit_urb().
  */
 #define URB_SHORT_NOT_OK       0x0001  /* report short reads as errors */
 #define URB_ISO_ASAP           0x0002  /* iso-only, urb->start_frame
@@ -1033,6 +1035,10 @@ extern int usb_disabled(void);
                                         * needed */
 #define URB_FREE_BUFFER                0x0100  /* Free transfer buffer with 
the URB */
 
+#define URB_DIR_IN             0x0200  /* Transfer from device to host */
+#define URB_DIR_OUT            0
+#define URB_DIR_MASK           URB_DIR_IN
+
 struct usb_iso_packet_descriptor {
        unsigned int offset;
        unsigned int length;            /* expected length */
@@ -1380,6 +1386,30 @@ extern void usb_unanchor_urb(struct urb *urb);
 extern int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor,
                                         unsigned int timeout);
 
+/**
+ * usb_urb_dir_in - check if an URB describes an IN transfer
+ * @urb: URB to be checked
+ *
+ * Returns 1 if @urb describes an IN transfer (device-to-host),
+ * otherwise 0.
+ */
+static inline int usb_urb_dir_in(struct urb *urb)
+{
+       return (urb->transfer_flags & URB_DIR_MASK) != URB_DIR_OUT;
+}
+
+/**
+ * usb_urb_dir_out - check if an URB describes an OUT transfer
+ * @urb: URB to be checked
+ *
+ * Returns 1 if @urb describes an OUT transfer (host-to-device),
+ * otherwise 0.
+ */
+static inline int usb_urb_dir_out(struct urb *urb)
+{
+       return (urb->transfer_flags & URB_DIR_MASK) == URB_DIR_OUT;
+}
+
 void *usb_buffer_alloc (struct usb_device *dev, size_t size,
        gfp_t mem_flags, dma_addr_t *dma);
 void usb_buffer_free (struct usb_device *dev, size_t size,
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to