]> git.sur5r.net Git - u-boot/blobdiff - drivers/usb/gadget/epautoconf.c
SPDX: Convert all of our single license tags to Linux Kernel style
[u-boot] / drivers / usb / gadget / epautoconf.c
index 7cf3c673ddd702641ce620205a0571a7df90bb94..179b94cdd0ae75759605a2617da9e6a5830de580 100644 (file)
@@ -1,30 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * epautoconf.c -- endpoint autoconfiguration for usb gadget drivers
  *
  * Copyright (C) 2004 David Brownell
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Ported to U-boot by: Thomas Smits <ts.smits@gmail.com> and
+ * Ported to U-Boot by: Thomas Smits <ts.smits@gmail.com> and
  *                      Remy Bohmer <linux@bohmer.net>
  */
 
 #include <common.h>
 #include <linux/usb/ch9.h>
-#include <asm/errno.h>
+#include <linux/errno.h>
 #include <linux/usb/gadget.h>
+#include <asm/unaligned.h>
 #include "gadget_chips.h"
 
 #define isdigit(c)      ('0' <= (c) && (c) <= '9')
@@ -127,7 +115,7 @@ static int ep_matches(
         * where it's an output parameter representing the full speed limit.
         * the usb spec fixes high speed bulk maxpacket at 512 bytes.
         */
-       max = 0x7ff & le16_to_cpu(desc->wMaxPacketSize);
+       max = 0x7ff & le16_to_cpu(get_unaligned(&desc->wMaxPacketSize));
        switch (type) {
        case USB_ENDPOINT_XFER_INT:
                /* INT:  limit 64 bytes full speed, 1024 high speed */
@@ -143,7 +131,8 @@ static int ep_matches(
                        return 0;
 
                /* BOTH:  "high bandwidth" works only at high speed */
-               if ((desc->wMaxPacketSize & __constant_cpu_to_le16(3<<11))) {
+               if ((get_unaligned(&desc->wMaxPacketSize) &
+                                       __constant_cpu_to_le16(3<<11))) {
                        if (!gadget->is_dualspeed)
                                return 0;
                        /* configure your hardware with enough buffering!! */
@@ -176,7 +165,7 @@ static int ep_matches(
                /* min() doesn't work on bitfields with gcc-3.5 */
                if (size > 64)
                        size = 64;
-               desc->wMaxPacketSize = cpu_to_le16(size);
+               put_unaligned(cpu_to_le16(size), &desc->wMaxPacketSize);
        }
        return 1;
 }
@@ -228,7 +217,7 @@ struct usb_ep *usb_ep_autoconfig(
        struct usb_endpoint_descriptor  *desc
 )
 {
-       struct usb_ep   *ep;
+       struct usb_ep   *ep = NULL;
        u8              type;
 
        type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
@@ -269,6 +258,28 @@ struct usb_ep *usb_ep_autoconfig(
                ep = find_ep(gadget, "ep1-bulk");
                if (ep && ep_matches(gadget, ep, desc))
                        return ep;
+       } else if (gadget_is_dwc3(gadget)) {
+               const char *name = NULL;
+               /*
+                * First try standard, common configuration: ep1in-bulk,
+                * ep2out-bulk, ep3in-int to match other udc drivers to avoid
+                * confusion in already deployed software (endpoint numbers
+                * hardcoded in userspace software/drivers)
+                */
+               if ((desc->bEndpointAddress & USB_DIR_IN) &&
+                   type == USB_ENDPOINT_XFER_BULK)
+                       name = "ep1in";
+               else if ((desc->bEndpointAddress & USB_DIR_IN) == 0 &&
+                        type == USB_ENDPOINT_XFER_BULK)
+                       name = "ep2out";
+               else if ((desc->bEndpointAddress & USB_DIR_IN) &&
+                        type == USB_ENDPOINT_XFER_INT)
+                       name = "ep3in";
+
+               if (name)
+                       ep = find_ep(gadget, name);
+               if (ep && ep_matches(gadget, ep, desc))
+                       return ep;
        }
 
        /* Second, look at endpoints until an unclaimed one looks usable */
@@ -302,4 +313,3 @@ void usb_ep_autoconfig_reset(struct usb_gadget *gadget)
 #endif
        epnum = 0;
 }
-