Skip to content

Commit

Permalink
[modesetting] Write dummy value to clear ffs function list. Fixes JB#…
Browse files Browse the repository at this point in the history
…39402

It seems that kernels in many if not all devices ignore writing of empty
string to ffs function control file - the function list is left as it were
and this can cause subtle issues on the next cable connect. On the other
hand writing a non-existing "function" will clear the function list, but
causes write error to be reported.

Treat attempts to clear function list as a special case so that non-empty
string gets written and the resulting write error is ignored under normal
logging verbosity.

Signed-off-by: Simo Piiroinen <simo.piiroinen@jollamobile.com>
  • Loading branch information
spiiroin committed Aug 17, 2017
1 parent 3350e0b commit e7536eb
Showing 1 changed file with 23 additions and 10 deletions.
33 changes: 23 additions & 10 deletions src/usb_moded-modesetting.c
Expand Up @@ -30,6 +30,7 @@
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <sys/stat.h>
#include <limits.h>

Expand Down Expand Up @@ -87,7 +88,7 @@ void usb_moded_mode_verify_values(void)
* values used in configuration files vs what we get
* back when reading from kernel interfaces. */
if( text && curr && !g_ascii_strcasecmp(text, curr) ) {
log_debug("unexpected change '%s' : '%s' -> '%s'", path,
log_debug("unexpected change '%s' : '%s' -> '%s' (case diff only)", path,
text ?: "???",
curr ?: "???");
}
Expand Down Expand Up @@ -169,26 +170,35 @@ int write_to_file_real(const char *file, int line, const char *func,
int fd = -1;
size_t todo = 0;
char *prev = 0;
bool clear = false;

/* if either path or the text to be written are not there
we return an error */
if(!text || !path)
return err;

/* There are usb-moded configuration files and code that use
* "none" as a place-holder for no-function. Attempting to
* write that into sysfs leads to journal spamming due to
* EINVAL error return. Substituting "none" with an empty
* string avoids that. */
if( !strcmp(path, "/sys/class/android_usb/android0/functions") &&
!strcmp(text, "none") ) {
text = "";
/* When attempting to clear ffs function list, writing an
* empty string is ignored and accomplishes nothing - while
* writing non-existing function clears the list but returns
* write error.
*
* Treat "none" (which is used as place-holder value in both
* configuration files and usb-moded sources) and "" similarly:
* - Write invalid function name to sysfs
* - Ignore resulting write error under default logging level
* - Assume reading from sysfs will result in empty string
*/
if( !strcmp(path, "/sys/class/android_usb/android0/functions") ) {
if( !strcmp(text, "") || !strcmp(text, "none") ) {
text = "none";
clear = true;
}
}

/* 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 = read_from_file(path, 0x1000)) )
usb_moded_mode_track_value(path, text);
usb_moded_mode_track_value(path, clear ? "" : text);

log_debug("%s:%d: %s(): WRITE '%s' : '%s' --> '%s'",
file, line, func,
Expand All @@ -208,6 +218,9 @@ int write_to_file_real(const char *file, int line, const char *func,
ssize_t n = TEMP_FAILURE_RETRY(write(fd, text, todo));
if( n < 0 )
{
if( clear && errno == EINVAL )
log_debug("write(%s): %m (expected failure)", path);
else
log_warning("write(%s): %m", path);
goto cleanup;
}
Expand Down

0 comments on commit e7536eb

Please sign in to comment.