Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fea34091 authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman
Browse files

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: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent bdd016ba
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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);
	}
+16 −2
Original line number Diff line number Diff line
@@ -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)
+30 −0
Original line number Diff line number Diff line
@@ -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,