From 7692558674be24dfe51d7be84b4d01995c23e67b Mon Sep 17 00:00:00 2001 From: Marcin Bukat Date: Tue, 13 Mar 2018 21:24:56 +0100 Subject: Agptek Rocker: Implement USB mass storage driver Agptek uses composite android driver. Change-Id: Iece188ad640f3dfd24c171946c14da4c3516b6d5 --- apps/main.c | 4 + bootloader/rocker_linux.c | 14 +-- firmware/SOURCES | 1 + firmware/export/config/agptekrocker.h | 2 +- firmware/target/hosted/agptek/power-agptek.c | 22 +++-- firmware/target/hosted/agptek/power-agptek.h | 3 +- firmware/target/hosted/agptek/powermgmt-agptek.c | 4 +- firmware/target/hosted/agptek/usb-agptek.c | 118 +++++++++++++++++++++++ 8 files changed, 149 insertions(+), 19 deletions(-) create mode 100644 firmware/target/hosted/agptek/usb-agptek.c diff --git a/apps/main.c b/apps/main.c index 88a6630f94..7d9d859681 100644 --- a/apps/main.c +++ b/apps/main.c @@ -335,6 +335,10 @@ static void init(void) font_init(); #endif show_logo(); +#ifndef USB_NONE + usb_init(); + usb_start_monitoring(); +#endif button_init(); powermgmt_init(); backlight_init(); diff --git a/bootloader/rocker_linux.c b/bootloader/rocker_linux.c index dd912ee378..cb0e5b66e5 100644 --- a/bootloader/rocker_linux.c +++ b/bootloader/rocker_linux.c @@ -449,6 +449,7 @@ static void tools_screen(void) power_off(); } +#if 0 /* open log file */ static int open_log(void) { @@ -467,11 +468,13 @@ static int open_log(void) /* re-open the file, truncate in case the move was unsuccessful */ return open("/mnt/sd_0/rockbox.log", O_RDWR | O_CREAT | O_APPEND | O_TRUNC); } +#endif int main(int argc, char **argv) { (void) argc; (void) argv; +#if 0 /* redirect stdout and stderr to have error messages logged somewhere on the * user partition */ int fd = open_log(); @@ -485,6 +488,7 @@ int main(int argc, char **argv) printf("Rockbox boot loader\n"); printf("Version: %s\n", rbversion); printf("%s\n", MODEL_NAME); +#endif system_init(); core_allocator_init(); @@ -506,10 +510,12 @@ int main(int argc, char **argv) enum boot_mode mode = get_boot_mode(); if(mode == BOOT_USB || mode == BOOT_OF) { +#if 0 fflush(stdout); fflush(stderr); close(fileno(stdout)); close(fileno(stderr)); +#endif /* for now the only way we have to trigger USB mode it to run the OF */ /* boot OF */ execvp("/usr/bin/hiby_player", argv); @@ -522,13 +528,9 @@ int main(int argc, char **argv) } else if(mode == BOOT_ROCKBOX) { - /* Rockbox expects /.rockbox to contain themes, rocks, etc, but we - * cannot easily create this symlink because the root filesystem is - * mounted read-only. Although we could remount it read-write temporarily, - * this is neededlessly complicated and we defer this job to the dualboot - * install script */ fflush(stdout); - execl("/mnt/sd_0/.rockbox/rockbox.rocker", "rockbox.rocker", NULL); + system("/bin/cp /mnt/sd_0/.rockbox/rockbox.rocker /tmp"); + execl("/tmp/rockbox.rocker", "rockbox.rocker", NULL); printf("execvp failed: %s\n", strerror(errno)); /* fallback to OF in case of failure */ error_screen("Cannot boot Rockbox"); diff --git a/firmware/SOURCES b/firmware/SOURCES index b85111af44..fdfa811804 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -124,6 +124,7 @@ target/hosted/agptek/lcd-agptek.c target/hosted/agptek/power-agptek.c target/hosted/agptek/powermgmt-agptek.c target/hosted/agptek/system-agptek.c +target/hosted/agptek/usb-agptek.c #endif #if defined(SAMSUNG_YPR0) && !defined(SIMULATOR) diff --git a/firmware/export/config/agptekrocker.h b/firmware/export/config/agptekrocker.h index 517448b86d..6a0a6689b3 100644 --- a/firmware/export/config/agptekrocker.h +++ b/firmware/export/config/agptekrocker.h @@ -79,7 +79,7 @@ #ifndef SIMULATOR /* We have usb power and can detect usb but it is handled by Linux */ #define HAVE_USB_POWER -#define USB_NONE + #endif #define CONFIG_BATTERY_MEASURE VOLTAGE_MEASURE diff --git a/firmware/target/hosted/agptek/power-agptek.c b/firmware/target/hosted/agptek/power-agptek.c index 7403801681..023d3888b9 100644 --- a/firmware/target/hosted/agptek/power-agptek.c +++ b/firmware/target/hosted/agptek/power-agptek.c @@ -35,19 +35,23 @@ const char * const sysfs_bat_voltage = const char * const sysfs_bat_status = "/sys/class/power_supply/battery/status"; -unsigned int agptek_power_get_status(void) +const char * const sysfs_pow_supply = + "/sys/class/power_supply/usb/present"; + +unsigned int agptek_power_input_status(void) +{ + int present = 0; + sysfs_get_int(sysfs_pow_supply, &present); + + return present ? POWER_INPUT_USB_CHARGER : POWER_INPUT_NONE; +} + +bool agptek_power_charging_status(void) { char buf[12] = {0}; sysfs_get_string(sysfs_bat_status, buf, sizeof(buf)); - if (strncmp(buf, "Charging", 8) == 0) - { - return POWER_INPUT_USB_CHARGER; - } - else - { - return POWER_INPUT_NONE; - } + return (strncmp(buf, "Charging", 8) == 0); } unsigned int agptek_power_get_battery_voltage(void) diff --git a/firmware/target/hosted/agptek/power-agptek.h b/firmware/target/hosted/agptek/power-agptek.h index 16f32b76ad..1ae2ff43d6 100644 --- a/firmware/target/hosted/agptek/power-agptek.h +++ b/firmware/target/hosted/agptek/power-agptek.h @@ -23,7 +23,8 @@ #include #include "config.h" -unsigned int agptek_power_get_status(void); +unsigned int agptek_power_input_status(void); +bool agptek_power_charging_status(void); unsigned int agptek_power_get_battery_voltage(void); #endif /* _POWER_AGPTEK_H_ */ diff --git a/firmware/target/hosted/agptek/powermgmt-agptek.c b/firmware/target/hosted/agptek/powermgmt-agptek.c index 3371d1e793..6bfccb4115 100644 --- a/firmware/target/hosted/agptek/powermgmt-agptek.c +++ b/firmware/target/hosted/agptek/powermgmt-agptek.c @@ -49,7 +49,7 @@ const unsigned short const percent_to_volt_charge[11] = unsigned int power_input_status(void) { /* POWER_INPUT_USB_CHARGER, POWER_INPUT_NONE */ - return agptek_power_get_status(); + return agptek_power_input_status(); } int _battery_voltage(void) @@ -59,5 +59,5 @@ int _battery_voltage(void) bool charging_state(void) { - return agptek_power_get_status() == POWER_INPUT_USB_CHARGER; + return agptek_power_charging_status(); } diff --git a/firmware/target/hosted/agptek/usb-agptek.c b/firmware/target/hosted/agptek/usb-agptek.c new file mode 100644 index 0000000000..6c805edb5a --- /dev/null +++ b/firmware/target/hosted/agptek/usb-agptek.c @@ -0,0 +1,118 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2018 by Marcin Bukat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include +#include +#include +#include "config.h" +#include "disk.h" +#include "usb.h" +#include "sysfs.h" +#include "power.h" +#include "power-agptek.h" + +static bool adb_mode = false; + +/* TODO: implement usb detection properly */ +int usb_detect(void) +{ + return power_input_status() == POWER_INPUT_USB_CHARGER ? USB_INSERTED : USB_EXTRACTED; +} + +void usb_enable(bool on) +{ + /* Ignore usb enable/disable when ADB is enabled so we can fireup adb shell + * without entering ums mode + */ + if (!adb_mode) + { + sysfs_set_int("/sys/class/android_usb/android0/enable", on ? 1 : 0); + } +} + +/* This is called by usb thread after usb extract in order to return + * regular FS access + * + * returns the # of successful mounts +*/ +int disk_mount_all(void) +{ + const char *dev[] = {"/dev/mmcblk0p1", "/dev/mmcblk0"}; + const char *fs[] = {"vfat", "exfat"}; + + sysfs_set_string("/sys/class/android_usb/android0/f_mass_storage/lun/file", ""); + + for (int i=0; i<2; i++) + { + for (int j=0; j<2; j++) + { + if (mount(dev[i], "/mnt/sd_0", fs[j], 0, NULL) == 0) + { + return 1; + } + } + } + + return 0; +} + +/* This is called by usb thread after all threads ACKs usb inserted message + * + * returns the # of successful unmounts + */ +int disk_unmount_all(void) +{ + if (umount("/mnt/sd_0") == 0) + { + sysfs_set_string("/sys/class/android_usb/android0/f_mass_storage/lun/file", "/dev/mmcblk0"); + return 1; + } + + return 0; +} + +void usb_init_device(void) +{ + char functions[32] = {0}; + + /* Check if ADB was activated in bootloader */ + sysfs_get_string("/sys/class/android_usb/android0/functions", functions, sizeof(functions)); + adb_mode = (strstr(functions, "adb") == NULL) ? false : true; + + usb_enable(false); + + if (adb_mode) + { + sysfs_set_string("/sys/class/android_usb/android0/functions", "mass_storage,adb"); + sysfs_set_string("/sys/class/android_usb/android0/idVendor", "18D1"); + sysfs_set_string("/sys/class/android_usb/android0/idProduct", "D002"); + } + else + { + sysfs_set_string("/sys/class/android_usb/android0/functions", "mass_storage"); + sysfs_set_string("/sys/class/android_usb/android0/idVendor", "C502"); + sysfs_set_string("/sys/class/android_usb/android0/idProduct", "0029"); + } + + sysfs_set_string("/sys/class/android_usb/android0/iManufacturer", "Rockbox.org"); + sysfs_set_string("/sys/class/android_usb/android0/iProduct", "Rockbox media player"); + sysfs_set_string("/sys/class/android_usb/android0/iSerial", "0123456789ABCDEF"); + sysfs_set_string("/sys/class/android_usb/android0/f_mass_storage/inquiry_string", "Agptek Rocker 0100"); +} -- cgit v1.2.3