From 88187197c475d625d8911e0d0613d04bab908d38 Mon Sep 17 00:00:00 2001 From: Marcel Alexandru Nitan Date: Sat, 29 Jul 2023 13:04:11 +0300 Subject: [PATCH] Add usb gadget support --- Makefile | 2 +- src/androidusbisomanager.cpp | 49 ++++++++++++ src/configfsisomanager.cpp | 92 +++++++++------------- src/include/androidusbisomanager.h | 20 +++++ src/include/configfsisomanager.h | 17 ++--- src/include/util.h | 13 ++-- src/main.cpp | 119 ++++++++++++++--------------- src/util.cpp | 60 +++++++-------- 8 files changed, 206 insertions(+), 166 deletions(-) create mode 100644 src/androidusbisomanager.cpp create mode 100644 src/include/androidusbisomanager.h diff --git a/Makefile b/Makefile index 762f72e..2e5b6db 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ CC = g++ CFLAGS = -I./src/include -SRCS = src/util.cpp src/configfsisomanager.cpp src/main.cpp +SRCS = src/util.cpp src/configfsisomanager.cpp src/androidusbisomanager.cpp src/main.cpp OBJS = $(SRCS:.cpp=.o) TARGET = isodrive INSTALL_DIR = /usr/local/bin diff --git a/src/androidusbisomanager.cpp b/src/androidusbisomanager.cpp new file mode 100644 index 0000000..9ec0211 --- /dev/null +++ b/src/androidusbisomanager.cpp @@ -0,0 +1,49 @@ +#include +#include + +#include "androidusbisomanager.h" +#include "util.h" +#include +#include +#include +#include + +bool usb_supported() { return isfile((char *)ANDROID0_SYSFS_ENABLE); } + +void usb_mount_iso(char *iso_path) { + + if (usb_enabled()) + usb_set_enabled(false); + + sysfs_write((char *)ANDROID0_SYSFS_IMG_FILE, iso_path); + + char *features = (char *)"mass_storage"; + + sysfs_write((char *)ANDROID0_SYSFS_FEATURES, features); + + usb_set_enabled(true); +} + +void usb_reset_iso() { + usb_mount_iso((char *)""); + + if (usb_enabled()) + usb_set_enabled(false); + + char *features = (char *)"mtp"; + + sysfs_write((char *)ANDROID0_SYSFS_FEATURES, features); + + usb_set_enabled(true); +} + +bool usb_enabled() { + return strcmp(sysfs_read((char *)ANDROID0_SYSFS_ENABLE), "1") == 0; +} + +void usb_set_enabled(bool enabled) { + if (enabled) + sysfs_write((char *)ANDROID0_SYSFS_ENABLE, (char *)"1"); + else + sysfs_write((char *)ANDROID0_SYSFS_ENABLE, (char *)"0"); +} \ No newline at end of file diff --git a/src/configfsisomanager.cpp b/src/configfsisomanager.cpp index 9c2f445..403f07a 100644 --- a/src/configfsisomanager.cpp +++ b/src/configfsisomanager.cpp @@ -2,39 +2,31 @@ #include #include -#include "util.h" #include "configfsisomanager.h" +#include "util.h" #include -#include -#include #include +#include +#include -bool supported() -{ - return fs_mount_point((char *)"configfs") != nullptr; -} +bool supported() { return fs_mount_point((char *)"configfs") != nullptr; } -char* get_gadget_root() -{ - char *configFsRoot = fs_mount_point((char *)"configfs"); +char *get_gadget_root() { + char *configFsRoot = fs_mount_point((char *)"configfs"); char *usbGadgetRoot = strjin(configFsRoot, (char *)"/usb_gadget/"); - char *gadgetRoot = nullptr; + char *gadgetRoot = nullptr; struct dirent *entry = nullptr; - DIR *dp = nullptr; + DIR *dp = nullptr; dp = opendir(usbGadgetRoot); - if (dp != nullptr) - { - while ((entry = readdir(dp))) - { - if (entry->d_name[0] != '.') - { + if (dp != nullptr) { + while ((entry = readdir(dp))) { + if (entry->d_name[0] != '.') { char *gadget = strjin(usbGadgetRoot, entry->d_name); - if (sysfs_read(strjin(gadget, (char *)"/UDC")) != nullptr) - { + if (sysfs_read(strjin(gadget, (char *)"/UDC")) != nullptr) { gadgetRoot = gadget; break; } @@ -44,28 +36,23 @@ char* get_gadget_root() return gadgetRoot; } -char* get_config_root() -{ +char *get_config_root() { char *gadgetRoot = get_gadget_root(); - if (gadgetRoot == nullptr) - { + if (gadgetRoot == nullptr) { return nullptr; } char *usbConfigRoot = strjin(gadgetRoot, (char *)"/configs/"); - char *configRoot = nullptr; + char *configRoot = nullptr; struct dirent *entry = nullptr; - DIR *dp = nullptr; + DIR *dp = nullptr; dp = opendir(usbConfigRoot); - if (dp != nullptr) - { - while ((entry = readdir(dp))) - { - if (entry->d_name[0] != '.') - { + if (dp != nullptr) { + while ((entry = readdir(dp))) { + if (entry->d_name[0] != '.') { configRoot = strjin(usbConfigRoot, entry->d_name); break; } @@ -74,58 +61,51 @@ char* get_config_root() return configRoot; } -void mount_iso(char *iso_path, char *cdrom, char *ro) -{ +void mount_iso(char *iso_path, char *cdrom, char *ro) { char *gadgetRoot = get_gadget_root(); - if (gadgetRoot == nullptr) - { + if (gadgetRoot == nullptr) { printf("No active gadget found\n"); return; } - char *configRoot = get_config_root(); - char *udc = get_udc(); - char *functionRoot = strjin(gadgetRoot, (char *)"/functions"); + char *configRoot = get_config_root(); + char *udc = get_udc(); + char *functionRoot = strjin(gadgetRoot, (char *)"/functions"); char *massStorageRoot = strjin(functionRoot, (char *)"/mass_storage.0"); - char *lunRoot = strjin(massStorageRoot, (char *)"/lun.0"); + char *lunRoot = strjin(massStorageRoot, (char *)"/lun.0"); char *stallFile = strjin(massStorageRoot, (char *)"/stall"); - char *udcFile = strjin(gadgetRoot, (char *)"/UDC"); - char *lunFile = strjin(lunRoot, (char *)"/file"); - char *lunCdRom = strjin(lunRoot, (char *)"/cdrom"); - char *lunRo = strjin(lunRoot, (char *)"/ro"); + char *udcFile = strjin(gadgetRoot, (char *)"/UDC"); + char *lunFile = strjin(lunRoot, (char *)"/file"); + char *lunCdRom = strjin(lunRoot, (char *)"/cdrom"); + char *lunRo = strjin(lunRoot, (char *)"/ro"); set_udc((char *)"", gadgetRoot); - if (!isdir(massStorageRoot)) - { + if (!isdir(massStorageRoot)) { mkdir(massStorageRoot, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); } - if (!isdir(strjin(configRoot, (char *)"/mass_storage.0"))) - { + if (!isdir(strjin(configRoot, (char *)"/mass_storage.0"))) { symlink(massStorageRoot, strjin(configRoot, (char *)"/mass_storage.0")); } - sysfs_write(lunFile, iso_path); + sysfs_write(lunFile, iso_path); sysfs_write(lunCdRom, cdrom); - sysfs_write(lunRo, ro); + sysfs_write(lunRo, ro); set_udc(udc, gadgetRoot); } -void set_udc(char *udc, char *gadget) -{ +void set_udc(char *udc, char *gadget) { char *udcFile = strjin(gadget, (char *)"/UDC"); sysfs_write(udcFile, udc); } -char* get_udc() -{ +char *get_udc() { char *gadget_root = get_gadget_root(); - if (gadget_root == nullptr) - { + if (gadget_root == nullptr) { return nullptr; } char *udcFile = strjin(gadget_root, (char *)"/UDC"); diff --git a/src/include/androidusbisomanager.h b/src/include/androidusbisomanager.h new file mode 100644 index 0000000..a263a22 --- /dev/null +++ b/src/include/androidusbisomanager.h @@ -0,0 +1,20 @@ +#ifndef ANDROIDUSBISOMANAGER_H +#define ANDROIDUSBISOMANAGER_H + +#define ANDROID0_SYSFS_ENABLE "/sys/devices/virtual/android_usb/android0/enable" +#define ANDROID0_SYSFS_IMG_FILE \ + "/sys/devices/virtual/android_usb/android0/f_mass_storage/lun/file" +#define ANDROID0_SYSFS_FEATURES \ + "/sys/devices/virtual/android_usb/android0/functions" + +bool usb_supported(); + +void usb_mount_iso(char *iso_path); +void usb_umount_iso(); +void usb_reset_iso(); + +bool usb_enabled(); +void usb_set_enabled(bool enabled); +char *usb_get_udc(); + +#endif // ifndef ANDROIDUSBISOMANAGER_H diff --git a/src/include/configfsisomanager.h b/src/include/configfsisomanager.h index ddaece7..5c42d99 100644 --- a/src/include/configfsisomanager.h +++ b/src/include/configfsisomanager.h @@ -1,16 +1,13 @@ #ifndef CONFIGFSISOMANAGER_H #define CONFIGFSISOMANAGER_H -bool supported(); -char* get_gadget_root(); -char* get_config_root(); +bool supported(); +char *get_gadget_root(); +char *get_config_root(); -void mount_iso(char *iso_path, - char *cdrom, - char *ro); -void umount_iso(); -void set_udc(char *udc, - char *gadget); -char* get_udc(); +void mount_iso(char *iso_path, char *cdrom, char *ro); +void umount_iso(); +void set_udc(char *udc, char *gadget); +char *get_udc(); #endif // ifndef CONFIGFSISOMANAGER_H diff --git a/src/include/util.h b/src/include/util.h index ac51ba3..114f3f6 100644 --- a/src/include/util.h +++ b/src/include/util.h @@ -1,12 +1,11 @@ #ifndef UTIL_H #define UTIL_H -char* fs_mount_point(char *filesystem_type); -char* strjin(char *w1, - char *w2); -bool isdir(char *path); -char* sysfs_read(char *path); -void sysfs_write(char *path, - char *content); +char *fs_mount_point(char *filesystem_type); +char *strjin(char *w1, char *w2); +bool isdir(char *path); +bool isfile(char *path); +char *sysfs_read(char *path); +void sysfs_write(char *path, char *content); #endif // ifndef UTIL_H diff --git a/src/main.cpp b/src/main.cpp index 545dce5..3d1ce5e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,83 +1,80 @@ +#include "androidusbisomanager.h" #include "configfsisomanager.h" -#include #include #include +#include -int print_help() -{ - printf("Usage:\n"); - printf("isodrive [FILE]... [OPTION]...\n"); - printf("Mounts the given FILE as a bootable device using configfs.\n"); - printf( - "Run without any arguments to unmount any mounted files and display this help message.\n\n"); +int print_help() { + printf("Usage:\n"); + printf("isodrive [FILE]... [OPTION]...\n"); + printf("Mounts the given FILE as a bootable device using configfs.\n"); + printf("Run without any arguments to unmount any mounted files and display " + "this help message.\n\n"); - printf("Optional arguments:\n"); - printf("-rw\t Mounts the file in read write mode.\n"); - printf("-cdrom\t Mounts the file as a cdrom.\n\n"); - printf("UMOUNT:\n"); + printf("Optional arguments:\n"); + printf("-rw\t Mounts the file in read write mode.\n"); + printf("-cdrom\t Mounts the file as a cdrom.\n\n"); + printf("UMOUNT:\n"); - return 1; + return 1; } -int main(int argc, char *argv[]) -{ - char *iso_target = (char *)""; - char *cdrom = (char *)"0"; - char *ro = (char *)"1"; - - for (int i = 1; i < argc; i++) - { - if (strcmp(argv[i], "-rw") == 0) - { - ro = (char *)"0"; - } - else if (strcmp(argv[i], "-cdrom") == 0) - { - cdrom = (char *)"1"; - } - else if(strcmp(iso_target, "") == 0) - { - iso_target = argv[i]; - } - } - - if (argc == 1) - { - return print_help(); - } - - else if (!supported()) - { - printf("Device does not support configfs usb gadget\n"); - return 1; - } - - else if (getuid() != 0) - { - printf("Permission denied\n"); - return 1; - } - - else - { - printf("MOUNT:\n"); - } - - if (strcmp(ro, "1") != 0 && strcmp(ro, "0") != 0) - { +void configs(char *iso_target, char *cdrom, char *ro) { + if (strcmp(ro, "1") != 0 && strcmp(ro, "0") != 0) { printf("\nFaled to parse -rw argument. Defaulting to ro\n"); printf("Check --help for more usage info\n"); ro = (char *)"0"; } - if (strcmp(cdrom, "1") != 0 && strcmp(cdrom, "0") != 0) - { + if (strcmp(cdrom, "1") != 0 && strcmp(cdrom, "0") != 0) { printf("\nFailed to parse -cdrom argument. Defaulting to disabled\n"); printf("Check --help for more usage info\n"); cdrom = (char *)"0"; } mount_iso(iso_target, cdrom, ro); +} +void usb(char *iso_target) { + if (strcmp(iso_target, (char *)"")) + usb_reset_iso(); + else + usb_mount_iso(iso_target); +} + +int main(int argc, char *argv[]) { + char *iso_target = (char *)""; + char *cdrom = (char *)"0"; + char *ro = (char *)"1"; + + for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "-rw") == 0) { + ro = (char *)"0"; + } else if (strcmp(argv[i], "-cdrom") == 0) { + cdrom = (char *)"1"; + } else if (strcmp(iso_target, "") == 0) { + iso_target = argv[i]; + } + } + + if (argc == 1) { + return print_help(); + } + + else if (getuid() != 0) { + printf("Permission denied\n"); + return 1; + } + + else { + printf("MOUNT:\n"); + } + + if (usb_supported()) + usb(iso_target); + else if (supported()) + configs(iso_target, cdrom, ro); + else + printf("Device does not support isodrive\n"); return 0; } diff --git a/src/util.cpp b/src/util.cpp index 5cf5fb1..6064f67 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1,49 +1,43 @@ +#include +#include +#include #include +#include +#include #include +#include #include #include #include #include -#include -#include -#include -#include -#include -#include -char* fs_mount_point(char *filesystem_type) -{ +char *fs_mount_point(char *filesystem_type) { struct mntent *ent; FILE *mounts; char *mount_point = nullptr; mounts = setmntent("/proc/mounts", "r"); - while (nullptr != (ent = getmntent(mounts))) - { - if (strcmp(ent->mnt_fsname, filesystem_type) == 0) - { + while (nullptr != (ent = getmntent(mounts))) { + if (strcmp(ent->mnt_fsname, filesystem_type) == 0) { mount_point = ent->mnt_dir; break; } } // Alternate search location on Android - if (mount_point == nullptr) - { + if (mount_point == nullptr) { const char *alt_usb_gadget = "/config/usb_gadget"; - DIR *dir = opendir(alt_usb_gadget); + DIR *dir = opendir(alt_usb_gadget); - if (dir) - { + if (dir) { mount_point = (char *)"/config"; } } return mount_point; } -char* strjin(char *w1, char *w2) -{ +char *strjin(char *w1, char *w2) { char *s = new char[strlen(w1) + strlen(w2) + 1]; strcpy(s, w1); @@ -51,38 +45,42 @@ char* strjin(char *w1, char *w2) return s; } -bool isdir(char *path) -{ +bool isdir(char *path) { struct stat sb; if (stat(path, &sb) == 0) - return true; + return S_ISDIR(sb.st_mode); else return false; } -void sysfs_write(char *path, char *content) -{ +bool isfile(char *path) { + struct stat sb; + + if (stat(path, &sb) == 0) + return S_ISREG(sb.st_mode); + else + return false; +} + +void sysfs_write(char *path, char *content) { printf("Write: %s -> %s\n", content, path); std::ofstream sysfsFile(path); sysfsFile << content << std::endl; sysfsFile.close(); } -char* sysfs_read(char *path) -{ - std::string value; +char *sysfs_read(char *path) { + std::string value; std::ifstream sysfsFile(path); - if (!sysfsFile.is_open()) - { + if (!sysfsFile.is_open()) { return nullptr; } sysfsFile >> value; sysfsFile.close(); - if (value.empty()) - { + if (value.empty()) { return nullptr; } char *result = new char[value.length() + 1];