Skip to content

Commit

Permalink
[modesetting] Track expected sysfs control file content. JB#38433
Browse files Browse the repository at this point in the history
When porting to new devices it is easy to miss usb related control actions
taken for example by android init scripts and the resulting conflicts with
usb-moded logic might be difficult to spot and/or debug.

Keep track of sysfs values written by usb-moded and add functionality for
checking if something else has overruled the settings made by usb-moded.

Signed-off-by: Simo Piiroinen <simo.piiroinen@jollamobile.com>
  • Loading branch information
spiiroin committed Apr 26, 2017
1 parent 7107bf5 commit be91259
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 13 deletions.
102 changes: 89 additions & 13 deletions src/usb_moded-modesetting.c
Expand Up @@ -47,10 +47,68 @@
#include "usb_moded-network.h"
#include "usb_moded-android.h"


static char *read_from_file(const char *path, size_t maxsize);

static GHashTable *tracked_values = 0;

static void usb_moded_mode_track_value(const char *path, const char *text)
{
if( !tracked_values || !path )
goto EXIT;

if( text )
g_hash_table_replace(tracked_values, g_strdup(path), g_strdup(text));
else
g_hash_table_remove(tracked_values, path);

EXIT:
return;
}

void usb_moded_mode_verify_values(void)
{
GHashTableIter iter;
gpointer key, value;

if( !tracked_values )
goto EXIT;

g_hash_table_iter_init(&iter, tracked_values);
while( g_hash_table_iter_next(&iter, &key, &value) )
{
const char *path = key;
const char *text = value;

char *curr = read_from_file(path, 0x1000);

if( g_strcmp0(text, curr) ) {
/* There might be case mismatch between hexadecimal
* 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,
text ?: "???",
curr ?: "???");
}
else {
log_warning("unexpected change '%s' : '%s' -> '%s'", path,
text ?: "???",
curr ?: "???");
}
usb_moded_mode_track_value(path, curr);
}

free(curr);
}

EXIT:
return;
}

static void report_mass_storage_blocker(const char *mountpoint, int try);
static guint delayed_network = 0;

#if LOG_ENABLE_DEBUG
static char *strip(char *str)
{
unsigned char *src = (unsigned char *)str;
Expand Down Expand Up @@ -103,21 +161,21 @@ static char *read_from_file(const char *path, size_t maxsize)
if(fd != -1) close(fd);
return text;
}
#endif /* LOG_ENABLE_DEBUG */

int write_to_file_real(const char *file, int line, const char *func,
const char *path, const char *text)
{
int err = -1;
int fd = -1;
size_t todo = 0;
char *prev = 0;

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

/* There is usb-moded code and configuration files that use
/* 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
Expand All @@ -127,16 +185,14 @@ int write_to_file_real(const char *file, int line, const char *func,
text = "";
}

#if LOG_ENABLE_DEBUG
if(log_level >= LOG_DEBUG)
{
char *prev = read_from_file(path, 0x1000);
log_debug("%s:%d: %s(): WRITE '%s' : '%s' --> '%s'",
file, line, func,
path, prev ?: "???", text);
free(prev);
}
#endif
/* 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);

log_debug("%s:%d: %s(): WRITE '%s' : '%s' --> '%s'",
file, line, func,
path, prev ?: "???", text);

todo = strlen(text);

Expand Down Expand Up @@ -165,6 +221,8 @@ int write_to_file_real(const char *file, int line, const char *func,

if( fd != -1 ) TEMP_FAILURE_RETRY(close(fd));

free(prev);

return err;
}

Expand Down Expand Up @@ -603,3 +661,21 @@ int usb_moded_mode_cleanup(const char *module)
return(0);
}

/** Allocate modesetting related dynamic resouces
*/
void usb_moded_mode_init(void)
{
if( !tracked_values ) {
tracked_values = g_hash_table_new_full(g_str_hash, g_str_equal,
g_free, g_free);
}
}

/** Release modesetting related dynamic resouces
*/
void usb_moded_mode_quit(void)
{
if( tracked_values ) {
g_hash_table_unref(tracked_values), tracked_values = 0;
}
}
3 changes: 3 additions & 0 deletions src/usb_moded-modesetting.h
Expand Up @@ -32,3 +32,6 @@ int set_dynamic_mode(void);
void unset_dynamic_mode(void);
/* clean up for the mode changes on disconnect */
int usb_moded_mode_cleanup(const char *module);
void usb_moded_mode_verify_values(void);
void usb_moded_mode_init(void);
void usb_moded_mode_quit(void);
2 changes: 2 additions & 0 deletions src/usb_moded.c
Expand Up @@ -1337,6 +1337,7 @@ int main(int argc, char* argv[])
#endif

/* Set daemon config/state data to sane state */
usb_moded_mode_init();
usb_moded_init();

/* Allos making systemd control ipc */
Expand Down Expand Up @@ -1449,6 +1450,7 @@ int main(int argc, char* argv[])

/* Release dynamically allocated config/state data */
usb_moded_cleanup();
usb_moded_mode_quit();

/* Detach from SessionBus connection used for APP_SYNC_DBUS.
*
Expand Down

0 comments on commit be91259

Please sign in to comment.