https://github.com/anatol/android-tools/blob/2f8405a47909861c9359fe4797e7b4a0fba4dc12/patches/adb/0023-Update-usage-of-usbdevfs_urb-to-match-new-kernel-UAP.patch https://github.com/nmeum/android-tools/issues/74 https://bugs.gentoo.org/876328 From c830c90995fc0877348e2ed9cdeccf9b739138d2 Mon Sep 17 00:00:00 2001 From: Anatol Pomozov Date: Mon, 10 Oct 2022 10:47:57 -0700 Subject: [PATCH] Update usage of usbdevfs_urb to match new kernel UAPI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Linux kernel API has been changed by commit 94dfc73e7cf4 ("treewide: uapi: Replace zero-length arrays with flexible-array members") where zero-length array iso_frame_desc in struct usbdevfs_urb was replaced with a proper flexible-array member. Current USB API usage causes a compilation error at Linux 6.0: In file included from /home/mae/.cache/kiss/proc/121205/build/android-tools/vendor/adb/client/usb_linux.cpp:28: /usr/include/linux/usbdevice_fs.h:134:41: error: flexible array member ‘usbdevfs_urb::iso_frame_desc’ not at end of ‘struct usb_handle’ 134 | struct usbdevfs_iso_packet_desc iso_frame_desc[]; | ^~~~~~~~~~~~~~ /home/mae/.cache/kiss/proc/121205/build/android-tools/vendor/adb/client/usb_linux.cpp:76:18: note: next member ‘usbdevfs_urb usb_handle::urb_out’ declared here 76 | usbdevfs_urb urb_out; | ^~~~~~~ /home/mae/.cache/kiss/proc/121205/build/android-tools/vendor/adb/client/usb_linux.cpp:61:8: note: in the definition of ‘struct usb_handle’ 61 | struct usb_handle { | ^~~~~~~~~~ Fix it by using pointers to a struct with flexible-array members. Current fix works both with the old and the new API. See https://github.com/nmeum/android-tools/issues/74 for more context. Tested: built on Linux against kernel 5.19 and 6.0; 'adb shell' over USB cable Acked-by: Gustavo A. R. Silva gustavoars@kernel.org Change-Id: I7f0f7b35d9a3ab980d3520b541b60c7857a6b101 Signed-off-by: Anatol Pomozov --- a/client/usb_linux.cpp +++ b/client/usb_linux.cpp @@ -71,8 +71,8 @@ struct usb_handle { unsigned zero_mask; unsigned writeable = 1; - usbdevfs_urb urb_in; - usbdevfs_urb urb_out; + usbdevfs_urb *urb_in; + usbdevfs_urb *urb_out; bool urb_in_busy = false; bool urb_out_busy = false; @@ -303,7 +303,7 @@ static int usb_bulk_write(usb_handle* h, const void* data, int len) { std::unique_lock lock(h->mutex); D("++ usb_bulk_write ++"); - usbdevfs_urb* urb = &h->urb_out; + usbdevfs_urb* urb = h->urb_out; memset(urb, 0, sizeof(*urb)); urb->type = USBDEVFS_URB_TYPE_BULK; urb->endpoint = h->ep_out; @@ -342,7 +342,7 @@ static int usb_bulk_read(usb_handle* h, void* data, int len) { std::unique_lock lock(h->mutex); D("++ usb_bulk_read ++"); - usbdevfs_urb* urb = &h->urb_in; + usbdevfs_urb* urb = h->urb_in; memset(urb, 0, sizeof(*urb)); urb->type = USBDEVFS_URB_TYPE_BULK; urb->endpoint = h->ep_in; @@ -387,7 +387,7 @@ static int usb_bulk_read(usb_handle* h, void* data, int len) { } D("[ urb @%p status = %d, actual = %d ]", out, out->status, out->actual_length); - if (out == &h->urb_in) { + if (out == h->urb_in) { D("[ reap urb - IN complete ]"); h->urb_in_busy = false; if (urb->status != 0) { @@ -396,7 +396,7 @@ static int usb_bulk_read(usb_handle* h, void* data, int len) { } return urb->actual_length; } - if (out == &h->urb_out) { + if (out == h->urb_out) { D("[ reap urb - OUT compelete ]"); h->urb_out_busy = false; h->cv.notify_all(); @@ -500,10 +500,10 @@ void usb_kick(usb_handle* h) { ** but this ensures that a reader blocked on REAPURB ** will get unblocked */ - ioctl(h->fd, USBDEVFS_DISCARDURB, &h->urb_in); - ioctl(h->fd, USBDEVFS_DISCARDURB, &h->urb_out); - h->urb_in.status = -ENODEV; - h->urb_out.status = -ENODEV; + ioctl(h->fd, USBDEVFS_DISCARDURB, h->urb_in); + ioctl(h->fd, USBDEVFS_DISCARDURB, h->urb_out); + h->urb_in->status = -ENODEV; + h->urb_out->status = -ENODEV; h->urb_in_busy = false; h->urb_out_busy = false; h->cv.notify_all(); @@ -519,6 +519,8 @@ int usb_close(usb_handle* h) { D("-- usb close %p (fd = %d) --", h, h->fd); + delete h->urb_in; + delete h->urb_out; delete h; return 0; @@ -572,6 +574,8 @@ static void register_device(const char* dev_name, const char* dev_path, unsigned usb->ep_out = ep_out; usb->zero_mask = zero_mask; usb->max_packet_size = max_packet_size; + usb->urb_in = new usbdevfs_urb; + usb->urb_out = new usbdevfs_urb; // Initialize mark so we don't get garbage collected after the device scan. usb->mark = true;