From 9675287062ed3193c8dbd7f4ad88e07823bdf36e Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Sat, 31 Aug 2013 12:23:44 +1000 Subject: [PATCH 1/9] Use ENOMEM instead of ENOSPC From errno(3): ENOMEM Not enough space (POSIX.1) ENOSPC No space left on device (POSIX.1) when we run out memory the reason is a failed malloc, for which ENOMEM seems more appropriate. Signed-off-by: Peter Hutterer Reviewed-by: Benjamin Tissoires --- libevdev/libevdev-int.h | 4 ++-- libevdev/libevdev.c | 8 ++++---- libevdev/libevdev.h | 2 +- test/test-common-uinput.c | 2 +- test/test-int-queue.c | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libevdev/libevdev-int.h b/libevdev/libevdev-int.h index 61c2454..dd38cc8 100644 --- a/libevdev/libevdev-int.h +++ b/libevdev/libevdev-int.h @@ -194,11 +194,11 @@ static inline int queue_alloc(struct libevdev *dev, size_t size) { if (size == 0) - return -ENOSPC; + return -ENOMEM; dev->queue = calloc(size, sizeof(struct input_event)); if (!dev->queue) - return -ENOSPC; + return -ENOMEM; dev->queue_size = size; dev->queue_next = 0; diff --git a/libevdev/libevdev.c b/libevdev/libevdev.c index 36160f6..436f7a9 100644 --- a/libevdev/libevdev.c +++ b/libevdev/libevdev.c @@ -89,7 +89,7 @@ libevdev_new_from_fd(int fd, struct libevdev **dev) d = libevdev_new(); if (!d) - return -ENOSPC; + return -ENOMEM; rc = libevdev_set_fd(d, fd); if (rc < 0) @@ -152,7 +152,7 @@ libevdev_set_fd(struct libevdev* dev, int fd) free(dev->name); dev->name = strdup(buf); if (!dev->name) { - errno = ENOSPC; + errno = ENOMEM; goto out; } @@ -167,7 +167,7 @@ libevdev_set_fd(struct libevdev* dev, int fd) } else { dev->phys = strdup(buf); if (!dev->phys) { - errno = ENOSPC; + errno = ENOMEM; goto out; } } @@ -182,7 +182,7 @@ libevdev_set_fd(struct libevdev* dev, int fd) } else { dev->uniq = strdup(buf); if (!dev->uniq) { - errno = ENOSPC; + errno = ENOMEM; goto out; } } diff --git a/libevdev/libevdev.h b/libevdev/libevdev.h index ff423b9..43b768d 100644 --- a/libevdev/libevdev.h +++ b/libevdev/libevdev.h @@ -202,7 +202,7 @@ extern "C" { * * dev = libevdev_new(); * if (!dev) - * return ENOSPC; + * return ENOMEM; * * err = libevdev_set_fd(dev, fd); * if (err < 0) { diff --git a/test/test-common-uinput.c b/test/test-common-uinput.c index 7f3fe1f..32ecb89 100644 --- a/test/test-common-uinput.c +++ b/test/test-common-uinput.c @@ -75,7 +75,7 @@ uinput_device_new_with_events_v(struct uinput_device **d, const char *name, cons dev = uinput_device_new(name); if (!dev) - return -ENOSPC; + return -ENOMEM; if (id != DEFAULT_IDS) uinput_device_set_ids(dev, id); diff --git a/test/test-int-queue.c b/test/test-int-queue.c index e809048..a57eb93 100644 --- a/test/test-int-queue.c +++ b/test/test-int-queue.c @@ -34,10 +34,10 @@ START_TEST(test_queue_alloc) int rc; rc = queue_alloc(&dev, 0); - ck_assert_int_eq(rc, -ENOSPC); + ck_assert_int_eq(rc, -ENOMEM); rc = queue_alloc(&dev, ULONG_MAX); - ck_assert_int_eq(rc, -ENOSPC); + ck_assert_int_eq(rc, -ENOMEM); rc = queue_alloc(&dev, 100); ck_assert_int_eq(rc, 0); From 2c101977b7830070bdbd18e696857c667e69dee0 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Sat, 31 Aug 2013 12:33:33 +1000 Subject: [PATCH 2/9] Return EBADF when trying to read from an uninitalized device All other functions that check the fd for validity return EBADF, which also makes it easier to debug if the actual device goes away. Signed-off-by: Peter Hutterer Reviewed-by: Benjamin Tissoires --- libevdev/libevdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libevdev/libevdev.c b/libevdev/libevdev.c index 436f7a9..1c99e1f 100644 --- a/libevdev/libevdev.c +++ b/libevdev/libevdev.c @@ -663,7 +663,7 @@ libevdev_next_event(struct libevdev *dev, unsigned int flags, struct input_event int rc = 0; if (dev->fd < 0) - return -ENODEV; + return -EBADF; if (!(flags & (LIBEVDEV_READ_NORMAL|LIBEVDEV_READ_SYNC|LIBEVDEV_FORCE_SYNC))) return -EINVAL; From 22d2a735c473dfa260ffc6bcbb16a5115b8ed719 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Sat, 31 Aug 2013 12:37:14 +1000 Subject: [PATCH 3/9] Return -EBADF for functions that need the fd initialized Signed-off-by: Peter Hutterer Reviewed-by: Benjamin Tissoires --- libevdev/libevdev.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libevdev/libevdev.c b/libevdev/libevdev.c index 1c99e1f..867e008 100644 --- a/libevdev/libevdev.c +++ b/libevdev/libevdev.c @@ -1130,6 +1130,9 @@ libevdev_kernel_set_abs_info(struct libevdev *dev, unsigned int code, const stru { int rc; + if (dev->fd < 0) + return -EBADF; + if (code > ABS_MAX) return -EINVAL; @@ -1147,6 +1150,9 @@ libevdev_grab(struct libevdev *dev, enum libevdev_grab_mode grab) { int rc = 0; + if (dev->fd < 0) + return -EBADF; + if (grab != LIBEVDEV_GRAB && grab != LIBEVDEV_UNGRAB) return -EINVAL; @@ -1250,6 +1256,9 @@ libevdev_kernel_set_led_values(struct libevdev *dev, ...) int rc = 0; size_t nleds = 0; + if (dev->fd < 0) + return -EBADF; + memset(ev, 0, sizeof(ev)); va_start(args, dev); From 37d37cdaea9c010c5f7f0ab878617c8239d14d15 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Sat, 31 Aug 2013 12:59:27 +1000 Subject: [PATCH 4/9] uinput: don't try to set the syspath twice If we have it, stop searching for it. Otherwise a second device with the same name would overwrite the first, causing a leak. Signed-off-by: Peter Hutterer Reviewed-by: Benjamin Tissoires --- libevdev/libevdev-uinput.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libevdev/libevdev-uinput.c b/libevdev/libevdev-uinput.c index de2833e..88ec313 100644 --- a/libevdev/libevdev-uinput.c +++ b/libevdev/libevdev-uinput.c @@ -230,6 +230,7 @@ fetch_syspath_and_devnode(struct libevdev_uinput *uinput_dev) strcat(buf, namelist[i]->d_name); uinput_dev->syspath = strdup(buf); uinput_dev->devnode = fetch_device_node(buf); + break; } } From 55d67a340b058da84b7a5f135192fe126e5cbe0d Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 26 Aug 2013 13:24:26 +1000 Subject: [PATCH 5/9] Drop per-device logging function, use per-library one instead There's no need to have separate logging function for each device created. More likely, libevdev will be hooked up once into the logging system and expected to deal with it. Plus, this allows us to log from the uinput code where we don't have the context anyway. Requires a rename to libevdev_set_log_function to avoid ABI breaks, and while we're breaking the ABI make the logging function more sophisticated to log line, number, etc. Signed-off-by: Peter Hutterer Reviewed-by: Benjamin Tissoires --- libevdev/libevdev-int.h | 27 +++++++++++++++++-- libevdev/libevdev.c | 56 +++++++++++++++++++++++++++++++-------- libevdev/libevdev.h | 40 +++++++++++++++++++++++++--- test/test-libevdev-init.c | 15 ++++++----- 4 files changed, 115 insertions(+), 23 deletions(-) diff --git a/libevdev/libevdev-int.h b/libevdev/libevdev-int.h index dd38cc8..e77db32 100644 --- a/libevdev/libevdev-int.h +++ b/libevdev/libevdev-int.h @@ -38,6 +38,7 @@ #define ABS_MT_MAX ABS_MT_TOOL_Y #define ABS_MT_CNT (ABS_MT_MAX - ABS_MT_MIN + 1) #define LIBEVDEV_EXPORT __attribute__((visibility("default"))) +#define LIBEVDEV_PRINTF(_format, _args) __attribute__ ((format (printf, _format, _args))) #undef min #undef max @@ -71,8 +72,6 @@ enum SyncState { struct libevdev { int fd; - libevdev_log_func_t log; - char *name; char *phys; char *uniq; @@ -109,6 +108,30 @@ struct libevdev { struct timeval last_event_time; }; +struct logdata { + enum libevdev_log_priority priority; /** minimum logging priority */ + libevdev_log_func_t handler; /** handler function */ + void *userdata; /** user-defined data pointer */ +}; +extern struct logdata log_data; + +#define log_msg_cond(priority, ...) \ + do { \ + if (libevdev_get_log_priority() >= priority) \ + log_msg(priority, log_data.userdata, __FILE__, __LINE__, __func__, __VA_ARGS__); \ + } while(0) + +#define log_error(...) log_msg_cond(LIBEVDEV_LOG_ERROR, __VA_ARGS__) +#define log_info(...) log_msg_cond(LIBEVDEV_LOG_INFO, __VA_ARGS__) +#define log_dbg(...) log_msg_cond(LIBEVDEV_LOG_DEBUG, __VA_ARGS__) +#define log_bug(...) log_msg_cond(LIBEVDEV_LOG_ERROR, "BUG: "__VA_ARGS__) + +extern void +log_msg(enum libevdev_log_priority priority, + void *data, + const char *file, int line, const char *func, + const char *format, ...) LIBEVDEV_PRINTF(6, 7); + /** * @return a pointer to the next element in the queue, or NULL if the queue * is full. diff --git a/libevdev/libevdev.c b/libevdev/libevdev.c index 867e008..ff1fd07 100644 --- a/libevdev/libevdev.c +++ b/libevdev/libevdev.c @@ -49,20 +49,35 @@ init_event_queue(struct libevdev *dev) } static void -_libevdev_log(struct libevdev *dev, const char *format, ...) +libevdev_noop_log_func(enum libevdev_log_priority priority, + void *data, + const char *file, int line, const char *func, + const char *format, va_list args) +{ +} + +/* + * Global logging settings. + */ +struct logdata log_data = { + LIBEVDEV_LOG_INFO, + libevdev_noop_log_func, + NULL, +}; + +void +log_msg(enum libevdev_log_priority priority, + void *data, + const char *file, int line, const char *func, + const char *format, ...) { va_list args; va_start(args, format); - dev->log(format, args); + log_data.handler(priority, data, file, line, func, format, args); va_end(args); } -static void -libevdev_noop_log_func(const char *format, va_list args) -{ -} - LIBEVDEV_EXPORT struct libevdev* libevdev_new(void) { @@ -74,7 +89,6 @@ libevdev_new(void) dev->fd = -1; dev->num_slots = -1; dev->current_slot = -1; - dev->log = libevdev_noop_log_func; dev->grabbed = LIBEVDEV_UNGRAB; dev->sync_state = SYNC_NONE; @@ -112,13 +126,33 @@ libevdev_free(struct libevdev *dev) free(dev); } +/* DEPRECATED */ LIBEVDEV_EXPORT void libevdev_set_log_handler(struct libevdev *dev, libevdev_log_func_t logfunc) { - if (dev == NULL) - return; + /* Can't be backwards compatible to this yet, so don't even try */ + fprintf(stderr, "libevdev: ABI change. Log function will not be honored.\n"); +} - dev->log = logfunc ? logfunc : libevdev_noop_log_func; +LIBEVDEV_EXPORT void +libevdev_set_log_function(libevdev_log_func_t logfunc, void *data) +{ + log_data.handler = logfunc ? logfunc : libevdev_noop_log_func; + log_data.userdata = data; +} + +LIBEVDEV_EXPORT void +libevdev_set_log_priority(enum libevdev_log_priority priority) +{ + if (priority > LIBEVDEV_LOG_DEBUG) + priority = LIBEVDEV_LOG_DEBUG; + log_data.priority = priority; +} + +LIBEVDEV_EXPORT enum libevdev_log_priority +libevdev_get_log_priority(void) +{ + return log_data.priority; } LIBEVDEV_EXPORT int diff --git a/libevdev/libevdev.h b/libevdev/libevdev.h index 43b768d..36ecdd1 100644 --- a/libevdev/libevdev.h +++ b/libevdev/libevdev.h @@ -349,28 +349,58 @@ int libevdev_new_from_fd(int fd, struct libevdev **dev); */ void libevdev_free(struct libevdev *dev); +enum libevdev_log_priority { + LIBEVDEV_LOG_ERROR = 10, /** cricitical errors and application bugs */ + LIBEVDEV_LOG_INFO = 20, /** informational messages */ + LIBEVDEV_LOG_DEBUG = 30, /** debug information */ +}; + /** * Logging function called by library-internal logging. * This function is expected to treat it's input like printf would. * + * @param priority Log priority of this message + * @param data User-supplied data pointer (see libevdev_set_log_function()) + * @param file libevdev source code file generating this message + * @param line libevdev source code line generating this message + * @param func libevdev source code function generating this message * @param format printf-style format string * @param args List of arguments * - * @see libevdev_set_log_handler + * @see libevdev_set_log_function */ -typedef void (*libevdev_log_func_t)(const char *format, va_list args); +typedef void (*libevdev_log_func_t)(enum libevdev_log_priority priority, + void *data, + const char *file, int line, + const char *func, + const char *format, va_list args); /** * Set a printf-style logging handler for library-internal logging. The default * logging function is a noop. * - * @param dev The evdev device * @param logfunc The logging function for this device. If NULL, the current * logging function is unset. + * @param data User-specific data passed to the log handler. * * @note This function may be called before libevdev_set_fd(). */ -void libevdev_set_log_handler(struct libevdev *dev, libevdev_log_func_t logfunc); +void libevdev_set_log_function(libevdev_log_func_t logfunc, void *data); + +/** + * Define the minimum level to be printed to the log handler. + * Messages higher than this level are printed, others are discarded. This + * is a global setting and applies to any future logging messages. + * + * @param priority Minimum priority to be printed to the log. + * + */ +void libevdev_set_log_priority(enum libevdev_log_priority priority); + +/** + * @return the current log level + */ +enum libevdev_log_priority libevdev_get_log_priority(void); enum libevdev_grab_mode { @@ -1333,6 +1363,8 @@ int libevdev_get_repeat(struct libevdev *dev, int *delay, int *period); /* replacement: libevdev_kernel_set_abs_info */ int libevdev_kernel_set_abs_value(struct libevdev *dev, unsigned int code, const struct input_absinfo *abs) LIBEVDEV_DEPRECATED; +/* replacement: libevdev_set_log_function */ +void libevdev_set_log_handler(struct libevdev *dev, libevdev_log_func_t logfunc) LIBEVDEV_DEPRECATED; /**************************************/ #ifdef __cplusplus diff --git a/test/test-libevdev-init.c b/test/test-libevdev-init.c index 344bbac..8f1d0d1 100644 --- a/test/test-libevdev-init.c +++ b/test/test-libevdev-init.c @@ -93,24 +93,27 @@ START_TEST(test_init_and_change_fd) } END_TEST -static void logfunc(const char *f, va_list args) {} +static void logfunc(enum libevdev_log_priority priority, + void *data, + const char *file, int line, const char *func, + const char *f, va_list args) {} START_TEST(test_log_init) { struct libevdev *dev = NULL; - libevdev_set_log_handler(NULL, logfunc); - libevdev_set_log_handler(NULL, NULL); + libevdev_set_log_function(logfunc, NULL); + libevdev_set_log_function(NULL, NULL); dev = libevdev_new(); ck_assert(dev != NULL); - libevdev_set_log_handler(dev, logfunc); + libevdev_set_log_function(logfunc, NULL); libevdev_free(dev); dev = libevdev_new(); ck_assert(dev != NULL); - libevdev_set_log_handler(dev, NULL); - libevdev_set_log_handler(dev, logfunc); + libevdev_set_log_function(NULL, NULL); + libevdev_set_log_function(logfunc, NULL); libevdev_free(dev); /* well, we didn't crash. can't test this otherwise */ From a6e25fab76949c5d7ffbaee676ad380b33d78cdb Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Sat, 31 Aug 2013 12:53:36 +1000 Subject: [PATCH 6/9] Log a few errors, specifically application bugs Signed-off-by: Peter Hutterer Reviewed-by: Benjamin Tissoires --- libevdev/libevdev-uinput.c | 5 ++++- libevdev/libevdev.c | 36 +++++++++++++++++++++++++++--------- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/libevdev/libevdev-uinput.c b/libevdev/libevdev-uinput.c index 88ec313..afebc0b 100644 --- a/libevdev/libevdev-uinput.c +++ b/libevdev/libevdev-uinput.c @@ -260,8 +260,10 @@ libevdev_uinput_create_from_device(const struct libevdev *dev, int fd, struct li return fd; new_device->fd_is_managed = 1; - } else if (fd < 0) + } else if (fd < 0) { + log_bug("Invalid fd %d\n", fd); return -EBADF; + } memset(&uidev, 0, sizeof(uidev)); @@ -301,6 +303,7 @@ libevdev_uinput_create_from_device(const struct libevdev *dev, int fd, struct li new_device->fd = fd; if (fetch_syspath_and_devnode(new_device) == -1) { + log_error("unable to fetch syspath or device node.\n"); errno = ENODEV; goto error; } diff --git a/libevdev/libevdev.c b/libevdev/libevdev.c index ff1fd07..dcf2beb 100644 --- a/libevdev/libevdev.c +++ b/libevdev/libevdev.c @@ -158,8 +158,10 @@ libevdev_get_log_priority(void) LIBEVDEV_EXPORT int libevdev_change_fd(struct libevdev *dev, int fd) { - if (dev->fd == -1) + if (dev->fd == -1) { + log_bug("device not initialized. call libevdev_set_fd() first\n"); return -1; + } dev->fd = fd; return 0; } @@ -171,8 +173,10 @@ libevdev_set_fd(struct libevdev* dev, int fd) int i; char buf[256]; - if (dev->fd != -1) + if (dev->fd != -1) { + log_bug("device already initialized.\n"); return -EBADF; + } rc = ioctl(fd, EVIOCGBIT(0, sizeof(dev->bits)), dev->bits); if (rc < 0) @@ -696,11 +700,15 @@ libevdev_next_event(struct libevdev *dev, unsigned int flags, struct input_event { int rc = 0; - if (dev->fd < 0) + if (dev->fd < 0) { + log_bug("device not initialized. call libevdev_set_fd() first\n"); return -EBADF; + } - if (!(flags & (LIBEVDEV_READ_NORMAL|LIBEVDEV_READ_SYNC|LIBEVDEV_FORCE_SYNC))) + if (!(flags & (LIBEVDEV_READ_NORMAL|LIBEVDEV_READ_SYNC|LIBEVDEV_FORCE_SYNC))) { + log_bug("invalid flags %#x\n.\n", flags); return -EINVAL; + } if (flags & LIBEVDEV_READ_SYNC) { if (dev->sync_state == SYNC_NEEDED) { @@ -782,8 +790,10 @@ libevdev_has_event_pending(struct libevdev *dev) struct pollfd fds = { dev->fd, POLLIN, 0 }; int rc; - if (dev->fd < 0) + if (dev->fd < 0) { + log_bug("device not initialized. call libevdev_set_fd() first\n"); return -EBADF; + } if (queue_num_elements(dev) != 0) return 1; @@ -1164,8 +1174,10 @@ libevdev_kernel_set_abs_info(struct libevdev *dev, unsigned int code, const stru { int rc; - if (dev->fd < 0) + if (dev->fd < 0) { + log_bug("device not initialized. call libevdev_set_fd() first\n"); return -EBADF; + } if (code > ABS_MAX) return -EINVAL; @@ -1184,11 +1196,15 @@ libevdev_grab(struct libevdev *dev, enum libevdev_grab_mode grab) { int rc = 0; - if (dev->fd < 0) + if (dev->fd < 0) { + log_bug("device not initialized. call libevdev_set_fd() first\n"); return -EBADF; + } - if (grab != LIBEVDEV_GRAB && grab != LIBEVDEV_UNGRAB) + if (grab != LIBEVDEV_GRAB && grab != LIBEVDEV_UNGRAB) { + log_bug("invalid grab parameter %#x\n", grab); return -EINVAL; + } if (grab == dev->grabbed) return 0; @@ -1290,8 +1306,10 @@ libevdev_kernel_set_led_values(struct libevdev *dev, ...) int rc = 0; size_t nleds = 0; - if (dev->fd < 0) + if (dev->fd < 0) { + log_bug("device not initialized. call libevdev_set_fd() first\n"); return -EBADF; + } memset(ev, 0, sizeof(ev)); From 4b5ffa6bea0d4ac92d567fdb3579baf0fe3ab80d Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Sat, 31 Aug 2013 13:03:47 +1000 Subject: [PATCH 7/9] Warn if there are multiple devices with the same syspath Change to the previous code in that we continue looking at devices even after we've found one. However, this way we can warn the user when we can't guarantee syspath correctness. Signed-off-by: Peter Hutterer Reviewed-by: Benjamin Tissoires --- libevdev/libevdev-uinput.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/libevdev/libevdev-uinput.c b/libevdev/libevdev-uinput.c index afebc0b..af98fa4 100644 --- a/libevdev/libevdev-uinput.c +++ b/libevdev/libevdev-uinput.c @@ -226,11 +226,16 @@ fetch_syspath_and_devnode(struct libevdev_uinput *uinput_dev) buf[len - 1] = '\0'; /* file contains \n */ if (strcmp(buf, uinput_dev->name) == 0) { - strcpy(buf, SYS_INPUT_DIR); - strcat(buf, namelist[i]->d_name); - uinput_dev->syspath = strdup(buf); - uinput_dev->devnode = fetch_device_node(buf); - break; + if (uinput_dev->syspath) { + /* FIXME: could descend into bit comparison here */ + log_info("multiple identical devices found. syspath is unreliable\n"); + break; + } else { + strcpy(buf, SYS_INPUT_DIR); + strcat(buf, namelist[i]->d_name); + uinput_dev->syspath = strdup(buf); + uinput_dev->devnode = fetch_device_node(buf); + } } } From ad709cf95377d1f95b1db4aa2b7fec11382d44dc Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 3 Sep 2013 16:58:29 +1000 Subject: [PATCH 8/9] Log to stderr by default The logging we do use atm inside the library is largely to spot application errors. Log that to stderr by default so it doesn't get lost. Signed-off-by: Peter Hutterer Reviewed-by: Benjamin Tissoires --- libevdev/libevdev.c | 30 +++++++++++++++++++++++++++--- libevdev/libevdev.h | 4 ++-- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/libevdev/libevdev.c b/libevdev/libevdev.c index dcf2beb..aa5cbd6 100644 --- a/libevdev/libevdev.c +++ b/libevdev/libevdev.c @@ -49,11 +49,32 @@ init_event_queue(struct libevdev *dev) } static void -libevdev_noop_log_func(enum libevdev_log_priority priority, +libevdev_dflt_log_func(enum libevdev_log_priority priority, void *data, const char *file, int line, const char *func, const char *format, va_list args) { + const char *prefix; + switch(priority) { + case LIBEVDEV_LOG_ERROR: prefix = "libevdev error"; break; + case LIBEVDEV_LOG_INFO: prefix = "libevdev info"; break; + case LIBEVDEV_LOG_DEBUG: + prefix = "libevdev debug"; + break; + default: + break; + } + /* default logging format: + libevev error in libevdev_some_func: blah blah + libevev info in libevdev_some_func: blah blah + libevev debug in file.c:123:libevdev_some_func: blah blah + */ + + fprintf(stderr, "%s in ", prefix); + if (priority == LIBEVDEV_LOG_DEBUG) + fprintf(stderr, "%s:%d:", file, line); + fprintf(stderr, "%s: ", func); + vfprintf(stderr, format, args); } /* @@ -61,7 +82,7 @@ libevdev_noop_log_func(enum libevdev_log_priority priority, */ struct logdata log_data = { LIBEVDEV_LOG_INFO, - libevdev_noop_log_func, + libevdev_dflt_log_func, NULL, }; @@ -73,6 +94,9 @@ log_msg(enum libevdev_log_priority priority, { va_list args; + if (!log_data.handler) + return; + va_start(args, format); log_data.handler(priority, data, file, line, func, format, args); va_end(args); @@ -137,7 +161,7 @@ libevdev_set_log_handler(struct libevdev *dev, libevdev_log_func_t logfunc) LIBEVDEV_EXPORT void libevdev_set_log_function(libevdev_log_func_t logfunc, void *data) { - log_data.handler = logfunc ? logfunc : libevdev_noop_log_func; + log_data.handler = logfunc; log_data.userdata = data; } diff --git a/libevdev/libevdev.h b/libevdev/libevdev.h index 36ecdd1..844a1eb 100644 --- a/libevdev/libevdev.h +++ b/libevdev/libevdev.h @@ -377,10 +377,10 @@ typedef void (*libevdev_log_func_t)(enum libevdev_log_priority priority, /** * Set a printf-style logging handler for library-internal logging. The default - * logging function is a noop. + * logging function is to stdout. * * @param logfunc The logging function for this device. If NULL, the current - * logging function is unset. + * logging function is unset and no logging is performed. * @param data User-specific data passed to the log handler. * * @note This function may be called before libevdev_set_fd(). From 112ac0351fa268522f836a28da6786c55e746ef7 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 3 Sep 2013 16:54:44 +1000 Subject: [PATCH 9/9] test: test for logging function Signed-off-by: Peter Hutterer --- test/test-libevdev-init.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/test/test-libevdev-init.c b/test/test-libevdev-init.c index 8f1d0d1..02dfa8b 100644 --- a/test/test-libevdev-init.c +++ b/test/test-libevdev-init.c @@ -93,10 +93,16 @@ START_TEST(test_init_and_change_fd) } END_TEST + +static int log_fn_called = 0; +static char *logdata = "test"; static void logfunc(enum libevdev_log_priority priority, void *data, const char *file, int line, const char *func, - const char *f, va_list args) {} + const char *f, va_list args) { + ck_assert_int_eq(strcmp(logdata, data), 0); + log_fn_called++; +} START_TEST(test_log_init) { @@ -107,16 +113,23 @@ START_TEST(test_log_init) dev = libevdev_new(); ck_assert(dev != NULL); - libevdev_set_log_function(logfunc, NULL); - libevdev_free(dev); - dev = libevdev_new(); - ck_assert(dev != NULL); + libevdev_set_log_function(logfunc, logdata); + libevdev_next_event(dev, LIBEVDEV_READ_NORMAL, NULL); + libevdev_set_log_function(NULL, NULL); - libevdev_set_log_function(logfunc, NULL); - libevdev_free(dev); - /* well, we didn't crash. can't test this otherwise */ + libevdev_next_event(dev, LIBEVDEV_READ_NORMAL, NULL); + libevdev_set_log_function(logfunc, logdata); + libevdev_next_event(dev, LIBEVDEV_READ_NORMAL, NULL); + + /* libevdev_next_event(dev, LIBEVDEV_READ_NORMAL, NULL) should + trigger a log message. We called it three times, but only twice + with the logfunc set, thus, ensure we only called the logfunc + twice */ + ck_assert_int_eq(log_fn_called, 2); + + libevdev_free(dev); } END_TEST