usb: sandbox: Add support for interrupt operations

Allow USB device emulation to support interrupt URBs so that we can use USB
keyboards with sandbox.

Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/drivers/usb/emul/usb-emul-uclass.c b/drivers/usb/emul/usb-emul-uclass.c
index 6b5f3c0..ee7ea5a 100644
--- a/drivers/usb/emul/usb-emul-uclass.c
+++ b/drivers/usb/emul/usb-emul-uclass.c
@@ -218,6 +218,18 @@
 	return ops->bulk(emul, udev, pipe, buffer, length);
 }
 
+int usb_emul_int(struct udevice *emul, struct usb_device *udev,
+		  unsigned long pipe, void *buffer, int length, int interval)
+{
+	struct dm_usb_ops *ops = usb_get_emul_ops(emul);
+
+	if (!ops->interrupt)
+		return -ENOSYS;
+	debug("%s: dev=%s\n", __func__, emul->name);
+
+	return ops->interrupt(emul, udev, pipe, buffer, length, interval);
+}
+
 int usb_emul_setup_device(struct udevice *dev, int maxpacketsize,
 			  struct usb_string *strings, void **desc_list)
 {
diff --git a/drivers/usb/host/usb-sandbox.c b/drivers/usb/host/usb-sandbox.c
index c5f9822..5e3d96c 100644
--- a/drivers/usb/host/usb-sandbox.c
+++ b/drivers/usb/host/usb-sandbox.c
@@ -87,6 +87,24 @@
 	return ret;
 }
 
+static int sandbox_submit_int(struct udevice *bus, struct usb_device *udev,
+			      unsigned long pipe, void *buffer, int length,
+			      int interval)
+{
+	struct udevice *emul;
+	int ret;
+
+	/* Just use child of dev as emulator? */
+	debug("%s: bus=%s\n", __func__, bus->name);
+	ret = usb_emul_find(bus, pipe, &emul);
+	usbmon_trace(bus, pipe, NULL, emul);
+	if (ret)
+		return ret;
+	ret = usb_emul_int(emul, udev, pipe, buffer, length, interval);
+
+	return ret;
+}
+
 static int sandbox_alloc_device(struct udevice *dev, struct usb_device *udev)
 {
 	return 0;
@@ -100,6 +118,7 @@
 static const struct dm_usb_ops sandbox_usb_ops = {
 	.control	= sandbox_submit_control,
 	.bulk		= sandbox_submit_bulk,
+	.interrupt	= sandbox_submit_int,
 	.alloc_device	= sandbox_alloc_device,
 };