From 49eab53c95f038362ce77665a06d6d2ccbb327c7 Mon Sep 17 00:00:00 2001 From: Ookiineko Date: Tue, 26 Apr 2022 14:05:19 +0800 Subject: [PATCH] android-tools: add Termux-usb support for fastboot Signed-off-by: Ookiineko --- .../vendor_CMakeLists.fastboot.txt.patch | 4 +- .../vendor_core_fastboot_fastboot.cpp.patch | 282 ++++++++++++++++++ .../vendor_core_fastboot_fastboot.h.patch | 23 ++ .../vendor_core_fastboot_usb.h.patch | 35 +++ .../vendor_core_fastboot_usb_linux.cpp.patch | 211 +++++++++++++ 5 files changed, 553 insertions(+), 2 deletions(-) create mode 100644 packages/android-tools/vendor_core_fastboot_fastboot.cpp.patch create mode 100644 packages/android-tools/vendor_core_fastboot_fastboot.h.patch create mode 100644 packages/android-tools/vendor_core_fastboot_usb.h.patch create mode 100644 packages/android-tools/vendor_core_fastboot_usb_linux.cpp.patch diff --git a/packages/android-tools/vendor_CMakeLists.fastboot.txt.patch b/packages/android-tools/vendor_CMakeLists.fastboot.txt.patch index a0db7641c..62b40ee76 100644 --- a/packages/android-tools/vendor_CMakeLists.fastboot.txt.patch +++ b/packages/android-tools/vendor_CMakeLists.fastboot.txt.patch @@ -1,5 +1,5 @@ diff --git a/vendor/CMakeLists.fastboot.txt b/vendor/CMakeLists.fastboot.txt -index 1d43937..189d91b 100644 +index 1d43937..880bb8c 100644 --- a/vendor/CMakeLists.fastboot.txt +++ b/vendor/CMakeLists.fastboot.txt @@ -135,4 +135,4 @@ target_compile_definitions(fastboot PRIVATE @@ -7,4 +7,4 @@ index 1d43937..189d91b 100644 libsparse libzip libcutils liblog libfsmgr libutil libbase libext4 libselinux libsepol libdiagnoseusb crypto - z pcre2-8 pthread dl) -+ z pcre2-8 dl) ++ z pcre2-8 dl usb-1.0) diff --git a/packages/android-tools/vendor_core_fastboot_fastboot.cpp.patch b/packages/android-tools/vendor_core_fastboot_fastboot.cpp.patch new file mode 100644 index 000000000..67875670f --- /dev/null +++ b/packages/android-tools/vendor_core_fastboot_fastboot.cpp.patch @@ -0,0 +1,282 @@ +diff --git a/vendor/core/fastboot/fastboot.cpp b/vendor/core/fastboot/fastboot.cpp +index 0062e7e..9d2ee12 100644 +--- a/vendor/core/fastboot/fastboot.cpp ++++ b/vendor/core/fastboot/fastboot.cpp +@@ -63,6 +63,9 @@ + #include + #include + #include ++#ifdef ANDROID ++#include ++#endif + + #include "bootimg_utils.h" + #include "constants.h" +@@ -301,7 +304,11 @@ static int list_devices_callback(usb_ifc_info* info) { + // + // The returned Transport is a singleton, so multiple calls to this function will return the same + // object, and the caller should not attempt to delete the returned Transport. ++#ifdef ANDROID ++static Transport* open_device(libusb_context *context) { ++#else + static Transport* open_device() { ++#endif + bool announce = true; + + Socket::Protocol protocol = Socket::Protocol::kTcp; +@@ -342,7 +349,11 @@ static Transport* open_device() { + fprintf(stderr, "error: %s\n", error.c_str()); + } + } else { ++#ifdef ANDROID ++ transport = usb_open(match_fastboot, context); ++#else + transport = usb_open(match_fastboot); ++#endif + } + + if (transport != nullptr) { +@@ -357,11 +368,20 @@ static Transport* open_device() { + } + } + ++#ifdef ANDROID ++static void list_devices(libusb_context *context) { ++#else + static void list_devices() { ++#endif + // We don't actually open a USB device here, + // just getting our callback called so we can + // list all the connected devices. ++#ifdef ANDROID ++ usb_open(list_devices_callback, context); ++#else ++ + usb_open(list_devices_callback); ++#endif + } + + static void syntax_error(const char* fmt, ...) { +@@ -1341,7 +1361,11 @@ static bool is_userspace_fastboot() { + return fb->GetVar("is-userspace", &value) == fastboot::SUCCESS && value == "yes"; + } + ++#ifdef ANDROID ++static void reboot_to_userspace_fastboot(libusb_context *context) { ++#else + static void reboot_to_userspace_fastboot() { ++#endif + fb->RebootTo("fastboot"); + + auto* old_transport = fb->set_transport(nullptr); +@@ -1350,7 +1374,11 @@ static void reboot_to_userspace_fastboot() { + // Give the current connection time to close. + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + ++#ifdef ANDROID ++ fb->set_transport(open_device(context)); ++#else + fb->set_transport(open_device()); ++#endif + + if (!is_userspace_fastboot()) { + die("Failed to boot into userspace fastboot; one or more components might be unbootable."); +@@ -1381,7 +1409,11 @@ class FlashAllTool { + FlashAllTool(const ImageSource& source, const std::string& slot_override, bool skip_secondary, + bool wipe, bool force_flash); + ++#ifdef ANDROID ++ void Flash(libusb_context *context); ++#else + void Flash(); ++#endif + + private: + void CheckRequirements(); +@@ -1389,7 +1421,11 @@ class FlashAllTool { + void CollectImages(); + void FlashImages(const std::vector>& images); + void FlashImage(const Image& image, const std::string& slot, fastboot_buffer* buf); ++#ifdef ANDROID ++ void UpdateSuperPartition(libusb_context *context); ++#else + void UpdateSuperPartition(); ++#endif + + const ImageSource& source_; + std::string slot_override_; +@@ -1411,7 +1447,11 @@ FlashAllTool::FlashAllTool(const ImageSource& source, const std::string& slot_ov + { + } + ++#ifdef ANDROID ++void FlashAllTool::Flash(libusb_context *context) { ++#else + void FlashAllTool::Flash() { ++#endif + DumpInfo(); + CheckRequirements(); + +@@ -1433,7 +1473,11 @@ void FlashAllTool::Flash() { + FlashImages(boot_images_); + + // Sync the super partition. This will reboot to userspace fastboot if needed. ++#ifdef ANDROID ++ UpdateSuperPartition(context); ++#else + UpdateSuperPartition(); ++#endif + + // Resize any logical partition to 0, so each partition is reset to 0 + // extents, and will achieve more optimal allocation. +@@ -1522,13 +1566,21 @@ void FlashAllTool::FlashImage(const Image& image, const std::string& slot, fastb + do_for_partitions(image.part_name, slot, flash, false); + } + ++#ifdef ANDROID ++void FlashAllTool::UpdateSuperPartition(libusb_context *context) { ++#else + void FlashAllTool::UpdateSuperPartition() { ++#endif + unique_fd fd = source_.OpenFile("super_empty.img"); + if (fd < 0) { + return; + } + if (!is_userspace_fastboot()) { ++#ifdef ANDROID ++ reboot_to_userspace_fastboot(context); ++#else + reboot_to_userspace_fastboot(); ++#endif + } + + std::string super_name; +@@ -1576,7 +1628,11 @@ unique_fd ZipImageSource::OpenFile(const std::string& name) const { + } + + static void do_update(const char* filename, const std::string& slot_override, bool skip_secondary, ++#ifdef ANDROID ++ bool force_flash, libusb_context *context) { ++#else + bool force_flash) { ++#endif + ZipArchiveHandle zip; + int error = OpenArchive(filename, &zip); + if (error != 0) { +@@ -1584,7 +1640,11 @@ static void do_update(const char* filename, const std::string& slot_override, bo + } + + FlashAllTool tool(ZipImageSource(zip), slot_override, skip_secondary, false, force_flash); ++#ifdef ANDROID ++ tool.Flash(context); ++#else + tool.Flash(); ++#endif + + CloseArchive(zip); + } +@@ -1609,9 +1669,17 @@ unique_fd LocalImageSource::OpenFile(const std::string& name) const { + } + + static void do_flashall(const std::string& slot_override, bool skip_secondary, bool wipe, ++#ifdef ANDROID ++ bool force_flash, libusb_context *context) { ++#else + bool force_flash) { ++#endif + FlashAllTool tool(LocalImageSource(), slot_override, skip_secondary, wipe, force_flash); ++#ifdef ANDROID ++ tool.Flash(context); ++#else + tool.Flash(); ++#endif + } + + static std::string next_arg(std::vector* args) { +@@ -1840,7 +1908,20 @@ static void do_wipe_super(const std::string& image, const std::string& slot_over + } + } + ++#ifdef ANDROID ++int FastBootTool::Main(int argc, char* argv[]) { ++ libusb_context *context; ++ libusb_set_option(NULL, LIBUSB_OPTION_WEAK_AUTHORITY); ++ libusb_init(&context); ++ int rc = FastBootTool::RealMain(argc, argv, context); ++ libusb_exit(context); ++ return rc; ++} ++ ++int FastBootTool::RealMain(int argc, char* argv[], libusb_context *context) { ++#else + int FastBootTool::Main(int argc, char* argv[]) { ++#endif + bool wants_wipe = false; + bool wants_reboot = false; + bool wants_reboot_bootloader = false; +@@ -1981,7 +2062,11 @@ int FastBootTool::Main(int argc, char* argv[]) { + if (argc == 0 && !wants_wipe && !wants_set_active) syntax_error("no command"); + + if (argc > 0 && !strcmp(*argv, "devices")) { ++#ifdef ANDROID ++ list_devices(context); ++#else + list_devices(); ++#endif + return 0; + } + +@@ -1989,7 +2074,11 @@ int FastBootTool::Main(int argc, char* argv[]) { + return show_help(); + } + ++#ifdef ANDROID ++ Transport* transport = open_device(context); ++#else + Transport* transport = open_device(); ++#endif + if (transport == nullptr) { + return 1; + } +@@ -2149,9 +2238,17 @@ int FastBootTool::Main(int argc, char* argv[]) { + } else if (command == "flashall") { + if (slot_override == "all") { + fprintf(stderr, "Warning: slot set to 'all'. Secondary slots will not be flashed.\n"); ++#ifdef ANDROID ++ do_flashall(slot_override, true, wants_wipe, force_flash, context); ++#else + do_flashall(slot_override, true, wants_wipe, force_flash); ++#endif + } else { ++#ifdef ANDROID ++ do_flashall(slot_override, skip_secondary, wants_wipe, force_flash, context); ++#else + do_flashall(slot_override, skip_secondary, wants_wipe, force_flash); ++#endif + } + wants_reboot = true; + } else if (command == "update") { +@@ -2163,7 +2260,11 @@ int FastBootTool::Main(int argc, char* argv[]) { + if (!args.empty()) { + filename = next_arg(&args); + } ++#ifdef ANDROID ++ do_update(filename.c_str(), slot_override, skip_secondary || slot_all, force_flash, context); ++#else + do_update(filename.c_str(), slot_override, skip_secondary || slot_all, force_flash); ++#endif + wants_reboot = true; + } else if (command == FB_CMD_SET_ACTIVE) { + std::string slot = verify_slot(next_arg(&args), false); +@@ -2266,7 +2367,11 @@ int FastBootTool::Main(int argc, char* argv[]) { + fb->RebootTo("recovery"); + fb->WaitForDisconnect(); + } else if (wants_reboot_fastboot) { ++#ifdef ANDROID ++ reboot_to_userspace_fastboot(context); ++#else + reboot_to_userspace_fastboot(); ++#endif + } + + fprintf(stderr, "Finished. Total time: %.3fs\n", (now() - start)); diff --git a/packages/android-tools/vendor_core_fastboot_fastboot.h.patch b/packages/android-tools/vendor_core_fastboot_fastboot.h.patch new file mode 100644 index 000000000..fbfec450b --- /dev/null +++ b/packages/android-tools/vendor_core_fastboot_fastboot.h.patch @@ -0,0 +1,23 @@ +diff --git a/vendor/core/fastboot/fastboot.h b/vendor/core/fastboot/fastboot.h +index c23793a..b7c07f0 100644 +--- a/vendor/core/fastboot/fastboot.h ++++ b/vendor/core/fastboot/fastboot.h +@@ -26,11 +26,18 @@ + * SUCH DAMAGE. + */ + ++#ifdef ANDROID ++#include ++#endif ++ + #include + + class FastBootTool { + public: + int Main(int argc, char* argv[]); ++#ifdef ANDROID ++ int RealMain(int argc, char* argv[], libusb_context *context); ++#endif + + void ParseOsPatchLevel(boot_img_hdr_v1*, const char*); + void ParseOsVersion(boot_img_hdr_v1*, const char*); diff --git a/packages/android-tools/vendor_core_fastboot_usb.h.patch b/packages/android-tools/vendor_core_fastboot_usb.h.patch new file mode 100644 index 000000000..b3f63a987 --- /dev/null +++ b/packages/android-tools/vendor_core_fastboot_usb.h.patch @@ -0,0 +1,35 @@ +diff --git a/vendor/core/fastboot/usb.h b/vendor/core/fastboot/usb.h +index e5f56e2..eea0075 100644 +--- a/vendor/core/fastboot/usb.h ++++ b/vendor/core/fastboot/usb.h +@@ -28,6 +28,10 @@ + + #pragma once + ++#ifdef ANDROID ++#include ++#endif ++ + #include "transport.h" + + struct usb_ifc_info { +@@ -52,6 +56,10 @@ struct usb_ifc_info { + char device_path[256]; + + char interface[256]; ++ ++#ifdef ANDROID ++ bool termux_usb; ++#endif + }; + + class UsbTransport : public Transport { +@@ -64,4 +72,8 @@ class UsbTransport : public Transport { + typedef int (*ifc_match_func)(usb_ifc_info *ifc); + + // 0 is non blocking ++#ifdef ANDROID ++UsbTransport* usb_open(ifc_match_func callback, libusb_context *context, uint32_t timeout_ms = 0); ++#else + UsbTransport* usb_open(ifc_match_func callback, uint32_t timeout_ms = 0); ++#endif diff --git a/packages/android-tools/vendor_core_fastboot_usb_linux.cpp.patch b/packages/android-tools/vendor_core_fastboot_usb_linux.cpp.patch new file mode 100644 index 000000000..90ea1217a --- /dev/null +++ b/packages/android-tools/vendor_core_fastboot_usb_linux.cpp.patch @@ -0,0 +1,211 @@ +diff --git a/vendor/core/fastboot/usb_linux.cpp b/vendor/core/fastboot/usb_linux.cpp +index 964488c..d03f3a2 100644 +--- a/vendor/core/fastboot/usb_linux.cpp ++++ b/vendor/core/fastboot/usb_linux.cpp +@@ -42,6 +42,9 @@ + #include + #include + #include ++#ifdef ANDROID ++#include ++#endif + + #include + #include +@@ -88,6 +91,10 @@ using namespace std::chrono_literals; + struct usb_handle + { + char fname[64]; ++#ifdef ANDROID ++ int fd; ++ bool termux_usb; ++#endif + int desc; + unsigned char ep_in; + unsigned char ep_out; +@@ -141,6 +148,9 @@ static int check(void *_desc, int len, unsigned type, int size) + } + + static int filter_usb_device(char* sysfs_name, ++#ifdef ANDROID ++ libusb_context *context, int fd, bool termux_usb, ++#endif + char *ptr, int len, int writable, + ifc_match_func callback, + int *ept_in_id, int *ept_out_id, int *ifc_id) +@@ -173,7 +183,13 @@ static int filter_usb_device(char* sysfs_name, + info.dev_subclass = dev->bDeviceSubClass; + info.dev_protocol = dev->bDeviceProtocol; + info.writable = writable; ++#ifdef ANDROID ++ info.termux_usb = termux_usb; + ++ if (termux_usb) ++ snprintf(info.device_path, sizeof(info.device_path), "fd:%d", fd); ++ else ++#endif + snprintf(info.device_path, sizeof(info.device_path), "usb:%s", sysfs_name); + + /* Read device serial number (if there is one). +@@ -184,6 +200,15 @@ static int filter_usb_device(char* sysfs_name, + */ + info.serial_number[0] = '\0'; + if (dev->iSerialNumber) { ++#ifdef ANDROID ++ if (termux_usb) { ++ libusb_device_handle *handle; ++ unsigned char serial_num[256]; ++ libusb_wrap_sys_device(context, fd, &handle); ++ libusb_get_string_descriptor_ascii(handle, dev->iSerialNumber, serial_num, sizeof(serial_num)); ++ snprintf(info.serial_number, sizeof(info.serial_number), "%s", serial_num); ++ } else { ++#endif + char path[80]; + int fd; + +@@ -204,6 +229,9 @@ static int filter_usb_device(char* sysfs_name, + info.serial_number[chars_read - 1] = '\0'; + } + } ++#ifdef ANDROID ++ } ++#endif + } + + for(i = 0; i < cfg->bNumInterfaces; i++) { +@@ -265,12 +293,20 @@ static int filter_usb_device(char* sysfs_name, + info.has_bulk_in = (in != -1); + info.has_bulk_out = (out != -1); + ++#ifdef ANDROID ++ if (termux_usb) ++ snprintf(info.interface, sizeof(info.interface), "fastboot\n"); ++ else { ++#endif + std::string interface; + auto path = android::base::StringPrintf("/sys/bus/usb/devices/%s/%s:1.%d/interface", + sysfs_name, sysfs_name, ifc->bInterfaceNumber); + if (android::base::ReadFileToString(path, &interface)) { + snprintf(info.interface, sizeof(info.interface), "%s", interface.c_str()); + } ++#ifdef ANDROID ++ } ++#endif + + if(callback(&info) == 0) { + *ept_in_id = in; +@@ -342,7 +378,11 @@ static int convert_to_devfs_name(const char* sysfs_name, + return 0; + } + ++#ifdef ANDROID ++static std::unique_ptr find_usb_device(const char* base, libusb_context *context, ifc_match_func callback) ++#else + static std::unique_ptr find_usb_device(const char* base, ifc_match_func callback) ++#endif + { + std::unique_ptr usb; + char devname[64]; +@@ -353,16 +393,47 @@ static std::unique_ptr find_usb_device(const char* base, ifc_match_f + int fd; + int writable; + ++#ifdef ANDROID ++ bool linux_usb, termux_usb; ++ linux_usb = termux_usb = true; ++ writable = 1; ++ char* fd_str = getenv("TERMUX_USB_FD"); ++ if (fd_str == nullptr) termux_usb = false; ++ else { ++ fd = strtol(fd_str, NULL, 10); ++ if (fcntl(fd, F_GETFD) == -1) termux_usb = false; ++ } ++#endif ++ + std::unique_ptr busdir(opendir(base), closedir); ++#ifdef ANDROID ++ if (busdir == 0) linux_usb = false; ++ ++ bool is_linux_usb, is_termux_usb; ++ ++ while (((is_linux_usb = (linux_usb && (de = readdir(busdir.get())))) || termux_usb) && (usb == nullptr)) { ++ is_termux_usb = !is_linux_usb; ++ ++ if (is_termux_usb) ++ termux_usb = false; ++ else if (badname(de->d_name)) continue; ++ ++ if (is_termux_usb || !convert_to_devfs_name(de->d_name, devname, sizeof(devname))) { ++#else + if (busdir == 0) return 0; + + while ((de = readdir(busdir.get())) && (usb == nullptr)) { + if (badname(de->d_name)) continue; + + if (!convert_to_devfs_name(de->d_name, devname, sizeof(devname))) { ++#endif + + // DBG("[ scanning %s ]\n", devname); + writable = 1; ++#ifdef ANDROID ++ if (is_termux_usb) lseek(fd, 0, SEEK_SET); ++ else { ++#endif + if ((fd = open(devname, O_RDWR)) < 0) { + // Check if we have read-only access, so we can give a helpful + // diagnostic like "adb devices" does. +@@ -371,12 +442,24 @@ static std::unique_ptr find_usb_device(const char* base, ifc_match_f + continue; + } + } ++#ifdef ANDROID ++ } ++#endif + + n = read(fd, desc, sizeof(desc)); + ++#ifdef ANDROID ++ if (filter_usb_device(de->d_name, context, fd, is_termux_usb, desc, n, writable, callback, &in, &out, &ifc) == 0) { ++#else + if (filter_usb_device(de->d_name, desc, n, writable, callback, &in, &out, &ifc) == 0) { ++#endif + usb.reset(new usb_handle()); ++#ifdef ANDROID ++ usb->fd = fd; ++ usb->termux_usb = is_termux_usb; ++#else + strcpy(usb->fname, devname); ++#endif + usb->ep_in = in; + usb->ep_out = out; + usb->desc = fd; +@@ -503,8 +586,13 @@ int LinuxUsbTransport::Reset() { + return 0; + } + ++#ifdef ANDROID ++UsbTransport* usb_open(ifc_match_func callback, libusb_context *context, uint32_t timeout_ms) { ++ std::unique_ptr handle = find_usb_device("/sys/bus/usb/devices", context, callback); ++#else + UsbTransport* usb_open(ifc_match_func callback, uint32_t timeout_ms) { + std::unique_ptr handle = find_usb_device("/sys/bus/usb/devices", callback); ++#endif + return handle ? new LinuxUsbTransport(std::move(handle), timeout_ms) : nullptr; + } + +@@ -516,7 +604,15 @@ int LinuxUsbTransport::WaitForDisconnect() + { + double deadline = now() + WAIT_FOR_DISCONNECT_TIMEOUT; + while (now() < deadline) { ++#ifdef ANDROID ++ if(handle_->termux_usb) { ++ if (fcntl(handle_->fd, F_GETFD) == -1) return 0; ++ } else { ++#endif + if (access(handle_->fname, F_OK)) return 0; ++#ifdef ANDROID ++ } ++#endif + std::this_thread::sleep_for(50ms); + } + return -1;