usb: sandbox: Fix emulator device select logic in usb_emul_find_devnum()

Current emulator select logic in usb_emul_find_devnum() is to test
the USB address. The USB address of the device being enumerated is
initialized to zero at the beginning of the enumeration process in
usb_setup_device(). At this point, the saved USB address in the
platform data has not been assigned to any valid USB address either.
This means: the logic will select an emulator device according to
its sequence of declaring order in the device tree. Take test.dts
for example, flash-stick@0 will be selected before flash-stick@1.
But unfortunately such logic is wrong.

In fact USB devices show up in a random order during the enumeration
which means usb_emul_find_devnum() may be called on port 3 for keyb@3
before on port 0 for flash-stick@0.

To fix this, we introduce a new emulator uclass specific platdata
to store the USB device's port number on its parent hub, and update
the logic to test the port number instead.

Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
diff --git a/drivers/usb/emul/sandbox_hub.c b/drivers/usb/emul/sandbox_hub.c
index 9ed7000..8ed7a0f 100644
--- a/drivers/usb/emul/sandbox_hub.c
+++ b/drivers/usb/emul/sandbox_hub.c
@@ -280,8 +280,10 @@
 static int sandbox_child_post_bind(struct udevice *dev)
 {
 	struct sandbox_hub_platdata *plat = dev_get_parent_platdata(dev);
+	struct usb_emul_platdata *emul = dev_get_uclass_platdata(dev);
 
 	plat->port = dev_read_u32_default(dev, "reg", -1);
+	emul->port1 = plat->port + 1;
 
 	return 0;
 }
diff --git a/drivers/usb/emul/usb-emul-uclass.c b/drivers/usb/emul/usb-emul-uclass.c
index e4a267b..1203eb2 100644
--- a/drivers/usb/emul/usb-emul-uclass.c
+++ b/drivers/usb/emul/usb-emul-uclass.c
@@ -107,7 +107,7 @@
 	return upto ? upto : length ? -EIO : 0;
 }
 
-static int usb_emul_find_devnum(int devnum, struct udevice **emulp)
+static int usb_emul_find_devnum(int devnum, int port1, struct udevice **emulp)
 {
 	struct udevice *dev;
 	struct uclass *uc;
@@ -120,7 +120,37 @@
 	uclass_foreach_dev(dev, uc) {
 		struct usb_dev_platdata *udev = dev_get_parent_platdata(dev);
 
-		if (udev->devnum == devnum) {
+		/*
+		 * devnum is initialzied to zero at the beginning of the
+		 * enumeration process in usb_setup_device(). At this
+		 * point, udev->devnum has not been assigned to any valid
+		 * USB address either, so we can't rely on the comparison
+		 * result between udev->devnum and devnum to select an
+		 * emulator device.
+		 */
+		if (!devnum) {
+			struct usb_emul_platdata *plat;
+
+			/*
+			 * If the parent is sandbox USB controller, we are
+			 * the root hub. And there is only one root hub
+			 * in the system.
+			 */
+			if (device_get_uclass_id(dev->parent) == UCLASS_USB) {
+				debug("%s: Found emulator '%s'\n",
+				      __func__, dev->name);
+				*emulp = dev;
+				return 0;
+			}
+
+			plat = dev_get_uclass_platdata(dev);
+			if (plat->port1 == port1) {
+				debug("%s: Found emulator '%s', port %d\n",
+				      __func__, dev->name, port1);
+				*emulp = dev;
+				return 0;
+			}
+		} else if (udev->devnum == devnum) {
 			debug("%s: Found emulator '%s', addr %d\n", __func__,
 			      dev->name, udev->devnum);
 			*emulp = dev;
@@ -132,18 +162,19 @@
 	return -ENOENT;
 }
 
-int usb_emul_find(struct udevice *bus, ulong pipe, struct udevice **emulp)
+int usb_emul_find(struct udevice *bus, ulong pipe, int port1,
+		  struct udevice **emulp)
 {
 	int devnum = usb_pipedevice(pipe);
 
-	return usb_emul_find_devnum(devnum, emulp);
+	return usb_emul_find_devnum(devnum, port1, emulp);
 }
 
 int usb_emul_find_for_dev(struct udevice *dev, struct udevice **emulp)
 {
 	struct usb_dev_platdata *udev = dev_get_parent_platdata(dev);
 
-	return usb_emul_find_devnum(udev->devnum, emulp);
+	return usb_emul_find_devnum(udev->devnum, 0, emulp);
 }
 
 int usb_emul_control(struct udevice *emul, struct usb_device *udev,
@@ -276,6 +307,7 @@
 	.id		= UCLASS_USB_EMUL,
 	.name		= "usb_emul",
 	.post_bind	= dm_scan_fdt_dev,
+	.per_device_platdata_auto_alloc_size = sizeof(struct usb_emul_platdata),
 	.per_child_auto_alloc_size = sizeof(struct usb_device),
 	.per_child_platdata_auto_alloc_size = sizeof(struct usb_dev_platdata),
 };
diff --git a/drivers/usb/host/usb-sandbox.c b/drivers/usb/host/usb-sandbox.c
index f85d36b..15055b3 100644
--- a/drivers/usb/host/usb-sandbox.c
+++ b/drivers/usb/host/usb-sandbox.c
@@ -50,7 +50,7 @@
 
 	/* Just use child of dev as emulator? */
 	debug("%s: bus=%s\n", __func__, bus->name);
-	ret = usb_emul_find(bus, pipe, &emul);
+	ret = usb_emul_find(bus, pipe, udev->portnr, &emul);
 	usbmon_trace(bus, pipe, setup, emul);
 	if (ret)
 		return ret;
@@ -83,7 +83,7 @@
 
 	/* Just use child of dev as emulator? */
 	debug("%s: bus=%s\n", __func__, bus->name);
-	ret = usb_emul_find(bus, pipe, &emul);
+	ret = usb_emul_find(bus, pipe, udev->portnr, &emul);
 	usbmon_trace(bus, pipe, NULL, emul);
 	if (ret)
 		return ret;
@@ -109,7 +109,7 @@
 
 	/* Just use child of dev as emulator? */
 	debug("%s: bus=%s\n", __func__, bus->name);
-	ret = usb_emul_find(bus, pipe, &emul);
+	ret = usb_emul_find(bus, pipe, udev->portnr, &emul);
 	usbmon_trace(bus, pipe, NULL, emul);
 	if (ret)
 		return ret;