diff options
-rw-r--r-- | Android.mk | 34 | ||||
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | clocks.c | 25 | ||||
-rw-r--r-- | debian/changelog | 13 | ||||
-rw-r--r-- | display.c | 1 | ||||
-rw-r--r-- | display.h | 4 | ||||
-rw-r--r-- | gpio.c | 280 | ||||
-rw-r--r-- | gpio.h | 17 | ||||
-rw-r--r-- | powerdebug.c | 26 | ||||
-rw-r--r-- | powerdebug.h | 2 | ||||
-rw-r--r-- | regulator.c | 2 | ||||
-rw-r--r-- | sensor.c | 2 | ||||
-rw-r--r-- | tree.c | 11 | ||||
-rw-r--r-- | tree.h | 2 |
14 files changed, 381 insertions, 40 deletions
diff --git a/Android.mk b/Android.mk new file mode 100644 index 0000000..e062c1c --- /dev/null +++ b/Android.mk @@ -0,0 +1,34 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + + +LOCAL_MODULE_TAGS := optional +LOCAL_SHARED_LIBRARIES := libstlport + +LOCAL_STATIC_LIBRARIES := libncurses + +LOCAL_MODULE := powerdebug + +LOCAL_CPPFLAGS += \ + -DDISABLE_I18N \ + -DDISABLE_TRYCATCH \ + -DNCURSES_NOMACROS \ + -DDISABLE_WSTRING \ + -DDEFAULT_TERM=\"xterm\" \ + -DTERMINFO_PATH=\"/system/etc/terminfo\" \ + -DDEFINE_ETHTOOL_CMD \ + +LOCAL_C_INCLUDES += external/stlport/stlport/ \ + external/stlport/stlport/stl \ + external/stlport/stlport/using/h/ \ + bionic \ + external/ncurses \ + external/ncurses/lib \ + external/ncurses/include \ + external/ncurses/include/ncurses + +LOCAL_SRC_FILES += \ + powerdebug.c sensor.c clocks.c regulator.c \ + display.c tree.c utils.c mainloop.c + +include $(BUILD_EXECUTABLE) @@ -4,7 +4,7 @@ MANDIR=/usr/share/man/man8 CFLAGS?=-O1 -g -Wall -Wshadow CC?=gcc -OBJS = powerdebug.o sensor.o clocks.o regulator.o \ +OBJS = powerdebug.o sensor.o clocks.o regulator.o gpio.o \ display.o tree.o utils.o mainloop.o default: powerdebug @@ -48,27 +48,8 @@ static struct tree *clock_tree = NULL; static int locate_debugfs(char *clk_path) { - const char *mtab = "/proc/mounts"; - struct mntent *mntent; - int ret = -1; - FILE *file = NULL; - - file = setmntent(mtab, "r"); - if (!file) - return -1; - - while ((mntent = getmntent(file))) { - - if (strcmp(mntent->mnt_type, "debugfs")) - continue; - - strcpy(clk_path, mntent->mnt_dir); - ret = 0; - break; - } - - fclose(file); - return ret; + strcpy(clk_path, "/sys/kernel/debug"); + return 0; } static struct clock_info *clock_alloc(void) @@ -413,7 +394,7 @@ int clock_init(void) if (access(clk_dir_path, F_OK)) return -1; - clock_tree = tree_load(clk_dir_path, NULL); + clock_tree = tree_load(clk_dir_path, NULL, false); if (!clock_tree) return -1; diff --git a/debian/changelog b/debian/changelog index 33dd149..1aecbca 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,16 +1,23 @@ -powerdebug (0.5-2011.08-0) natty; urgency=low +powerdebug (0.6.0-2011.09-0) natty; urgency=low + + * added gpio support + * added android port + + -- Daniel Lezcano <daniel.lezcano@linaro.org> Tue, 20 Sep 2011 15:54:06 +0200 + +powerdebug (0.5.2-2011.08-0) natty; urgency=low * fixed lp: 827825 -- Daniel Lezcano <daniel.lezcano@linaro.org> Wed, 17 Aug 2011 17:01:28 +0200 -powerdebug (0.5-2011.07-0) natty; urgency=low +powerdebug (0.5.1-2011.07-0) natty; urgency=low * fixed lp: 802387 -- Daniel Lezcano <daniel.lezcano@linaro.org> Mon, 25 Jul 2011 23:25:05 +0200 -powerdebug (0.5-2011.06-0) natty; urgency=low +powerdebug (0.5.0-2011.06-0) natty; urgency=low * added tree algorithm * a lot of code cleanup @@ -63,6 +63,7 @@ struct windata windata[] = { [CLOCK] = { .name = "Clocks" }, [REGULATOR] = { .name = "Regulators" }, [SENSOR] = { .name = "Sensors" }, + [GPIO] = { .name = "Gpio" }, }; static void display_fini(void) @@ -13,7 +13,7 @@ * - initial API and implementation *******************************************************************************/ -enum { CLOCK, REGULATOR, SENSOR }; +enum { CLOCK, REGULATOR, SENSOR, GPIO }; struct display_ops { int (*display)(bool refresh); @@ -32,3 +32,5 @@ extern void *display_get_row_data(int window); extern int display_init(int wdefault); extern int display_register(int win, struct display_ops *ops); extern int display_column_name(const char *line); + +#define NAME_MAX 255 @@ -0,0 +1,280 @@ +/******************************************************************************* + * Copyright (C) 2010, Linaro Limited. + * + * This file is part of PowerDebug. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daniel Lezcano <daniel.lezcano@linaro.org> (IBM Corporation) + * - initial API and implementation + *******************************************************************************/ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#include <stdio.h> +#undef _GNU_SOURCE +#endif +#include <mntent.h> +#include <string.h> +#include <stdbool.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/param.h> +#include <sys/stat.h> + +#include "powerdebug.h" +#include "display.h" +#include "tree.h" +#include "utils.h" + +#define SYSFS_GPIO "/sys/class/gpio" + +struct gpio_info { + bool expanded; + int active_low; + int value; + int direction; + int edge; + char *prefix; +} *gpios_info; + +static struct tree *gpio_tree = NULL; + +static struct gpio_info *gpio_alloc(void) +{ + struct gpio_info *gi; + + gi = malloc(sizeof(*gi)); + if (gi) { + memset(gi, -1, sizeof(*gi)); + gi->prefix = NULL; + } + + return gi; +} + +static int gpio_filter_cb(const char *name) +{ + /* let's ignore some directories in order to avoid to be + * pulled inside the sysfs circular symlinks mess/hell + * (choose the word which fit better) + */ + if (!strcmp(name, "device")) + return 1; + + if (!strcmp(name, "subsystem")) + return 1; + + if (!strcmp(name, "driver")) + return 1; + + /* we want to ignore the gpio chips */ + if (strstr(name, "chip")) + return 1; + + /* we are not interested by the power value */ + if (!strcmp(name, "power")) + return 1; + + return 0; +} + +static inline int read_gpio_cb(struct tree *t, void *data) +{ + struct gpio_info *gpio = t->private; + + file_read_value(t->path, "active_low", "%d", &gpio->active_low); + file_read_value(t->path, "value", "%d", &gpio->value); + file_read_value(t->path, "edge", "%d", &gpio->edge); + file_read_value(t->path, "direction", "%d", &gpio->direction); + + return 0; +} + +static int read_gpio_info(struct tree *tree) +{ + return tree_for_each(tree, read_gpio_cb, NULL); +} + +static int fill_gpio_cb(struct tree *t, void *data) +{ + struct gpio_info *gpio; + + gpio = gpio_alloc(); + if (!gpio) + return -1; + t->private = gpio; + + /* we skip the root node but we set it expanded for its children */ + if (!t->parent) { + gpio->expanded = true; + return 0; + } + + return read_gpio_cb(t, data); + +} + +static int fill_gpio_tree(void) +{ + return tree_for_each(gpio_tree, fill_gpio_cb, NULL); +} + +static int dump_gpio_cb(struct tree *t, void *data) +{ + struct gpio_info *gpio = t->private; + struct gpio_info *pgpio; + + if (!t->parent) { + printf("/\n"); + gpio->prefix = ""; + return 0; + } + + pgpio = t->parent->private; + + if (!gpio->prefix) + if (asprintf(&gpio->prefix, "%s%s%s", pgpio->prefix, + t->depth > 1 ? " ": "", t->next ? "|" : " ") < 0) + return -1; + + printf("%s%s-- %s (", gpio->prefix, !t->next ? "`" : "", t->name); + + if (gpio->active_low != -1) + printf(" active_low:%d", gpio->active_low); + + if (gpio->value != -1) + printf(", value:%d", gpio->value); + + if (gpio->edge != -1) + printf(", edge:%d", gpio->edge); + + if (gpio->direction != -1) + printf(", direction:%d", gpio->direction); + + printf(" )\n"); + + return 0; +} + +int dump_gpio_info(void) +{ + return tree_for_each(gpio_tree, dump_gpio_cb, NULL); +} + +int gpio_dump(void) +{ + int ret; + + printf("\nGpio Tree :\n"); + printf("***********\n"); + ret = dump_gpio_info(); + printf("\n\n"); + + return ret; +} + +static char *gpio_line(struct tree *t) +{ + struct gpio_info *gpio = t->private; + char *gpioline; + + if (asprintf(&gpioline, "%-20s %-10d %-10d %-10d %-10d", t-> name, + gpio->value, gpio->active_low, gpio->edge, gpio->direction) < 0) + return NULL; + + return gpioline; +} + +static int _gpio_print_info_cb(struct tree *t, void *data) +{ + int *line = data; + char *buffer; + + /* we skip the root node of the tree */ + if (!t->parent) + return 0; + + buffer = gpio_line(t); + if (!buffer) + return -1; + + display_print_line(GPIO, *line, buffer, 0, t); + + (*line)++; + + free(buffer); + + return 0; +} + +static int gpio_print_info_cb(struct tree *t, void *data) +{ + /* we skip the root node of the tree */ + if (!t->parent) + return 0; + + return _gpio_print_info_cb(t, data); +} + +static int gpio_print_header(void) +{ + char *buf; + int ret; + + if (asprintf(&buf, "%-20s %-10s %-10s %-10s %-10s", + "Name", "Value", "Active_low", "Edge", "Direction") < 0) + return -1; + + ret = display_column_name(buf); + + free(buf); + + return ret; +} + +static int gpio_print_info(struct tree *tree) +{ + int ret, line = 0; + + display_reset_cursor(GPIO); + + gpio_print_header(); + + ret = tree_for_each(tree, gpio_print_info_cb, &line); + + display_refresh_pad(GPIO); + + return ret; +} + +static int gpio_display(bool refresh) +{ + if (refresh && read_gpio_info(gpio_tree)) + return -1; + + return gpio_print_info(gpio_tree); +} + +static struct display_ops gpio_ops = { + .display = gpio_display, +}; + +/* + * Initialize the gpio framework + */ +int gpio_init(void) +{ + gpio_tree = tree_load(SYSFS_GPIO, gpio_filter_cb, false); + if (!gpio_tree) + return -1; + + if (fill_gpio_tree()) + return -1; + + return display_register(GPIO, &gpio_ops); +} @@ -0,0 +1,17 @@ +/******************************************************************************* + * Copyright (C) 2010, Linaro Limited. + * + * This file is part of PowerDebug. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daniel Lezcano <daniel.lezcano@linaro.org> (IBM Corporation) + * - initial API and implementation + *******************************************************************************/ + +extern int gpio_init(void); +extern int gpio_dump(void); diff --git a/powerdebug.c b/powerdebug.c index b4575c4..cc9e871 100644 --- a/powerdebug.c +++ b/powerdebug.c @@ -24,6 +24,7 @@ #include "display.h" #include "clocks.h" #include "sensor.h" +#include "gpio.h" #include "mainloop.h" #include "powerdebug.h" @@ -54,9 +55,10 @@ void version() /* * Options: - * -r, --regulator : regulator + * -r, --regulator : regulators * -s, --sensor : sensors * -c, --clock : clocks + * -g, --gpio : gpios * -p, --findparents : clockname whose parents have to be found * -t, --time : ticktime * -d, --dump : dump @@ -70,6 +72,7 @@ static struct option long_options[] = { { "regulator", 0, 0, 'r' }, { "sensor", 0, 0, 's' }, { "clock", 0, 0, 'c' }, + { "gpio", 0, 0, 'g' }, { "findparents", 1, 0, 'p' }, { "time", 1, 0, 't' }, { "dump", 0, 0, 'd' }, @@ -84,6 +87,7 @@ struct powerdebug_options { bool regulators; bool sensors; bool clocks; + bool gpios; bool dump; unsigned int ticktime; int selectedwindow; @@ -101,7 +105,7 @@ int getoptions(int argc, char *argv[], struct powerdebug_options *options) while (1) { int optindex = 0; - c = getopt_long(argc, argv, "rscp:t:dvVh", + c = getopt_long(argc, argv, "rscgp:t:dvVh", long_options, &optindex); if (c == -1) break; @@ -119,6 +123,10 @@ int getoptions(int argc, char *argv[], struct powerdebug_options *options) options->clocks = true; options->selectedwindow = CLOCK; break; + case 'g': + options->gpios = true; + options->selectedwindow = GPIO; + break; case 'p': options->clkname = strdup(optarg); if (!options->clkname) { @@ -149,8 +157,10 @@ int getoptions(int argc, char *argv[], struct powerdebug_options *options) } /* No system specified to be dump, let's default to all */ - if (!options->regulators && !options->clocks && !options->sensors) - options->regulators = options->clocks = options->sensors = true; + if (!options->regulators && !options->clocks && + !options->sensors && !options->gpios) + options->regulators = options->clocks = + options->sensors = options->gpios = true; if (options->selectedwindow == -1) options->selectedwindow = CLOCK; @@ -169,6 +179,9 @@ static int powerdebug_dump(struct powerdebug_options *options) if (options->sensors) sensor_dump(); + if (options->gpios) + gpio_dump(); + return 0; } @@ -234,6 +247,11 @@ int main(int argc, char **argv) options->sensors = false; } + if (gpio_init()) { + printf("failed to initialize gpios\n"); + options->gpios = false; + } + ret = options->dump ? powerdebug_dump(options) : powerdebug_display(options); diff --git a/powerdebug.h b/powerdebug.h index 05d919b..39a7b31 100644 --- a/powerdebug.h +++ b/powerdebug.h @@ -13,4 +13,4 @@ * - initial API and implementation *******************************************************************************/ -#define VERSION "0.5.1" +#define VERSION "0.6.0" diff --git a/regulator.c b/regulator.c index e9b01bb..55bd3e9 100644 --- a/regulator.c +++ b/regulator.c @@ -236,7 +236,7 @@ static struct display_ops regulator_ops = { int regulator_init(void) { - reg_tree = tree_load(SYSFS_REGULATOR, regulator_filter_cb); + reg_tree = tree_load(SYSFS_REGULATOR, regulator_filter_cb, false); if (!reg_tree) return -1; @@ -271,7 +271,7 @@ static struct display_ops sensor_ops = { int sensor_init(void) { - sensor_tree = tree_load(SYSFS_SENSOR, sensor_filter_cb); + sensor_tree = tree_load(SYSFS_SENSOR, sensor_filter_cb, false); if (!sensor_tree) return -1; @@ -17,6 +17,7 @@ #include <stdio.h> #undef _GNU_SOURCE #include <stdlib.h> +#include <stdbool.h> #include <string.h> #include <dirent.h> #include <sys/types.h> @@ -111,7 +112,7 @@ static inline void tree_add_child(struct tree *parent, struct tree *child) * @filter : a callback to filter out the directories * Returns 0 on success, -1 otherwise */ -static int tree_scan(struct tree *tree, tree_filter_t filter) +static int tree_scan(struct tree *tree, tree_filter_t filter, bool follow) { DIR *dir; char *basedir, *newpath; @@ -152,7 +153,7 @@ static int tree_scan(struct tree *tree, tree_filter_t filter) if (ret) goto out_free_newpath; - if (S_ISDIR(s.st_mode)) { + if (S_ISDIR(s.st_mode) || (S_ISLNK(s.st_mode) && follow)) { ret = -1; @@ -164,7 +165,7 @@ static int tree_scan(struct tree *tree, tree_filter_t filter) tree->nrchild++; - ret = tree_scan(child, filter); + ret = tree_scan(child, filter, follow); } out_free_newpath: @@ -190,7 +191,7 @@ static int tree_scan(struct tree *tree, tree_filter_t filter) * Returns a tree structure corresponding to the root node of the * directory tree representation on success, NULL otherwise */ -struct tree *tree_load(const char *path, tree_filter_t filter) +struct tree *tree_load(const char *path, tree_filter_t filter, bool follow) { struct tree *tree; @@ -198,7 +199,7 @@ struct tree *tree_load(const char *path, tree_filter_t filter) if (!tree) return NULL; - if (tree_scan(tree, filter)) { + if (tree_scan(tree, filter, follow)) { tree_free(tree); return NULL; } @@ -41,7 +41,7 @@ typedef int (*tree_cb_t)(struct tree *t, void *data); typedef int (*tree_filter_t)(const char *name); -extern struct tree *tree_load(const char *path, tree_filter_t filter); +extern struct tree *tree_load(const char *path, tree_filter_t filter, bool follow); extern struct tree *tree_find(struct tree *tree, const char *name); |