Skip to content

Commit

Permalink
Merge branch 'jb39402_clear_ffs_functions' into 'master'
Browse files Browse the repository at this point in the history
Write dummy value to clear ffs function list

See merge request !29
  • Loading branch information
spiiroin committed Aug 18, 2017
2 parents 31c104d + e7536eb commit 69a44b2
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 59 deletions.
5 changes: 4 additions & 1 deletion src/usb_moded-dbus.c
Expand Up @@ -54,7 +54,8 @@ extern gboolean rescue_mode;
*/
static void usb_moded_send_config_signal(const char *section, const char *key, const char *value)
{
log_debug(USB_MODE_CONFIG_SIGNAL_NAME ": %s %s %s\n", section, key, value);
log_debug("broadcast signal %s(%s, %s, %s)\n", USB_MODE_CONFIG_SIGNAL_NAME, section, key, value);

if( !have_service_name )
{
log_err("config notification without service: [%s] %s=%s",
Expand Down Expand Up @@ -603,6 +604,8 @@ static int usb_moded_dbus_signal(const char *signal_type, const char *content)
int result = 1;
DBusMessage* msg = 0;

log_debug("broadcast signal %s(%s)\n", signal_type, content);

if( !have_service_name )
{
log_err("sending signal without service: %s(%s)",
Expand Down
118 changes: 96 additions & 22 deletions src/usb_moded-log.c
Expand Up @@ -34,9 +34,10 @@

#include "usb_moded-log.h"

const char *log_name = "<unset>";
int log_level = LOG_WARNING;
int log_type = LOG_TO_STDERR;
static const char *log_name = "<unset>";
static int log_level = LOG_WARNING;
static int log_type = LOG_TO_STDERR;
static bool log_lineinfo = false;

static char *strip(char *str)
{
Expand Down Expand Up @@ -71,10 +72,10 @@ static void log_gettime(struct timeval *tv)
* @param fmt The message to be logged
* @param va The stdarg variable list
*/
void log_emit_va(int lev, const char *fmt, va_list va)
void log_emit_va(const char *file, const char *func, int line, int lev, const char *fmt, va_list va)
{
int saved = errno;
if( log_level >= lev )
if( log_p(lev) )
{
switch( log_type )
{
Expand All @@ -85,7 +86,15 @@ void log_emit_va(int lev, const char *fmt, va_list va)

case LOG_TO_STDERR:

fprintf(stderr, "%s: ", log_name);
if( log_get_lineinfo() ) {
/* Use gcc error like prefix for logging so
* that logs can be analyzed with jump to
* line parsing available in editors. */
fprintf(stderr, "%s:%d: %s(): ", file, line, func);
}
else {
fprintf(stderr, "%s: ", log_get_name());
}

#if LOG_ENABLE_TIMESTAMPS
{
Expand All @@ -102,12 +111,12 @@ void log_emit_va(int lev, const char *fmt, va_list va)
static const char *tag = "U:";
switch( lev )
{
case 2: tag = "C:"; break;
case 3: tag = "E:"; break;
case 4: tag = "W:"; break;
case 5: tag = "N:"; break;
case 6: tag = "I:"; break;
case 7: tag = "D:"; break;
case LOG_CRIT: tag = "C:"; break;
case LOG_ERR: tag = "E:"; break;
case LOG_WARNING: tag = "W:"; break;
case LOG_NOTICE: tag = "N:"; break;
case LOG_INFO: tag = "I:"; break;
case LOG_DEBUG: tag = "D:"; break;
}
fprintf(stderr, "%s ", tag);
}
Expand All @@ -129,44 +138,109 @@ void log_emit_va(int lev, const char *fmt, va_list va)
errno = saved;
}

void log_emit(int lev, const char *fmt, ...)
void log_emit_real(const char *file, const char *func, int line, int lev, const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
log_emit_va(lev, fmt, va);
log_emit_va(file, func, line, lev, fmt, va);
va_end(va);
}

void log_debugf(const char *fmt, ...)
{
/* This goes always to stderr */
if( log_type == LOG_TO_STDERR && log_level >= LOG_DEBUG )
if( log_type == LOG_TO_STDERR && log_p(LOG_DEBUG) )
{
va_list va;
va_start(va, fmt);
vfprintf(stderr, fmt, va);
va_end(va);
}
}
/**
* returns the currently set log level

/** Get the currently set logging level
*
* @return The current log level
* @return The current logging level
*/
inline int log_get_level(void)
int log_get_level(void)
{
return log_level;
}

/* Set the log level
/** Set the logging level
*
* @param The wanted log level
* @param lev The wanted logging level
*/
inline void log_set_level(int lev)
void log_set_level(int lev)
{
log_level = lev;
}

/** Test if logging should be done at given level
*
* @param lev The logging level to query
*
* @return true if logging in the given level is allowed, false otherwise
*/
bool log_p(int lev)
{
return lev <= log_level;
}

/** Get the currently set logging type
*
* @return The current logging type
*/
int log_get_type(void)
{
return log_type;
}

/* Set the logging type
*
* @param type The wanted logging type
*/
void log_set_type(int type)
{
log_type = type;
}

/** Get the currently set logging name
*
* @return The current logging name
*/
const char *log_get_name(void)
{
return log_name;
}

/** Set the logging name
*
* @param name The wanted logging name
*/
void log_set_name(const char *name)
{
log_name = name;
}

/** Enable/disable the logging line info
*
* @param lineinfo true to enable line info, false to disable
*/
void log_set_lineinfo(bool lineinfo)
{
log_lineinfo = lineinfo;
}

/** Test if line info should be included in logging
*
* @return true when line info should be emitted, false otherwise
*/
bool log_get_lineinfo(void)
{
return log_lineinfo;
}

/** Initialize logging */
void log_init(void)
{
Expand Down
41 changes: 26 additions & 15 deletions src/usb_moded-log.h
Expand Up @@ -20,6 +20,7 @@
02110-1301 USA
*/

#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
Expand All @@ -28,9 +29,6 @@
#include <syslog.h>

/* Logging functionality */
extern const char *log_name;
extern int log_level;
extern int log_type;

#define LOG_ENABLE_DEBUG 01
#define LOG_ENABLE_TIMESTAMPS 01
Expand All @@ -45,25 +43,38 @@ enum

void log_set_level(int lev);
int log_get_level(void);
int log_get_type(void);
void log_set_type(int type);
const char *log_get_name(void);
void log_set_name(const char *name);
void log_set_lineinfo(bool lineinfo);
bool log_get_lineinfo(void);

void log_init(void);
void log_emit_va(int lev, const char *fmt, va_list va);
void log_emit(int lev, const char *fmt, ...) __attribute__((format(printf,2,3)));
void log_emit_va(const char *file, const char *func, int line, int lev, const char *fmt, va_list va);
void log_emit_real(const char *file, const char *func, int line, int lev, const char *fmt, ...) __attribute__((format(printf,5,6)));
void log_debugf(const char *fmt, ...) __attribute__((format(printf,1,2)));
bool log_p(int lev);

#define log_crit(...) log_emit(2, __VA_ARGS__)
#define log_err(...) log_emit(3, __VA_ARGS__)
#define log_warning(...) log_emit(4, __VA_ARGS__)
#define log_emit(LEV, FMT, ARGS...) do {\
if( log_p(LEV) ) {\
log_emit_real(__FILE__,__FUNCTION__,__LINE__, LEV, FMT, ##ARGS);\
}\
} while(0)

#define log_crit( FMT, ARGS...) log_emit(LOG_CRIT, FMT, ##ARGS)
#define log_err( FMT, ARGS...) log_emit(LOG_ERR, FMT, ##ARGS)
#define log_warning( FMT, ARGS...) log_emit(LOG_WARNING, FMT, ##ARGS)

#if LOG_ENABLE_DEBUG
# define log_notice(...) log_emit(5, __VA_ARGS__)
# define log_info(...) log_emit(6, __VA_ARGS__)
# define log_debug(...) log_emit(7, __VA_ARGS__)
# define log_notice( FMT, ARGS...) log_emit(LOG_NOTICE, FMT, ##ARGS)
# define log_info( FMT, ARGS...) log_emit(LOG_INFO, FMT, ##ARGS)
# define log_debug( FMT, ARGS...) log_emit(LOG_DEBUG, FMT, ##ARGS)
#else
# define log_notice(...) do{}while(0)
# define log_info(...) do{}while(0)
# define log_debug(...) do{}while(0)
# define log_notice( FMT, ARGS...) do{}while(0)
# define log_info( FMT, ARGS...) do{}while(0)
# define log_debug( FMT, ARGS...) do{}while(0)

# define log_debugf(...) do{}while(0)
# define log_debugf( FMT, ARGS...) do{}while(0)
#endif

35 changes: 24 additions & 11 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,7 +218,10 @@ 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 )
{
log_warning("write(%s): %m", path);
if( clear && errno == EINVAL )
log_debug("write(%s): %m (expected failure)", path);
else
log_warning("write(%s): %m", path);
goto cleanup;
}
todo -= n;
Expand Down

0 comments on commit 69a44b2

Please sign in to comment.