Update initial source codes 75/88475/1 release-20160930 upstream/0.1
authorDonghoon Shin <dhs.shin@samsung.com>
Mon, 19 Sep 2016 08:39:50 +0000 (17:39 +0900)
committerDonghoon Shin <dhs.shin@samsung.com>
Mon, 19 Sep 2016 08:39:50 +0000 (17:39 +0900)
Change-Id: Idbb25ef27bbe570b7684143029395b61cc98f9d8

12 files changed:
Makefile [new file with mode: 0644]
README [new file with mode: 0644]
csv2plot [new file with mode: 0755]
debian/changelog [new file with mode: 0644]
debian/compat [new file with mode: 0644]
debian/control [new file with mode: 0644]
debian/copyright [new file with mode: 0644]
debian/docs [new file with mode: 0644]
debian/files [new file with mode: 0644]
debian/rules [new file with mode: 0755]
debian/source/format [new file with mode: 0644]
smartpower.c [new file with mode: 0755]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..169c84c
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,13 @@
+OUT = smartpower
+SRC = smartpower.c
+
+$(OUT): $(SRC)
+       gcc $< -Wall -O2 -o $@
+
+clean:
+       -rm -f $(OUT)
+
+install: $(OUT)
+       cp $(OUT) $(DESTDIR)/usr/bin
+
+$(OUT): Makefile
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..d5381bb
--- /dev/null
+++ b/README
@@ -0,0 +1,2 @@
+This work is motivated by the need of having command line tool that can stream
+data from ODROID Smart Power power supply.
diff --git a/csv2plot b/csv2plot
new file mode 100755 (executable)
index 0000000..fbb250f
--- /dev/null
+++ b/csv2plot
@@ -0,0 +1,67 @@
+#!/bin/sh
+#
+# rudimental script to plot two csv data sets
+#
+# Copyright (c) 2015, Aliaksei Katovich <aliaksei.katovich at gmail.com>
+#
+# Licensed under the GNU General Public License version 2 (GPLv2).
+
+color1="#000070"
+color2="#007000"
+
+bg="grey80"
+fg="black"
+
+_init()
+{
+       echo "set obj 1 rectangle behind from screen 0,0 to screen 1,1"
+       echo "set obj 1 fillstyle solid 1.0 fillcolor rgb '$bg'"
+       echo "set term wxt font 'Arial Bold,9'"
+
+       echo "set title '$name1 vs $name2' tc rgb '$fg'"
+       echo "set key left Left"
+       echo "set key tc rgb '$fg'"
+       echo "set xtic auto"
+       echo "set xlabel 'Time in seconds' tc rgb '$fg' offset 0,-4"
+       echo "set xtics rotate by 90 offset 0,-4"
+
+       echo "set ylabel '$name1 (mA)' tc rgb '$color1'"
+       echo "set ytic auto nomirror tc lt 1"
+
+       echo "set y2label '$name2 (mA)' tc rgb '$color2'"
+       echo "set y2tic auto nomirror tc lt 2"
+
+       echo "set border 1 lt rgb '$fg'"
+       echo "set grid lt 0 lw 1 lc rgb '$fg'"
+
+       echo "set ytics tc rgb '$fg'"
+       echo "set y2tics tc rgb '$fg'"
+       echo "set style data lines"
+
+       echo "set datafile separator ','"
+
+       echo "f(x) = mean_y"
+       echo "fit f(x) '$file1' u 1:3 via mean_y"
+       echo "f(x) = mean_y2"
+       echo "fit f(x) '$file2' u 1:3 via mean_y2"
+
+       echo -n "plot '$file1' u 1:3 "
+       echo -n "title sprintf('$name1 mean %.06f mA', mean_y) "
+       echo -n "lt 1 lc rgb '$color1' axes x1y1,"
+       echo -n "'$file2' u 1:3 "
+       echo -n "title sprintf('$name2 mean %.06f mA', mean_y2) "
+       echo "lt 2 lc rgb '$color2' axes x1y2"
+}
+
+file1=$1
+file2=$2
+
+if [ -z "$file2" ]; then
+       echo "Usage: $(basename $0) <data1.csv> <data2.csv>"
+       exit 1
+fi
+
+name1=$(basename $file1)
+name2=$(basename $file2)
+
+_init | gnuplot -noraise -p
diff --git a/debian/changelog b/debian/changelog
new file mode 100644 (file)
index 0000000..a8841e2
--- /dev/null
@@ -0,0 +1,5 @@
+smartpower (0.1-1) unstable; urgency=low
+
+  * Initial release
+
+ -- Donghoon Shin <dhs.shin@samsung.com>  Mon, 30 May 2016 11:24:58 +0900
diff --git a/debian/compat b/debian/compat
new file mode 100644 (file)
index 0000000..ec63514
--- /dev/null
@@ -0,0 +1 @@
+9
diff --git a/debian/control b/debian/control
new file mode 100644 (file)
index 0000000..e05c9f0
--- /dev/null
@@ -0,0 +1,13 @@
+Source: smartpower
+Section: devel
+Priority: optional
+Maintainer: Donghoon Shin <dhs.shin@samsung.com>
+Build-Depends: debhelper (>= 8.0.0)
+Standards-Version: 3.9.4
+Homepage: https://github.com/polarcat/smartpower.git
+
+Package: smartpower
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: smartpower
+ This work is motivated by the need of having command line tool that can stream data from ODROID Smart Power power supply.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644 (file)
index 0000000..610786c
--- /dev/null
@@ -0,0 +1,31 @@
+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: smartpower
+Source: https://github.com/polarcat/smartpower.git
+
+Upstream Authors: Aliaksei Katovich
+
+Files: *
+Copyright:
+ Copyright (C) 2013  Aliaksei Katovich
+License: GPL-3.0+
+
+Files: debian/*
+Copyright: 2016 Donghoon Shin <dhs.shin@samsung.com>
+License: GPL-3.0+
+
+License: GPL-3.0+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ .
+ This package is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+ .
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ .
+ On Debian systems, the complete text of the GNU General
+ Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
diff --git a/debian/docs b/debian/docs
new file mode 100644 (file)
index 0000000..e845566
--- /dev/null
@@ -0,0 +1 @@
+README
diff --git a/debian/files b/debian/files
new file mode 100644 (file)
index 0000000..b6a272c
--- /dev/null
@@ -0,0 +1 @@
+smartpower_0.1-1_amd64.deb devel optional
diff --git a/debian/rules b/debian/rules
new file mode 100755 (executable)
index 0000000..6c65b43
--- /dev/null
@@ -0,0 +1,12 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+%:
+       dh $@ 
+
+override_dh_auto_install:
+       mkdir -p debian/smartpower/usr/bin
+       dh_auto_install
diff --git a/debian/source/format b/debian/source/format
new file mode 100644 (file)
index 0000000..163aaf8
--- /dev/null
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/smartpower.c b/smartpower.c
new file mode 100755 (executable)
index 0000000..b603126
--- /dev/null
@@ -0,0 +1,457 @@
+/*
+ * @file smartpower.c: ODROID Smart Power data logger
+ *
+ * @author: Aliaksei Katovich <aliaksei.katovich@gmail.com>
+ *
+ * Copyright (C) 2013  Aliaksei Katovich
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/types.h>
+#include <linux/input.h>
+#include <linux/hidraw.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#define err(fmt, args...) { \
+       fprintf(stderr, "(ee) "fmt, ##args); \
+       fprintf(stderr, "(ii) %s:%d: %s, %d\n", __func__, __LINE__, \
+               strerror(errno), errno); \
+}
+
+#define msg(fmt, args...) fprintf(stderr, "(==) "fmt, ##args)
+
+#define MAX_BUF                65
+#define MAX_SLEEP      100 /* us */
+
+#define        FLG_DATA        0x37
+#define FLG_STARTSTOP  0x80
+#define FLG_STATUS     0x81
+#define FLG_ONOFF      0x82
+#define FLG_VERSION    0x83
+
+const char *bus_str(int bus)
+{
+       switch (bus) {
+       case BUS_USB:
+               return "USB";
+               break;
+       case BUS_HIL:
+               return "HIL";
+               break;
+       case BUS_BLUETOOTH:
+               return "Bluetooth";
+               break;
+       case BUS_VIRTUAL:
+               return "Virtual";
+               break;
+       default:
+               return "Other";
+               break;
+       }
+}
+
+static int smartp_open(const char *dev)
+{
+       int fd;
+
+       fd = open(dev, O_RDWR | O_NONBLOCK);
+       if (fd < 0) {
+               err("%s: unable to open device\n", dev);
+
+               if (errno == 13) {
+                       msg("become root or escalate priviledge\n");
+                       exit(errno);
+               }
+
+               return -errno;
+       }
+
+       return fd;
+}
+
+static int csv;
+static char sep;
+static int ts_style;
+static double ts_start;
+
+static void smartp_printd(const unsigned char *data)
+{
+       struct timeval tv;
+       double ts;
+       unsigned long long ts_sec, ts_usec;
+
+       if (ts_start == 0.0) {
+               gettimeofday(&tv, NULL);
+               ts_start = (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0;
+               if (ts_style == 0)
+                       printf("0.0%c%s\n", sep, data);
+               else
+                       printf("[%5u.%06u] %s\n", 0, 0, data);
+               return;
+       }
+
+       gettimeofday(&tv, NULL);
+       ts = (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0 - ts_start;
+       if (ts_style == 0) {
+               printf("%f%c%s\n", ts, sep, data);
+       } else {
+               ts_sec = ts;
+               ts_usec = (ts - (unsigned long long) ts) * 1000000.0;
+               printf("[%5u.%06u] %s\n", (unsigned int) ts_sec,
+                       (unsigned int) ts_usec, data);
+       }
+}
+
+static void smartp_csv(unsigned char *data, size_t len, unsigned int start)
+{
+       int i, space = 0;
+       unsigned char *ptr;
+
+       for (i = 0, ptr = &data[start]; *ptr != '\0'; ptr++) {
+               if (*ptr == ' ' && space == 0) {
+                       data[i] = ',';
+                       space++;
+                       i++;
+               } else if (*ptr == '.' || (*ptr >= 0x30 && *ptr <= 0x39)) {
+                       data[i] = *ptr;
+                       space = 0;
+                       i++;
+               }
+       }
+       data[i] = '\0';
+}
+
+#define SMARTP_READ_MAX 100000
+
+static int smartp_read(int fd, unsigned char *buf, size_t len)
+{
+       int rc = -1;
+       int i;
+
+       memset(buf, 0, len);
+
+       for (i = 0; i < SMARTP_READ_MAX; i++) {
+               rc = read(fd, buf, len);
+               if (rc >= 0)
+                       break;
+       }
+
+       if (rc < 0) {
+               err("failed to read %lu bytes\n", (unsigned long)len);
+               return rc;
+       }
+
+       switch (buf[0]) {
+       case 0x37:
+               if (!csv) {
+                       smartp_printd(&buf[2]);
+               } else {
+                       smartp_csv(buf, len, 2);
+                       smartp_printd(buf);
+               }
+               break;
+       case 0x81:
+               printf("Power %s, record %s\n",
+                       buf[2] == 0 ? "off" : "on",
+                       buf[1] == 0 ? "off" : "on");
+               break;
+       case 0x83:
+               printf("Version: %s\n", buf);
+               break;
+       default:
+               printf("????:");
+               for (i = 0; i < rc; i++)
+                       printf("%hhx ", buf[i]);
+               printf("\n");
+       }
+
+       return rc;
+}
+
+static int smartp_send(int fd, unsigned char *buf, size_t len)
+{
+       int rc;
+
+       rc = write(fd, buf, len);
+       if (rc < 0) {
+               err("cmd=%02x\n", buf[1]);
+               return rc;
+       }
+
+       return rc;
+}
+
+static int smartp_toggle_record(int fd)
+{
+       int rc;
+       unsigned char cmd[2] = { 0x00, FLG_STARTSTOP, };
+       unsigned char buf[3];
+
+       rc = smartp_send(fd, cmd, sizeof(cmd));
+       if (rc < 0)
+               return rc;
+
+       /* update status */
+       cmd[1] = FLG_STATUS;
+       rc = smartp_send(fd, cmd, sizeof(cmd));
+       if (rc < 0)
+               return rc;
+
+       return smartp_read(fd, buf, sizeof(buf));
+}
+
+static int smartp_toggle_power(int fd)
+{
+       int rc;
+       unsigned char cmd[2] = { 0x00, FLG_ONOFF, };
+       unsigned char buf[3];
+
+       rc = smartp_send(fd, cmd, sizeof(cmd));
+       if (rc < 0)
+               return rc;
+
+       /* update status */
+       cmd[1] = FLG_STATUS;
+       rc = smartp_send(fd, cmd, sizeof(cmd));
+       if (rc < 0)
+               return rc;
+
+       usleep(100000); /* wait status update; time gained experimentally */
+       return smartp_read(fd, buf, sizeof(buf));
+}
+
+#define MAX_VERSION 17
+
+static int smartp_version(int fd)
+{
+       int rc;
+       unsigned char buf[MAX_VERSION];
+       unsigned char cmd[2] = { 0x00, FLG_VERSION, };
+
+       rc = smartp_send(fd, cmd, sizeof(cmd));
+       if (rc < 0)
+               return rc;
+
+       memset(buf, 0, sizeof(buf));
+       return smartp_read(fd, buf, sizeof(buf));
+}
+
+#define MAX_DATA 34
+
+static int smartp_getdata(int fd)
+{
+       int rc;
+       unsigned char buf[MAX_DATA];
+       unsigned char cmd[2] = { 0x00, FLG_DATA, };
+
+       rc = smartp_send(fd, cmd, sizeof(cmd));
+       if (rc < 0)
+               return rc;
+
+       memset(buf, 0, sizeof(buf));
+       return smartp_read(fd, buf, sizeof(buf));
+}
+
+#define SMARTP_VENDOR  0x04d8
+#define SMARTP_PRODUCT 0x003f
+
+#define HIDRAW_CLASS   "/sys/class/hidraw"
+
+static int smartp_probe(void)
+{
+       int i = 0;
+       int rc;
+       int fd = -1;
+       struct hidraw_devinfo info;
+       char name[80];
+       DIR *dir;
+       struct dirent *dentry;
+
+       dir = opendir(HIDRAW_CLASS);
+       if (!dir) {
+               err(HIDRAW_CLASS": failed to open directory\n");
+               msg("try to enable CONFIG_HIDRAW in kernel config\n");
+               return -errno;
+       }
+
+       while ((dentry = readdir(dir))) {
+               if (dentry->d_name[0] == '.')
+                       continue;
+               i++;
+               snprintf(name, sizeof(name), "/dev/%s", dentry->d_name);
+               fd = smartp_open(name);
+               if (fd < 0)
+                       continue;
+               rc = ioctl(fd, HIDIOCGRAWINFO, &info);
+               if (rc < 0)
+                       continue;
+               if (info.vendor == SMARTP_VENDOR && info.product == SMARTP_PRODUCT) {
+                       msg("Detected smartp at %s\n", name);
+                       break;
+               }
+       }
+       closedir(dir);
+
+       if (i == 0)
+               msg("smart power device is not connected\n");
+
+       return fd;
+}
+
+static int smartp_verbose(int fd, const char *dev)
+{
+       int rc;
+       unsigned char buf[256];
+       struct hidraw_devinfo info;
+
+       memset(&info, 0x0, sizeof(info));
+       memset(buf, 0x0, sizeof(buf));
+
+       /* Get Raw Name */
+       rc = ioctl(fd, HIDIOCGRAWNAME(256), buf);
+       if (rc < 0) {
+               err("%s: failed to get raw name\n", dev);
+               return -errno;
+       }
+       printf("Raw name: %s\n", buf);
+
+       /* Get Physical Location */
+       rc = ioctl(fd, HIDIOCGRAWPHYS(256), buf);
+       if (rc < 0) {
+               err("%s: failed to get physical location\n", dev);
+               return -errno;
+       }
+       printf("Raw phys: %s\n", buf);
+
+       /* Get Raw Info */
+       rc = ioctl(fd, HIDIOCGRAWINFO, &info);
+       if (rc < 0) {
+               err("%s: failed to get raw info\n", dev);
+               return -errno;
+       }
+       printf("Raw info: bustype %d (%s), vendor 0x%04hx, product 0x%04hx\n",
+               info.bustype, bus_str(info.bustype), info.vendor, info.product);
+       return 0;
+}
+
+static int signal_caught;
+
+void signal_handler(int signum)
+{
+       signal_caught = signum;
+}
+
+static void help(const char *name)
+{
+       printf("Usage: %s [options]\n", name);
+       printf("Options:\n");
+       printf("  -h, --help         print this message\n");
+       printf("  -p, --power        toggle power supply on/off\n");
+       printf("  -r, --record       toggle power consumption recording\n");
+       printf("  -v, --verbose      print hidraw details\n");
+       printf("  -k, --kernel       dmesg like time stamps\n");
+       printf("  -c, --csv          produce csv output (default raw)\n");
+       printf("  -s, --samples <n>  take n samples and exit\n");
+       printf("  -d, --dev <dev>    path to hidraw device node\n");
+}
+
+static int opt(const char *arg, const char *args, const char *argl)
+{
+       return (strcmp(arg, args) == 0 || strcmp(arg, argl) == 0);
+}
+
+int main(int argc, char **argv)
+{
+       int fd;
+       int i, samples = 0;
+       const char *dev = NULL;
+       const char *arg;
+       int power = 0, record = 0, verbose = 0;
+
+       for (i = 0; i < argc; i++) {
+               arg = argv[i];
+               if (opt(arg, "-d", "--dev")) {
+                       i++;
+                       dev = argv[i];
+                       continue;
+               }
+               if (opt(arg, "-s", "--samples")) {
+                       i++;
+                       samples = atoi(argv[i]);
+                       continue;
+               }
+               if (opt(arg, "-p", "--power")) {
+                       power = 1;
+                       continue;
+               }
+               if (opt(arg, "-r", "--record")) {
+                       record = 1;
+                       continue;
+               }
+               if (opt(arg, "-v", "--verbose")) {
+                       verbose = 1;
+                       continue;
+               }
+               if (opt(arg, "-k", "--kernel")) {
+                       ts_style = 1;
+                       csv = 0;
+                       sep = ' ';
+                       continue;
+               }
+               if (opt(arg, "-c", "--csv")) {
+                       csv = 1;
+                       sep = ',';
+                       ts_style = 0;
+                       continue;
+               }
+               if (opt(arg, "-h", "--help")) {
+                       help(argv[0]);
+                       return 0;
+               }
+       }
+
+       if (dev)
+               fd = smartp_open(dev);
+       else
+               fd = smartp_probe();
+
+       if (fd < 0)
+               return fd;
+
+       if (verbose == 1) {
+               smartp_verbose(fd, dev);
+               smartp_version(fd);
+       }
+
+       if (record == 1)
+               return smartp_toggle_record(fd);
+
+       if (power == 1)
+               return smartp_toggle_power(fd);
+
+       signal(SIGINT, signal_handler);
+       signal(SIGTERM, signal_handler);
+
+       if (samples == 0) {
+               while (!signal_caught)
+                       smartp_getdata(fd);
+       } else {
+               for (i = 0; i < samples && !signal_caught; i++)
+                       smartp_getdata(fd);
+       }
+
+       close(fd);
+       return 0;
+}