Add usb gadget support

This commit is contained in:
Marcel Alexandru Nitan
2023-07-29 13:04:11 +03:00
parent 2bd53ff6c7
commit 88187197c4
8 changed files with 206 additions and 166 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
CC = g++ CC = g++
CFLAGS = -I./src/include 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) OBJS = $(SRCS:.cpp=.o)
TARGET = isodrive TARGET = isodrive
INSTALL_DIR = /usr/local/bin INSTALL_DIR = /usr/local/bin
+49
View File
@@ -0,0 +1,49 @@
#include <sys/stat.h>
#include <sys/types.h>
#include "androidusbisomanager.h"
#include "util.h"
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
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");
}
+36 -56
View File
@@ -2,39 +2,31 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include "util.h"
#include "configfsisomanager.h" #include "configfsisomanager.h"
#include "util.h"
#include <dirent.h> #include <dirent.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <unistd.h>
bool supported() bool supported() { return fs_mount_point((char *)"configfs") != nullptr; }
{
return fs_mount_point((char *)"configfs") != nullptr;
}
char* get_gadget_root() char *get_gadget_root() {
{ char *configFsRoot = fs_mount_point((char *)"configfs");
char *configFsRoot = fs_mount_point((char *)"configfs");
char *usbGadgetRoot = strjin(configFsRoot, (char *)"/usb_gadget/"); char *usbGadgetRoot = strjin(configFsRoot, (char *)"/usb_gadget/");
char *gadgetRoot = nullptr; char *gadgetRoot = nullptr;
struct dirent *entry = nullptr; struct dirent *entry = nullptr;
DIR *dp = nullptr; DIR *dp = nullptr;
dp = opendir(usbGadgetRoot); dp = opendir(usbGadgetRoot);
if (dp != nullptr) if (dp != nullptr) {
{ while ((entry = readdir(dp))) {
while ((entry = readdir(dp))) if (entry->d_name[0] != '.') {
{
if (entry->d_name[0] != '.')
{
char *gadget = strjin(usbGadgetRoot, entry->d_name); 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; gadgetRoot = gadget;
break; break;
} }
@@ -44,28 +36,23 @@ char* get_gadget_root()
return gadgetRoot; return gadgetRoot;
} }
char* get_config_root() char *get_config_root() {
{
char *gadgetRoot = get_gadget_root(); char *gadgetRoot = get_gadget_root();
if (gadgetRoot == nullptr) if (gadgetRoot == nullptr) {
{
return nullptr; return nullptr;
} }
char *usbConfigRoot = strjin(gadgetRoot, (char *)"/configs/"); char *usbConfigRoot = strjin(gadgetRoot, (char *)"/configs/");
char *configRoot = nullptr; char *configRoot = nullptr;
struct dirent *entry = nullptr; struct dirent *entry = nullptr;
DIR *dp = nullptr; DIR *dp = nullptr;
dp = opendir(usbConfigRoot); dp = opendir(usbConfigRoot);
if (dp != nullptr) if (dp != nullptr) {
{ while ((entry = readdir(dp))) {
while ((entry = readdir(dp))) if (entry->d_name[0] != '.') {
{
if (entry->d_name[0] != '.')
{
configRoot = strjin(usbConfigRoot, entry->d_name); configRoot = strjin(usbConfigRoot, entry->d_name);
break; break;
} }
@@ -74,58 +61,51 @@ char* get_config_root()
return configRoot; 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(); char *gadgetRoot = get_gadget_root();
if (gadgetRoot == nullptr) if (gadgetRoot == nullptr) {
{
printf("No active gadget found\n"); printf("No active gadget found\n");
return; return;
} }
char *configRoot = get_config_root(); char *configRoot = get_config_root();
char *udc = get_udc(); char *udc = get_udc();
char *functionRoot = strjin(gadgetRoot, (char *)"/functions"); char *functionRoot = strjin(gadgetRoot, (char *)"/functions");
char *massStorageRoot = strjin(functionRoot, (char *)"/mass_storage.0"); 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 *stallFile = strjin(massStorageRoot, (char *)"/stall");
char *udcFile = strjin(gadgetRoot, (char *)"/UDC"); char *udcFile = strjin(gadgetRoot, (char *)"/UDC");
char *lunFile = strjin(lunRoot, (char *)"/file"); char *lunFile = strjin(lunRoot, (char *)"/file");
char *lunCdRom = strjin(lunRoot, (char *)"/cdrom"); char *lunCdRom = strjin(lunRoot, (char *)"/cdrom");
char *lunRo = strjin(lunRoot, (char *)"/ro"); char *lunRo = strjin(lunRoot, (char *)"/ro");
set_udc((char *)"", gadgetRoot); set_udc((char *)"", gadgetRoot);
if (!isdir(massStorageRoot)) if (!isdir(massStorageRoot)) {
{
mkdir(massStorageRoot, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); 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")); symlink(massStorageRoot, strjin(configRoot, (char *)"/mass_storage.0"));
} }
sysfs_write(lunFile, iso_path); sysfs_write(lunFile, iso_path);
sysfs_write(lunCdRom, cdrom); sysfs_write(lunCdRom, cdrom);
sysfs_write(lunRo, ro); sysfs_write(lunRo, ro);
set_udc(udc, gadgetRoot); set_udc(udc, gadgetRoot);
} }
void set_udc(char *udc, char *gadget) void set_udc(char *udc, char *gadget) {
{
char *udcFile = strjin(gadget, (char *)"/UDC"); char *udcFile = strjin(gadget, (char *)"/UDC");
sysfs_write(udcFile, udc); sysfs_write(udcFile, udc);
} }
char* get_udc() char *get_udc() {
{
char *gadget_root = get_gadget_root(); char *gadget_root = get_gadget_root();
if (gadget_root == nullptr) if (gadget_root == nullptr) {
{
return nullptr; return nullptr;
} }
char *udcFile = strjin(gadget_root, (char *)"/UDC"); char *udcFile = strjin(gadget_root, (char *)"/UDC");
+20
View File
@@ -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
+7 -10
View File
@@ -1,16 +1,13 @@
#ifndef CONFIGFSISOMANAGER_H #ifndef CONFIGFSISOMANAGER_H
#define CONFIGFSISOMANAGER_H #define CONFIGFSISOMANAGER_H
bool supported(); bool supported();
char* get_gadget_root(); char *get_gadget_root();
char* get_config_root(); char *get_config_root();
void mount_iso(char *iso_path, void mount_iso(char *iso_path, char *cdrom, char *ro);
char *cdrom, void umount_iso();
char *ro); void set_udc(char *udc, char *gadget);
void umount_iso(); char *get_udc();
void set_udc(char *udc,
char *gadget);
char* get_udc();
#endif // ifndef CONFIGFSISOMANAGER_H #endif // ifndef CONFIGFSISOMANAGER_H
+6 -7
View File
@@ -1,12 +1,11 @@
#ifndef UTIL_H #ifndef UTIL_H
#define UTIL_H #define UTIL_H
char* fs_mount_point(char *filesystem_type); char *fs_mount_point(char *filesystem_type);
char* strjin(char *w1, char *strjin(char *w1, char *w2);
char *w2); bool isdir(char *path);
bool isdir(char *path); bool isfile(char *path);
char* sysfs_read(char *path); char *sysfs_read(char *path);
void sysfs_write(char *path, void sysfs_write(char *path, char *content);
char *content);
#endif // ifndef UTIL_H #endif // ifndef UTIL_H
+58 -61
View File
@@ -1,83 +1,80 @@
#include "androidusbisomanager.h"
#include "configfsisomanager.h" #include "configfsisomanager.h"
#include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h>
int print_help() int print_help() {
{ printf("Usage:\n");
printf("Usage:\n"); printf("isodrive [FILE]... [OPTION]...\n");
printf("isodrive [FILE]... [OPTION]...\n"); printf("Mounts the given FILE as a bootable device using configfs.\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 "
printf( "this help message.\n\n");
"Run without any arguments to unmount any mounted files and display this help message.\n\n");
printf("Optional arguments:\n"); printf("Optional arguments:\n");
printf("-rw\t Mounts the file in read write mode.\n"); printf("-rw\t Mounts the file in read write mode.\n");
printf("-cdrom\t Mounts the file as a cdrom.\n\n"); printf("-cdrom\t Mounts the file as a cdrom.\n\n");
printf("UMOUNT:\n"); printf("UMOUNT:\n");
return 1; return 1;
} }
int main(int argc, char *argv[]) void configs(char *iso_target, char *cdrom, char *ro) {
{ if (strcmp(ro, "1") != 0 && strcmp(ro, "0") != 0) {
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)
{
printf("\nFaled to parse -rw argument. Defaulting to ro\n"); printf("\nFaled to parse -rw argument. Defaulting to ro\n");
printf("Check --help for more usage info\n"); printf("Check --help for more usage info\n");
ro = (char *)"0"; 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("\nFailed to parse -cdrom argument. Defaulting to disabled\n");
printf("Check --help for more usage info\n"); printf("Check --help for more usage info\n");
cdrom = (char *)"0"; cdrom = (char *)"0";
} }
mount_iso(iso_target, cdrom, ro); 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; return 0;
} }
+29 -31
View File
@@ -1,49 +1,43 @@
#include <array>
#include <cstdio>
#include <dirent.h>
#include <fcntl.h> #include <fcntl.h>
#include <fstream>
#include <memory>
#include <mntent.h> #include <mntent.h>
#include <sstream>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <fstream>
#include <sstream>
#include <array>
#include <memory>
#include <cstdio>
#include <dirent.h>
char* fs_mount_point(char *filesystem_type) char *fs_mount_point(char *filesystem_type) {
{
struct mntent *ent; struct mntent *ent;
FILE *mounts; FILE *mounts;
char *mount_point = nullptr; char *mount_point = nullptr;
mounts = setmntent("/proc/mounts", "r"); mounts = setmntent("/proc/mounts", "r");
while (nullptr != (ent = getmntent(mounts))) while (nullptr != (ent = getmntent(mounts))) {
{ if (strcmp(ent->mnt_fsname, filesystem_type) == 0) {
if (strcmp(ent->mnt_fsname, filesystem_type) == 0)
{
mount_point = ent->mnt_dir; mount_point = ent->mnt_dir;
break; break;
} }
} }
// Alternate search location on Android // Alternate search location on Android
if (mount_point == nullptr) if (mount_point == nullptr) {
{
const char *alt_usb_gadget = "/config/usb_gadget"; 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"; mount_point = (char *)"/config";
} }
} }
return mount_point; return mount_point;
} }
char* strjin(char *w1, char *w2) char *strjin(char *w1, char *w2) {
{
char *s = new char[strlen(w1) + strlen(w2) + 1]; char *s = new char[strlen(w1) + strlen(w2) + 1];
strcpy(s, w1); strcpy(s, w1);
@@ -51,38 +45,42 @@ char* strjin(char *w1, char *w2)
return s; return s;
} }
bool isdir(char *path) bool isdir(char *path) {
{
struct stat sb; struct stat sb;
if (stat(path, &sb) == 0) if (stat(path, &sb) == 0)
return true; return S_ISDIR(sb.st_mode);
else else
return false; 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); printf("Write: %s -> %s\n", content, path);
std::ofstream sysfsFile(path); std::ofstream sysfsFile(path);
sysfsFile << content << std::endl; sysfsFile << content << std::endl;
sysfsFile.close(); sysfsFile.close();
} }
char* sysfs_read(char *path) char *sysfs_read(char *path) {
{ std::string value;
std::string value;
std::ifstream sysfsFile(path); std::ifstream sysfsFile(path);
if (!sysfsFile.is_open()) if (!sysfsFile.is_open()) {
{
return nullptr; return nullptr;
} }
sysfsFile >> value; sysfsFile >> value;
sysfsFile.close(); sysfsFile.close();
if (value.empty()) if (value.empty()) {
{
return nullptr; return nullptr;
} }
char *result = new char[value.length() + 1]; char *result = new char[value.length() + 1];