usb-linux: walk async urb list in cancel

Lookup async urbs which are to be canceled using the linked list
instead of the direct opaque pointer.  There are two reasons we
are doing that:  First, to avoid the opaque poiner to the callback,
which is needed for upcoming cleanups.  Second, because we might
need multiple urbs per request for highspeed support, so a single
opaque pointer doesn't cut it any more anyway.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
diff --git a/usb-linux.c b/usb-linux.c
index 3213215..5e9c5e4 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -315,19 +315,25 @@
     }
 }
 
-static void async_cancel(USBPacket *unused, void *opaque)
+static void async_cancel(USBPacket *p, void *opaque)
 {
-    AsyncURB *aurb = opaque;
-    USBHostDevice *s = aurb->hdev;
+    USBHostDevice *s = opaque;
+    AsyncURB *aurb;
 
-    DPRINTF("husb: async cancel. aurb %p\n", aurb);
+    QLIST_FOREACH(aurb, &s->aurbs, next) {
+        if (p != aurb->packet) {
+            continue;
+        }
 
-    /* Mark it as dead (see async_complete above) */
-    aurb->packet = NULL;
+        DPRINTF("husb: async cancel: packet %p, aurb %p\n", p, aurb);
 
-    int r = ioctl(s->fd, USBDEVFS_DISCARDURB, aurb);
-    if (r < 0) {
-        DPRINTF("husb: async. discard urb failed errno %d\n", errno);
+        /* Mark it as dead (see async_complete above) */
+        aurb->packet = NULL;
+
+        int r = ioctl(s->fd, USBDEVFS_DISCARDURB, aurb);
+        if (r < 0) {
+            DPRINTF("husb: async. discard urb failed errno %d\n", errno);
+        }
     }
 }
 
@@ -696,7 +702,7 @@
         }
     }
 
-    usb_defer_packet(p, async_cancel, aurb);
+    usb_defer_packet(p, async_cancel, s);
     return USB_RET_ASYNC;
 }
 
@@ -828,7 +834,7 @@
         }
     }
 
-    usb_defer_packet(p, async_cancel, aurb);
+    usb_defer_packet(p, async_cancel, s);
     return USB_RET_ASYNC;
 }