From 7896a72829219ec97ddaea243c560c163df5ed65 Mon Sep 17 00:00:00 2001 From: Simo Piiroinen Date: Mon, 20 Aug 2018 16:12:49 +0300 Subject: [PATCH] [android] Use wrapper function for all sysfs writes. JB#41748 Writing empty string gets ignored. This causes problems for example when switching from mass-storage mode to charging only as the lua/file attribute does not get cleared. Use a wrapper function to append a linefeed to strings written to sysfs. This avoids zero length writes and makes behavior similar to how redirected echo from command line works. Also tweak unexpected-sysfs-content-change tracker so that it ignores changes in whitespace. Signed-off-by: Simo Piiroinen --- src/usb_moded-android.c | 67 ++++++++++++++++++++++++++++++++----- src/usb_moded-android.h | 1 + src/usb_moded-modesetting.c | 18 ++++++---- 3 files changed, 70 insertions(+), 16 deletions(-) diff --git a/src/usb_moded-android.c b/src/usb_moded-android.c index a2e8fac..551b8a9 100644 --- a/src/usb_moded-android.c +++ b/src/usb_moded-android.c @@ -50,6 +50,7 @@ bool android_set_charging_mode(void); bool android_set_function (const char *function); bool android_set_productid (const char *id); bool android_set_vendorid (const char *id); +bool android_set_attr (const char *function, const char *attr, const char *value); /* ========================================================================= * * Data @@ -61,6 +62,29 @@ static int android_probed = -1; * Functions * ========================================================================= */ +static bool +android_write_file(const char *path, const char *text) +{ + bool ack = false; + + if( !path || !text ) + goto EXIT; + + log_debug("WRITE %s '%s'", path, text); + + char buff[64]; + snprintf(buff, sizeof buff, "%s\n", text); + + if( write_to_file(path, buff) == -1 ) + goto EXIT; + + ack = true; + +EXIT: + + return ack; +} + bool android_in_use(void) { @@ -146,14 +170,14 @@ android_init_values(void) /* Configure */ if( (text = android_get_serial()) ) { - write_to_file(ANDROID0_SERIAL, text); + android_write_file(ANDROID0_SERIAL, text); g_free(text); } text = config_get_android_manufacturer(); if(text) { - write_to_file(ANDROID0_MANUFACTURER, text); + android_write_file(ANDROID0_MANUFACTURER, text); g_free(text); } text = config_get_android_vendor_id(); @@ -165,7 +189,7 @@ android_init_values(void) text = config_get_android_product(); if(text) { - write_to_file(ANDROID0_PRODUCT, text); + android_write_file(ANDROID0_PRODUCT, text); g_free(text); } text = config_get_android_product_id(); @@ -177,11 +201,16 @@ android_init_values(void) text = mac_read_mac(); if(text) { - write_to_file("/sys/class/android_usb/f_rndis/ethaddr", text); + android_set_attr("f_rndis", "ethaddr", text); g_free(text); } /* For rndis to be discovered correctly in M$ Windows (vista and later) */ - write_to_file("/sys/class/android_usb/f_rndis/wceis", "1"); + android_set_attr("f_rndis", "wceis", "1"); + + /* Make sure remnants off mass-storage mode do not cause + * issues for charging_fallback & co */ + android_set_attr("f_mass_storage", "lun/nofua", "0"); + android_set_attr("f_mass_storage", "lun/file", ""); EXIT: return android_in_use(); @@ -193,7 +222,7 @@ android_set_enabled(bool enable) bool ack = false; if( android_in_use() ) { const char *val = enable ? "1" : "0"; - ack = write_to_file(ANDROID0_ENABLE, val) != -1; + ack = android_write_file(ANDROID0_ENABLE, val) != -1; } log_debug("ANDROID %s(%d) -> %d", __func__, enable, ack); return ack; @@ -246,7 +275,7 @@ android_set_function(const char *function) if( !android_set_enabled(false) ) goto EXIT; - if( write_to_file(ANDROID0_FUNCTIONS, function) == -1 ) + if( android_write_file(ANDROID0_FUNCTIONS, function) == -1 ) goto EXIT; /* Leave disabled, so that caller can adjust attributes @@ -276,7 +305,7 @@ android_set_productid(const char *id) snprintf(str, sizeof str, "%04x", num); id = str; } - ack = write_to_file(ANDROID0_ID_PRODUCT, id) != -1; + ack = android_write_file(ANDROID0_ID_PRODUCT, id) != -1; } log_debug("ANDROID %s(%s) -> %d", __func__, id, ack); return ack; @@ -298,8 +327,28 @@ android_set_vendorid(const char *id) snprintf(str, sizeof str, "%04x", num); id = str; } - ack = write_to_file(ANDROID0_ID_VENDOR, id) != -1; + ack = android_write_file(ANDROID0_ID_VENDOR, id) != -1; } log_debug("ANDROID %s(%s) -> %d", __func__, id, ack); return ack; } + +/** Set function attribute + * + * @return true if successful, false on failure + */ +bool +android_set_attr(const char *function, const char *attr, const char *value) +{ + bool ack = false; + + if( function && attr && value && android_in_use() ) { + char path[256]; + snprintf(path, sizeof path, "%s/%s/%s", + ANDROID0_DIRECTORY, function, attr); + ack = android_write_file(path, value); + } + log_debug("ANDROID %s(%s, %s, %s) -> %d", __func__, + function, attr, value, ack); + return ack; +} diff --git a/src/usb_moded-android.h b/src/usb_moded-android.h index a5bf959..b9a92b2 100644 --- a/src/usb_moded-android.h +++ b/src/usb_moded-android.h @@ -53,5 +53,6 @@ bool android_set_charging_mode(void); bool android_set_function (const char *function); bool android_set_productid (const char *id); bool android_set_vendorid (const char *id); +bool android_set_attr (const char *function, const char *attr, const char *value); #endif /* USB_MODED_ANDROID_H_ */ diff --git a/src/usb_moded-modesetting.c b/src/usb_moded-modesetting.c index d1ce1de..913ca0e 100644 --- a/src/usb_moded-modesetting.c +++ b/src/usb_moded-modesetting.c @@ -201,11 +201,12 @@ int modesetting_write_to_file_real(const char *file, int line, const char *func, size_t todo = 0; char *prev = 0; bool clear = false; + gchar *repr = 0; /* if either path or the text to be written are not there * we return an error */ if(!text || !path) - return err; + goto cleanup; /* When attempting to clear ffs function list, writing an * empty string is ignored and accomplishes nothing - while @@ -225,14 +226,17 @@ int modesetting_write_to_file_real(const char *file, int line, const char *func, } } + repr = g_strdup(text); + modesetting_strip(repr); + /* If the file can be read, it also means we can later check that * the file retains the value we are about to write here. */ if( (prev = modesetting_read_from_file(path, 0x1000)) ) - modesetting_track_value(path, clear ? "" : text); + modesetting_track_value(path, clear ? "" : repr); log_debug("%s:%d: %s(): WRITE '%s' : '%s' --> '%s'", file, line, func, - path, prev ?: "???", text); + path, prev ?: "???", repr); todo = strlen(text); @@ -265,6 +269,7 @@ int modesetting_write_to_file_real(const char *file, int line, const char *func, if( fd != -1 ) TEMP_FAILURE_RETRY(close(fd)); free(prev); + free(repr); return err; } @@ -470,9 +475,8 @@ static bool modesetting_enter_mass_storage_mode(struct mode_list_elem *data) const gchar *mountdev = info[0].si_mountdevice; android_set_enabled(false); android_set_function("mass_storage"); - write_to_file("/sys/class/android_usb/f_mass_storage/lun/nofua", - nofua ? "1" : "0"); - write_to_file("/sys/class/android_usb/f_mass_storage/lun/file", mountdev); + android_set_attr("f_mass_storage", "lun/nofua", nofua ? "1" : "0"); + android_set_attr("f_mass_storage", "lun/file", mountdev); android_set_enabled(true); } else if( configfs_in_use() ) { @@ -553,7 +557,7 @@ static int modesetting_leave_mass_storage_mode(struct mode_list_elem *data) if( android_in_use() ) { log_debug("Disable android mass storage\n"); android_set_enabled(false); - write_to_file("/sys/class/android_usb/f_mass_storage/lun/file", ""); + android_set_attr("f_mass_storage", "lun/file", ""); } else if( configfs_in_use() ) { // TODO