summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore101
-rw-r--r--CONTRIBUTE.md188
-rw-r--r--COPYING340
-rw-r--r--Doxyfile.in2498
-rw-r--r--Makefile.am17
-rw-r--r--PowerTop.pngbin0 -> 5542 bytes
-rw-r--r--README.md201
-rw-r--r--README.traceevent20
-rw-r--r--TODO21
-rwxr-xr-xautogen.sh3
-rw-r--r--configure.ac169
-rw-r--r--doc/Makefile.am2
-rw-r--r--doc/powertop.8103
-rw-r--r--m4/ChangeLog11
-rw-r--r--patches/linux-2.6.37-ahci-alpm-accounting.patch302
-rw-r--r--patches/linux-2.6.37-vfs-dirty-inode.patch102
-rw-r--r--patches/linux-3.15-rc3-ahci-alpm-with-devslp-accounting.patch340
-rw-r--r--patches/linux-3.3.0-ahci-alpm-accounting.patch307
-rw-r--r--patches/linux-3.3.0-vfs-dirty-inode.patch103
-rw-r--r--patches/linux-3.9.0-ahci-alpm-accounting.patch306
-rw-r--r--patches/linux-3.9.0-ahci-alpm-with-devslp-accounting.patch334
-rw-r--r--po/.tx/config3
-rw-r--r--po/ChangeLog11
-rw-r--r--po/LINGUAS11
-rw-r--r--po/Makefile.in.in453
-rw-r--r--po/Makevars53
-rw-r--r--po/POTFILES.in45
-rw-r--r--po/bn_IN.po1037
-rw-r--r--po/ca.po975
-rw-r--r--po/cs_CZ.po1002
-rw-r--r--po/da_DK.po951
-rw-r--r--po/de_DE.po1011
-rw-r--r--po/en_GB.po967
-rw-r--r--po/en_US.po972
-rw-r--r--po/es_CO.po951
-rw-r--r--po/es_ES.po980
-rw-r--r--po/fy.po992
-rw-r--r--po/hi.po996
-rw-r--r--po/hu_HU.po1002
-rw-r--r--po/id_ID.po997
-rw-r--r--po/it_IT.po994
-rw-r--r--po/ja_JP.po951
-rw-r--r--po/ko.po955
-rw-r--r--po/lt.po993
-rw-r--r--po/nl_NL.po967
-rw-r--r--po/pl_PL.po991
-rw-r--r--po/powertop.pot949
-rw-r--r--po/pt_BR.po999
-rw-r--r--po/ru_RU.po996
-rw-r--r--po/tr_TR.po961
-rw-r--r--po/zh_CN.po996
-rw-r--r--po/zh_TW.po997
-rw-r--r--powertop.service9
-rw-r--r--scripts/bash-completion/Makefile.am2
-rw-r--r--scripts/bash-completion/powertop43
-rw-r--r--scripts/regenerate-potfiles-in15
-rw-r--r--src/Makefile.am176
-rw-r--r--src/calibrate/calibrate.cpp435
-rw-r--r--src/calibrate/calibrate.h32
-rw-r--r--src/cpu/abstract_cpu.cpp535
-rw-r--r--src/cpu/cpu.cpp1075
-rw-r--r--src/cpu/cpu.h234
-rw-r--r--src/cpu/cpu_core.cpp100
-rw-r--r--src/cpu/cpu_linux.cpp350
-rw-r--r--src/cpu/cpu_package.cpp113
-rw-r--r--src/cpu/cpu_rapl_device.cpp74
-rw-r--r--src/cpu/cpu_rapl_device.h57
-rw-r--r--src/cpu/cpudevice.cpp86
-rw-r--r--src/cpu/cpudevice.h63
-rw-r--r--src/cpu/dram_rapl_device.cpp75
-rw-r--r--src/cpu/dram_rapl_device.h57
-rw-r--r--src/cpu/intel_cpus.cpp757
-rw-r--r--src/cpu/intel_cpus.h180
-rw-r--r--src/cpu/intel_gpu.cpp122
-rw-r--r--src/cpu/rapl/rapl_interface.cpp699
-rw-r--r--src/cpu/rapl/rapl_interface.h91
-rwxr-xr-xsrc/csstoh.sh50
-rw-r--r--src/devices/ahci.cpp428
-rw-r--r--src/devices/ahci.h72
-rw-r--r--src/devices/alsa.cpp207
-rw-r--r--src/devices/alsa.h67
-rw-r--r--src/devices/backlight.cpp225
-rw-r--r--src/devices/backlight.h59
-rw-r--r--src/devices/devfreq.cpp334
-rw-r--r--src/devices/devfreq.h76
-rw-r--r--src/devices/device.cpp345
-rw-r--r--src/devices/device.h85
-rw-r--r--src/devices/gpu_rapl_device.cpp70
-rw-r--r--src/devices/gpu_rapl_device.h57
-rw-r--r--src/devices/i915-gpu.cpp121
-rw-r--r--src/devices/i915-gpu.h58
-rw-r--r--src/devices/network.cpp441
-rw-r--r--src/devices/network.h85
-rw-r--r--src/devices/rfkill.cpp177
-rw-r--r--src/devices/rfkill.h62
-rw-r--r--src/devices/runtime_pm.cpp257
-rw-r--r--src/devices/runtime_pm.h66
-rw-r--r--src/devices/thinkpad-fan.cpp124
-rw-r--r--src/devices/thinkpad-fan.h58
-rw-r--r--src/devices/thinkpad-light.cpp113
-rw-r--r--src/devices/thinkpad-light.h58
-rw-r--r--src/devices/usb.cpp254
-rw-r--r--src/devices/usb.h67
-rw-r--r--src/devlist.cpp351
-rw-r--r--src/devlist.h27
-rw-r--r--src/display.cpp342
-rw-r--r--src/display.h99
-rw-r--r--src/lib.cpp597
-rw-r--r--src/lib.h95
-rw-r--r--src/main.cpp578
-rw-r--r--src/measurement/acpi.cpp213
-rw-r--r--src/measurement/acpi.h46
-rw-r--r--src/measurement/extech.cpp354
-rw-r--r--src/measurement/extech.h51
-rw-r--r--src/measurement/measurement.cpp188
-rw-r--r--src/measurement/measurement.h71
-rw-r--r--src/measurement/opal-sensors.cpp48
-rw-r--r--src/measurement/opal-sensors.h42
-rw-r--r--src/measurement/sysfs.cpp160
-rw-r--r--src/measurement/sysfs.h55
-rw-r--r--src/parameters/learn.cpp282
-rw-r--r--src/parameters/parameters.cpp462
-rw-r--r--src/parameters/parameters.h123
-rw-r--r--src/parameters/persistent.cpp202
-rw-r--r--src/perf/perf.cpp266
-rw-r--r--src/perf/perf.h76
-rw-r--r--src/perf/perf_bundle.cpp348
-rw-r--r--src/perf/perf_bundle.h59
-rw-r--r--src/perf/perf_event.h910
-rw-r--r--src/powertop.css263
-rw-r--r--src/process/do_process.cpp1230
-rw-r--r--src/process/interrupt.cpp131
-rw-r--r--src/process/interrupt.h62
-rw-r--r--src/process/powerconsumer.cpp100
-rw-r--r--src/process/powerconsumer.h79
-rw-r--r--src/process/process.cpp246
-rw-r--r--src/process/process.h96
-rw-r--r--src/process/processdevice.cpp99
-rw-r--r--src/process/processdevice.h55
-rw-r--r--src/process/timer.cpp159
-rw-r--r--src/process/timer.h64
-rw-r--r--src/process/work.cpp130
-rw-r--r--src/process/work.h57
-rw-r--r--src/report/report-data-html.cpp128
-rw-r--r--src/report/report-data-html.h76
-rw-r--r--src/report/report-formatter-base.cpp114
-rw-r--r--src/report/report-formatter-base.h52
-rw-r--r--src/report/report-formatter-csv.cpp163
-rw-r--r--src/report/report-formatter-csv.h73
-rw-r--r--src/report/report-formatter-html.cpp376
-rw-r--r--src/report/report-formatter-html.h73
-rw-r--r--src/report/report-formatter.h57
-rw-r--r--src/report/report-maker.cpp187
-rw-r--r--src/report/report-maker.h139
-rw-r--r--src/report/report.cpp217
-rw-r--r--src/report/report.h47
-rw-r--r--src/tuning/bluetooth.cpp228
-rw-r--r--src/tuning/bluetooth.h49
-rw-r--r--src/tuning/ethernet.cpp157
-rw-r--r--src/tuning/ethernet.h49
-rw-r--r--src/tuning/iw.c303
-rw-r--r--src/tuning/iw.h69
-rw-r--r--src/tuning/nl80211.h1897
-rw-r--r--src/tuning/runtime.cpp202
-rw-r--r--src/tuning/runtime.h50
-rw-r--r--src/tuning/tunable.cpp52
-rw-r--r--src/tuning/tunable.h81
-rw-r--r--src/tuning/tuning.cpp332
-rw-r--r--src/tuning/tuning.h33
-rw-r--r--src/tuning/tuningi2c.cpp129
-rw-r--r--src/tuning/tuningi2c.h46
-rw-r--r--src/tuning/tuningsysfs.cpp130
-rw-r--r--src/tuning/tuningsysfs.h53
-rw-r--r--src/tuning/tuningusb.cpp157
-rw-r--r--src/tuning/tuningusb.h51
-rw-r--r--src/tuning/wifi.cpp112
-rw-r--r--src/tuning/wifi.h50
-rw-r--r--src/wakeup/waketab.cpp195
-rw-r--r--src/wakeup/wakeup.cpp52
-rw-r--r--src/wakeup/wakeup.h81
-rw-r--r--src/wakeup/wakeup_ethernet.cpp111
-rw-r--r--src/wakeup/wakeup_ethernet.h50
-rw-r--r--src/wakeup/wakeup_usb.cpp111
-rw-r--r--src/wakeup/wakeup_usb.h50
-rw-r--r--traceevent/Makefile.am7
-rw-r--r--traceevent/event-parse.c5664
-rw-r--r--traceevent/event-parse.h857
-rw-r--r--traceevent/event-utils.h85
-rw-r--r--traceevent/kbuffer-parse.c732
-rw-r--r--traceevent/kbuffer.h67
-rw-r--r--traceevent/parse-filter.c2303
-rw-r--r--traceevent/parse-utils.c129
-rw-r--r--traceevent/trace-seq.c212
193 files changed, 65476 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..aae8e7c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,101 @@
+# automake
+Makefile
+Makefile.in
+/ar-lib
+/mdate-sh
+/py-compile
+/test-driver
+/ylwrap
+.deps/
+.dirstamp
+
+# autoconf
+autom4te.cache
+/config.h
+/config.rpath
+/autoscan.log
+/autoscan-*.log
+/aclocal.m4
+/compile
+/config.guess
+/config.h.in
+/config.log
+/config.status
+/config.sub
+/configure
+/configure.scan
+/depcomp
+/install-sh
+/missing
+/stamp-h1
+
+# libtool
+/libtool
+/ltmain.sh
+m4/libtool.m4
+m4/ltoptions.m4
+m4/ltsugar.m4
+m4/ltversion.m4
+m4/lt~obsolete.m4
+.libs
+*.lo
+*.la
+
+# texinfo
+/texinfo.tex
+
+# autoreconf and gettext
+/ABOUT-NLS
+m4/ax_add_fortify_source.m4
+m4/ax_cxx_compile_stdcxx.m4
+m4/ax_pthread.m4
+m4/gettext.m4
+m4/host-cpu-c-abi.m4
+m4/iconv.m4
+m4/intlmacosx.m4
+m4/lib-ld.m4
+m4/lib-link.m4
+m4/lib-prefix.m4
+m4/nls.m4
+m4/pkg.m4
+m4/po.m4
+m4/progtest.m4
+po/POTFILES
+po/Makevars.template
+po/Rules-quot
+po/boldquot.sed
+po/en@boldquot.header
+po/en@quot.header
+po/insert-header.sin
+po/quot.sed
+po/remove-potcdate.sin
+po/remove-potcdate.sed
+
+# gettext build artifacts
+po/ca.gmo
+po/cs_CZ.gmo
+po/de_DE.gmo
+po/en_GB.gmo
+po/en_US.gmo
+po/es_ES.gmo
+po/hu_HU.gmo
+po/id_ID.gmo
+po/nl_NL.gmo
+po/stamp-po
+po/zh_TW.gmo
+
+# other generated files
+/Doxyfile
+src/css.h
+
+# object files
+*.o
+src/powertop
+
+# development tools
+cscope.out
+tags
+
+# doxygen
+doc/html
+Doxyfile.in.bak
diff --git a/CONTRIBUTE.md b/CONTRIBUTE.md
new file mode 100644
index 0000000..4287d41
--- /dev/null
+++ b/CONTRIBUTE.md
@@ -0,0 +1,188 @@
+# How to Contribute to PowerTOP
+
+If you are interested in PowerTOP and wish to put some time and effort into it,
+this is the document for you. Filing bug reports, translating text strings,
+editing or creating documentation, helping fellow users, or making changes to
+the program source code are some of the ways you can contribute to the project.
+
+Thank you for your interest in PowerTOP. We appreciate your effort, time, and
+continued participation in this project.
+
+
+# Official source code repository
+
+The official source code repository is hosted on GitHub*, so a GitHub account is
+strongly recommended for effective collaboration. All bug filings, changes, and
+releases are hosted there:
+* [Official Upstream Repository][upstream]
+
+Developers, check out the "Code Conventions" section further down. We look
+forward to your pull requests!
+
+
+# Finding bugs
+
+No software is perfect. Since PowerTOP is a diagnostic/debug tool concerned
+with your system, different hardware may behave differently than we expect,
+resulting in weird behaviors (or crashes). There are plenty of bugs to be found
+and squashed, and we appreciate your willingness to help.
+
+Bugs will be filed here:
+* [Official Upstream Repository][upstream]
+
+It is important to note that bug filings are the start of a conversation, and
+conversations are two-way streets. When you find a bug, do not merely "file and
+forget". Expect follow-up questions to be asked. We may even ask you to patch,
+re-compile, and re-run to see if our change(s) fix your issue, especially if
+your system's particular behavior(s) have revealed the bug.
+
+If one of us asks you to do something that tests the limits of your comfort or
+ability, say so, and we will do our best to help you.
+
+
+# Writing documentation
+
+Here is the layout of PowerTOP's documentation:
+* `CONTRIBUTE.md` is this document
+* `README.md` covers cloning, building, and getting started with PowerTOP
+* `doc/powertop.8` is the (roff) manual page for the project
+* Code comments (or lack thereof)
+
+PowerTOP, at present, does not generate a library for use by other programs, so
+there is no "PowerTOP API". The source code does have internal functions and
+APIs for specific duties that are key to program functionality. Those need to
+be thoroughly documented for future developers.
+
+Markdown documents follow the latest CommonMark spec. Generally speaking,
+do not use GitHub's proprietary extensions to Markdown syntax.
+* [CommonMark Specifications][cmark]
+
+The manual page uses roff syntax.
+* `man 7 roff`, or
+* [man 7 roff (in html)][manroff]
+
+Code comments are described in the "Code Conventions" section further down.
+
+
+# Localization
+
+PowerTOP uses `gettext` for localization. Translating strings is done using PO
+files, and those are contributed back to PowerTOP through a GitHub pull
+request.
+
+If you are new to `gettext`, here is the official documentation for it:
+* [Creating PO Files][gettext_create]
+
+The `gettext` project also has some links to commonly-used PO editors:
+* [Editing PO Files][gettext_edit]
+
+
+# Code conventions
+
+PowerTOP's maintainers will enforce the Linux* kernel coding style.
+* [Linux Kernel Coding Style][kernel_style]
+
+That style guide is tailored for the Linux kernel, so "I" is Linus Torvalds.
+For the purposes of the PowerTOP project, the maintainers of PowerTOP have the
+final say on style. If a specific thing does not apply to PowerTOP, the essence
+of the guidance almost surely does. This section will be expanded upon
+as needed.
+
+While C++ is used in some parts of the codebase, C-style comments are
+preferred. This is copy-pasted directly from the kernel style guide:
+
+ /*
+ * This is the preferred style for multi-line
+ * comments in the Linux kernel source code.
+ * Please use it consistently.
+ *
+ * Description: A column of asterisks on the left side,
+ * with beginning and ending almost-blank lines.
+ */
+
+There are sections of that style guide that are specific to the kernel-- the
+"Allocating Memory" and "Don't re-invent the kernel macros" sections come to
+mind. The essential take-aways from those sections are: "Use the right function
+for the right job" and "do not re-invent existing functionality". That is sound
+development advice for any software project.
+
+The PowerTOP code base is constantly evolving, and the code base has been
+around for a while. Expect to see code that does not follow the kernel style
+guide. If you find any such code, fix it or let us know. Those are style bugs
+that need fixing.
+
+When you submit a patch to the PowerTOP project, we assume you agree to
+what's written in the "License" section below.
+
+
+# License
+
+PowerTOP is a GPLv2 project (see `COPYING` and `README.md`). All contributions
+will be licensed under the terms of the GPLv2.
+
+If you create a new source file or header, here is the comment to be placed at
+the beginning (from line 1) of the new file:
+
+```
+/*
+ * Copyright (C) yyyy name of author
+ *
+ * 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; version 2.
+ *
+ * This program 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ */
+```
+
+All contributions to PowerTOP *must* adhere to the Linux kernel's "Developer's
+Certificate of Origin", which we will copy-paste here for completeness:
+
+By making a contribution to this project, you certify that:
+
+```
+a. The contribution was created in whole or in part by me and I have the right
+ to submit it under the open source license indicated in the file; or
+
+b. The contribution is based upon previous work that, to the best of my
+ knowledge, is covered under an appropriate open source license and I have the
+ right under that license to submit that work with modifications, whether
+ created in whole or in part by me, under the same open source license (unless I
+ am permitted to submit under a different license), as indicated in the file; or
+
+c. The contribution was provided directly to me by some other person who
+ certified (a), (b) or (c) and I have not modified it.
+
+d. I understand and agree that this project and the contribution are public and
+ that a record of the contribution (including all personal information I submit
+ with it, including my sign-off) is maintained indefinitely and may be
+ redistributed consistent with this project or the open source license(s)
+ involved.
+```
+
+From: [Developer's Cerificate of Origin][kernel_cos]
+
+
+# Thank You!
+
+Again, thank you! Your time and effort are greatly appreciated! We look forward
+to your contributions, and appreciate your continued participation in the
+project!
+
+
+[upstream]: https://github.com/fenrus75/powertop "Official PowerTOP Repository"
+[cmark]: https://spec.commonmark.org/ "External Link: CommonMark Specifications"
+[manroff]: http://man7.org/linux/man-pages/man7/roff.7.html "External Link: man 7 roff"
+[gettext_create]: https://www.gnu.org/software/gettext/manual/html_node/Creating.html#Creating "External Link: Creating a PO File"
+[gettext_edit]: https://www.gnu.org/software/gettext/manual/html_node/Editing.html#Editing "External Link: PO File Editors"
+[kernel_style]: https://www.kernel.org/doc/html/latest/process/coding-style.html "External Link: Linux kernel coding style"
+[kernel_cos]: https://www.kernel.org/doc/html/latest/process/submitting-patches.html#sign-your-work-the-developer-s-certificate-of-origin "External Link: Developer's Certificate of Origin"
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..6d45519
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/Doxyfile.in b/Doxyfile.in
new file mode 100644
index 0000000..c354044
--- /dev/null
+++ b/Doxyfile.in
@@ -0,0 +1,2498 @@
+# Doxyfile 1.8.18
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the configuration
+# file that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME = "PowerTOP"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER = @VERSION@
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
+
+PROJECT_LOGO = "PowerTop.png"
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = doc
+
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE = English
+
+# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all generated output in the proper direction.
+# Possible values are: None, LTR, RTL and Context.
+# The default value is: None.
+
+OUTPUT_TEXT_DIRECTION = None
+
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
+# such as
+# /***************
+# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
+# Javadoc-style will behave just like regular comments and it will not be
+# interpreted by doxygen.
+# The default value is: NO.
+
+JAVADOC_BANNER = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines (in the resulting output). You can put ^^ in the value part of an
+# alias to insert a newline as if a physical newline was in the original file.
+# When you need a literal { or } or , in the value part of an alias you have to
+# escape them by means of a backslash (\), this can lead to conflicts with the
+# commands \{ and \} for these it is advised to use the version @{ and @} or use
+# a double escape (\\{ and \\})
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice
+# sources only. Doxygen will then generate output that is more tailored for that
+# language. For instance, namespaces will be presented as modules, types will be
+# separated into more groups, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_SLICE = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
+# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL,
+# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
+# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
+# tries to guess whether the code is fixed or free formatted code, this is the
+# default for Fortran type files). For instance to make doxygen treat .inc files
+# as Fortran files (default is PHP), and .f files as C (default is Fortran),
+# use: inc=Fortran f=C.
+#
+# Note: For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See https://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT = NO
+
+# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
+# to that level are automatically included in the table of contents, even if
+# they do not have an id attribute.
+# Note: This feature currently applies only to Markdown headings.
+# Minimum value: 0, maximum value: 99, default value: 5.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+TOC_INCLUDE_HEADINGS = 5
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT = YES
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE = YES
+
+# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
+# methods of a class will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIV_VIRTUAL = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE = YES
+
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. If set to YES, local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO, these classes will be included in the various overviews. This option
+# has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# declarations. If set to NO, these declarations will be included in the
+# documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO, these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES, upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# (including Cygwin) ands Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES, the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO, doxygen will only warn about wrong or incomplete
+# parameter documentation, but not about the absence of documentation. If
+# EXTRACT_ALL is set to YES then this flag will automatically be disabled.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC = NO
+
+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
+# a warning is encountered.
+# The default value is: NO.
+
+WARN_AS_ERROR = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
+# Note: If this tag is empty the current directory is searched.
+
+INPUT = src \
+ traceevent
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: https://www.gnu.org/software/libiconv/) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
+# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment),
+# *.doc (to be provided as doxygen C comment), *.txt (to be provided as doxygen
+# C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd,
+# *.vhdl, *.ucf, *.qsf and *.ice.
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES = YES
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# entity all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see https://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to YES can help to show when doxygen was last run and thus if the
+# documentation is up to date.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP = NO
+
+# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
+# documentation will contain a main index with vertical navigation menus that
+# are dynamically created via JavaScript. If disabled, the navigation index will
+# consists of multiple levels of tabs that are statically embedded in every HTML
+# page. Disable this option to support browsers that do not have JavaScript,
+# like the Qt help browser.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_MENUS = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: https://developer.apple.com/xcode/), introduced with OSX
+# 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
+# genXcode/_index.html for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the master .chm file (NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW = YES
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH = 250
+
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
+# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
+# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
+# the HTML output. These images will generally look nicer at scaled resolutions.
+# Possible values are: png The default and svg Looks nicer but requires the
+# pdf2svg tool.
+# The default value is: png.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FORMULA_FORMAT = svg
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT = YES
+
+# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
+# to create new LaTeX commands to be used in formulas as building blocks. See
+# the section "Including formulas" for details.
+
+FORMULA_MACROFILE =
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# https://www.mathjax.org) which uses client side JavaScript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX = YES
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT = NativeMML
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from https://www.mathjax.org before deployment.
+# The default value is: https://cdn.jsdelivr.net/npm/mathjax@2.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using JavaScript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: https://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: https://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when not enabling USE_PDFLATEX the default is latex when enabling
+# USE_PDFLATEX the default is pdflatex and when in the later case latex is
+# chosen this is overwritten by pdflatex. For specific output languages the
+# default can have been set differently, this depends on the implementation of
+# the output language.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# Note: This tag is used in the Makefile / make.bat.
+# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file
+# (.tex).
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
+# generate index for LaTeX. In case there is no backslash (\) as first character
+# it will be automatically added in the LaTeX code.
+# Note: This tag is used in the generated output file (.tex).
+# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
+# The default value is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_MAKEINDEX_CMD = makeindex
+
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
+# string, for the replacement values of the other commands the user is referred
+# to HTML_HEADER.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER =
+
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES, to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE = plain
+
+# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_TIMESTAMP = NO
+
+# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
+# path from which the emoji images will be read. If a relative path is entered,
+# it will be relative to the LATEX_OUTPUT directory. If left blank the
+# LATEX_OUTPUT directory will be used.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EMOJI_DIRECTORY =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# configuration file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's configuration file. A template extensions file can be
+# generated using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE =
+
+# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
+# with syntax highlighting in the RTF output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_SOURCE_CODE = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING = YES
+
+# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include
+# namespace members in file scope as well, matching the HTML output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_NS_MEMB_FILE_SCOPE = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT = docbook
+
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
+# the structure of the code including all documentation. Note that this feature
+# is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO, the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
+# The default value is: NO.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS = YES
+
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS = YES
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
+# If set to YES the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT = YES
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS = YES
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH = YES
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH = YES
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# http://www.graphviz.org/)).
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT = svg
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG = YES
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+
+PLANTUML_JAR_PATH =
+
+# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
+# configuration file for plantuml.
+
+PLANTUML_CFG_FILE =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP = YES
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..34d085c
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,17 @@
+AUTOMAKE_OPTIONS = subdir-objects
+ACLOCAL_AMFLAGS = --install -I m4
+
+SUBDIRS = \
+ traceevent \
+ src \
+ po \
+ doc \
+ scripts/bash-completion
+
+EXTRA_DIST = \
+ config.rpath \
+ m4/ChangeLog \
+ README \
+ TODO \
+ COPYING \
+ autogen.sh
diff --git a/PowerTop.png b/PowerTop.png
new file mode 100644
index 0000000..838272b
--- /dev/null
+++ b/PowerTop.png
Binary files differ
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..43bd5b2
--- /dev/null
+++ b/README.md
@@ -0,0 +1,201 @@
+# PowerTOP
+
+PowerTOP is a Linux* tool used to diagnose issues with power consumption and
+power management. In addition to being a diagnostic tool, PowerTOP also has an
+interactive mode you can use to experiment with various power management
+settings, for cases where the Linux distribution has not enabled those
+settings.
+
+
+# Build dependencies
+
+PowerTOP is coded in C++. It was written for Linux-based operating systems.
+GNU* libc (`glibc`) and Linux `pthreads` are needed for PowerTOP to function
+properly. The GNU build system (`autoconf`, `automake`, `make`, `libtool`), as
+well as `gettext`, are required to build PowerTOP.
+
+In addition, PowerTOP requires the following:
+
+* kernel version => 2.6.38
+* `ncurses-devel` (required)
+* `libnl-devel` (required)
+* `pciutils-devel` (is only required if you have PCI)
+* `autoconf-archive` (for building)
+
+Example packages to install in Ubuntu*:
+
+ sudo apt install libpci-dev libnl-3-dev libnl-genl-3-dev gettext \
+ libgettextpo-dev autopoint gettext libncurses5-dev libncursesw5-dev libtool-bin \
+ dh-autoreconf autoconf-archive pkg-config
+
+
+## Building PowerTOP
+
+The `autogen.sh` script needs to be run only once to generate `configure`.
+You need to re-run it only if the build system configuration files
+(e.g. `configure.ac`) are modified. The remaining steps are required whenever
+source files are modified.
+
+To build PowerTOP from the cloned source, use the following commands:
+
+ ./autogen.sh
+ ./configure
+ make
+
+
+# Running PowerTOP
+
+The following sections go over basic operation of PowerTOP. This includes
+kernel configuration options (or kernel patches) needed for full functionality.
+Run `powertop --help` to see all options.
+
+
+## Kernel parameters and (optional) patches
+
+PowerTOP needs some kernel config options enabled to function
+properly. As of linux-3.3.0, these are (the list probably is incomplete):
+
+ CONFIG_NO_HZ
+ CONFIG_HIGH_RES_TIMERS
+ CONFIG_HPET_TIMER
+ CONFIG_CPU_FREQ_GOV_ONDEMAND
+ CONFIG_USB_SUSPEND
+ CONFIG_SND_AC97_POWER_SAVE
+ CONFIG_TIMER_STATS
+ CONFIG_PERF_EVENTS
+ CONFIG_PERF_COUNTERS
+ CONFIG_TRACEPOINTS
+ CONFIG_TRACING
+ CONFIG_EVENT_POWER_TRACING_DEPRECATED
+ CONFIG_X86_MSR
+ ACPI_PROCFS_POWER
+ CONFIG_DEBUG_FS
+
+Use these configs from linux-3.13.rc1:
+
+ CONFIG_POWERCAP
+ CONFIG_INTEL_RAPL
+
+The patches in the `patches/` sub-directory are optional but enable *full*
+PowerTOP functionality.
+
+
+## Outputting a report
+
+When PowerTOP is executed as root and without arguments, it runs in
+interactive mode. In this mode, PowerTOP most resembles `top`.
+
+For generating reports, or for filing functional bug reports, there are two
+output modes: CSV and HTML. You can set sample times, the number of iterations,
+a workload over which to run PowerTOP, and whether to include
+`debug`-level output.
+
+For an HTML report, execute PowerTOP with this option:
+
+ powertop --html=report.html
+
+This creates a static `report.html` file, suitable for sharing.
+
+For a CSV report, execute PowerTOP with this option:
+
+ powertop --csv=report.csv
+
+This creates a static `powertop.csv` file, also suitable for sharing.
+
+If you wish to file a functional bug report, generate and share a
+`debug`-mode HTML report and share it, using the following command:
+
+ powertop --debug --html=report.html
+
+**Important Note:** As PowerTOP is intended for privileged (`root`) use, your
+reports-- especially when run with `--debug`-- will contain verbose system
+information. PowerTOP **does not** sanitize, scrub, or otherwise anonymize its
+reports. Be mindful of this when sharing reports.
+
+**Developers:** If you make changes to the HTML reporting code, validate HTML
+output by using the W3C* Markup Validation Service and the W3C CSS Validation
+Service:
+* http://validator.w3.org/#validate_by_upload
+* http://jigsaw.w3.org/css-validator/#validate_by_upload
+
+
+## Calibrating and power numbers
+
+PowerTOP, when running on battery, tracks power consumption and activity on
+the system. Once there are sufficient measurements, PowerTOP can start to
+report power estimates for various activities. You can help increase the
+accuracy of the estimation by running a calibration cycle at least once:
+
+ powertop --calibrate
+
+*Calibration* entails cycling through various display brightness levels
+(including "off"), USB device activities, and other workloads.
+
+
+## Extech Power Analyzer / Datalogger support
+
+Our analysis teams use the Extech* Power Analyzer/Datalogger (model
+number 380803). PowerTOP supports this device over the serial cable by passing
+the device node on the command line using this command:
+
+ powertop --extech=/dev/ttyUSB0
+
+(where ttyUSB0 is the devicenode of the serial-to-usb adapter on our system)
+
+
+# Contributing to PowerTOP and getting support
+
+There are numerous ways you and your friends can contribute to PowerTOP. See
+the `CONTRIBUTE.md` document for more details. Elevator summary: "fork, and
+send PRs!".
+
+We have a mailing list: `powertop@lists.01.org`:
+* Subscribe at:
+ * https://lists.01.org/postorius/lists/powertop.lists.01.org/
+* Browse archives at:
+ * https://lists.01.org/hyperkitty/list/powertop@lists.01.org/
+
+If you find bugs, you can file an issue-- see `CONTRIBUTE.md` for further
+details:
+* File bugs/wishes at:
+ * https://github.com/fenrus75/powertop/issues
+
+
+# Code from other open source projects
+
+PowerTOP contains some code from other open source projects; we'd like to thank
+the authors of those projects for their work. Specifically, PowerTOP contains
+code from
+
+```
+Parse Event Library - Copyright 2009, 2010 Red Hat Inc Steven Rostedt <srostedt@redhat.com>
+nl80211 userspace tool - Copyright 2007, 2008 Johannes Berg <johannes@sipsolutions.net>
+```
+
+
+# Copyright and License
+
+ PowerTOP
+ Copyright (C) 2020 Intel Corporation
+
+ 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; version 2.
+
+ This program 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, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+See `COPYING` file for a copy of the aforementioned (GPLv2) license.
+
+
+## SPDX Tag
+
+ /* SPDX-License-Identifier: GPL-2.0-only */
+
+From: https://spdx.org/licenses/GPL-2.0-only.html
diff --git a/README.traceevent b/README.traceevent
new file mode 100644
index 0000000..0747766
--- /dev/null
+++ b/README.traceevent
@@ -0,0 +1,20 @@
+traceevent:
+
+The traceevent library being built in PowerTOP is really a effort by
+Steven Rostedt. The long term intent is for Steven to push the trace
+event library to distributions, and consume it externally. Right now the
+PowerTOP project is keeping in sync with his code posted in the Linux
+kernel git under tools/lib/traceevent. We will not take patches into the
+traceevent code directly, rather we will be re-basing against that code
+base.
+
+If you find a bug in the trace event code, you should to one of two things.
+
+1. Send a patch to the PowerTOP mailing list, which will get forwared to
+ Steven if appropriate.
+
+2. Send a patch to the PowerTOP mailing list, and
+ CC: Steven Rostedt <rostedt@goodmis.org>
+
+Please do use the PowerTOP mailing list to discuss topics about
+traceevent as its used with PowerTOP.
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..6735b82
--- /dev/null
+++ b/TODO
@@ -0,0 +1,21 @@
+Needed for 2.2
+----------------------------------
+
+* more translations / strings
+* more end user documentation
+* audio calibration? Need appropriate sample
+* reporting for workload mode
+* Add GPU stats to reports [csv,html]
+
+
+Nice to Have
+----------------------------------
+NCURSES STUB (anyone who may care to do this)
+ PowerTOP is intended to be run with ncurses. As such if there is any
+ distribution that can't or won't support ncurses, they need to supply
+ a separate stub to handle there issues.
+
+DONE for 2.2
+----------------------------------
+* interactive mode scrolling
+* In tunables suggest writing min_power to all SATA ports
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..e210037
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+autoreconf --install --verbose
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..f057463
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,169 @@
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ([2.69])
+AC_INIT([powertop], [2.15], [powertop@lists.01.org], [], [https://github.com/fenrus75/powertop])
+AM_INIT_AUTOMAKE([
+ -Wall
+ 1.12.2
+ foreign
+])
+AC_LANG([C++])
+AC_CONFIG_FILES([
+ Makefile
+ Doxyfile
+ src/Makefile
+ traceevent/Makefile
+ po/Makefile.in
+ doc/Makefile
+ scripts/bash-completion/Makefile
+])
+AC_CONFIG_SRCDIR([src/main.cpp])
+AC_CONFIG_MACRO_DIR([m4])
+AC_USE_SYSTEM_EXTENSIONS
+AC_CONFIG_HEADERS([config.h])
+GETTEXT_PACKAGE=powertop
+AC_SUBST([GETTEXT_PACKAGE])
+AM_SILENT_RULES([yes])
+AM_GNU_GETTEXT([external])
+AM_GNU_GETTEXT_VERSION([0.18.2])
+
+m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
+AX_REQUIRE_DEFINED([AX_ADD_FORTIFY_SOURCE])
+AX_REQUIRE_DEFINED([AX_CXX_COMPILE_STDCXX])
+AX_REQUIRE_DEFINED([AX_PTHREAD])
+# Checks for programs.
+AC_PROG_CPP
+AC_PROG_CXX
+AC_PROG_LIBTOOL
+AC_PROG_CC
+AC_PROG_INSTALL
+AM_PROG_CC_C_O
+AX_ADD_FORTIFY_SOURCE
+AX_CXX_COMPILE_STDCXX([11], [noext], [mandatory])
+PKG_PROG_PKG_CONFIG
+
+# Checks for libraries.
+AX_PTHREAD([
+ LIBS="$PTHREAD_LIBS $LIBS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ CC="$PTHREAD_CC"
+ ], [
+ AC_MSG_ERROR([Could not configure pthreads support])
+])
+
+# Checks for header files.
+AC_CHECK_HEADERS([ \
+ fcntl.h \
+ libintl.h \
+ limits.h \
+ locale.h \
+ malloc.h \
+ ncurses.h \
+ stdint.h \
+ stdlib.h \
+ string.h \
+ sys/ioctl.h \
+ sys/socket.h \
+ sys/statfs.h \
+ sys/time.h \
+ termios.h \
+ unistd.h \
+])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_HEADER_STDBOOL
+AC_C_INLINE
+AC_TYPE_INT64_T
+AC_TYPE_PID_T
+AC_TYPE_SIZE_T
+AC_TYPE_SSIZE_T
+AC_TYPE_UINT16_T
+AC_TYPE_UINT32_T
+AC_TYPE_UINT64_T
+
+# Checks for library functions.
+AC_FUNC_MALLOC
+AC_FUNC_MMAP
+AC_FUNC_REALLOC
+AC_FUNC_STRERROR_R
+AC_FUNC_STRTOD
+AC_CHECK_FUNCS([ \
+ clock_gettime \
+ fdatasync \
+ getpagesize \
+ gettimeofday \
+ memmove \
+ memset \
+ mkdir \
+ munmap \
+ pow \
+ realpath \
+ regcomp \
+ select \
+ setlocale \
+ socket \
+ sqrt \
+ strcasecmp \
+ strchr \
+ strrchr \
+ strdup \
+ strerror \
+ strncasecmp \
+ strstr \
+ strtoul \
+ strtoull \
+])
+
+AC_SEARCH_LIBS([clock_gettime], [rt])
+
+PKG_CHECK_MODULES([NCURSES], [ncursesw ncurses], [LIBS="$LIBS $ncurses_LIBS"], [
+ AC_SEARCH_LIBS([delwin], [ncursesw ncurses], [], [
+ AC_MSG_ERROR([ncurses is required but was not found])
+ ], [])
+])
+
+has_libpci=0
+PKG_CHECK_MODULES([PCIUTILS], [libpci],[has_libpci=1], [
+ AC_SEARCH_LIBS([pci_get_dev], [pci],[has_libpci=1], [has_libpci=0])
+])
+
+
+has_libnl_ver=0
+dnl libnl-2 provides only libnl-2.0.pc file, so we check for separate
+dnl libnl-genl-3.0.pc pkg-config file just for libnl-3.0 case.
+PKG_CHECK_MODULES([LIBNL], [libnl-3.0 >= 3.0 libnl-genl-3.0 >= 3.0], [has_libnl_ver=3], [
+ PKG_CHECK_MODULES([LIBNL], [libnl-2.0 >= 2.0], [has_libnl_ver=2], [
+ PKG_CHECK_MODULES([LIBNL], [libnl-1], [has_libnl_ver=1], [has_libnl_ver=0])
+ ])
+])
+AS_IF([test "$has_libnl_ver" -eq 0], [
+ AC_MSG_ERROR([libnl and libnl-genl are required but were not found])
+])
+AS_IF([test "$has_libnl_ver" -gt 1], [
+ AC_DEFINE([HAVE_LIBNL20], [1], [Define if you have libnl-2.0 or higher])
+])
+
+AS_IF([test "$has_libpci" -eq 0], [
+ AC_DEFINE([HAVE_NO_PCI], [1], [Define if pci is not supported])
+ AC_MSG_WARN([
+ ************* LIBPCI SUPPORT NOT CONFIGURED**************
+ If you need or want pci support, please install libpci
+ and re-configure PowerTOP.
+ *********************************************************
+ ])
+])
+
+AC_SEARCH_LIBS([inet_aton], [resolv], [], [
+ AC_MSG_ERROR([libresolv is required but was not found])
+], [])
+
+
+AS_IF([`${PKG_CONFIG} --exists bash-completion`], [
+ bashcompletiondir=`${PKG_CONFIG} --variable=completionsdir --define-variable=prefix=${prefix} bash-completion`
+], [
+ bashcompletiondir=${datadir}/bash-completion/completions
+])
+AC_SUBST([bashcompletiondir], [$bashcompletiondir])
+
+AC_OUTPUT
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644
index 0000000..3fa3770
--- /dev/null
+++ b/doc/Makefile.am
@@ -0,0 +1,2 @@
+man_MANS = powertop.8
+EXTRA_DIST = powertop.8
diff --git a/doc/powertop.8 b/doc/powertop.8
new file mode 100644
index 0000000..60e3c73
--- /dev/null
+++ b/doc/powertop.8
@@ -0,0 +1,103 @@
+.TH POWERTOP "8" "2014-08-02" "powertop manual" "System Administration"
+.SH NAME
+powertop \- a power consumption and power management diagnosis tool.
+.SH SYNOPSIS
+.B powertop
+.RI [ options ]
+.SH DESCRIPTION
+.B powertop
+is a program that helps to diagnose various issues with power consumption
+and power management. It also has an interactive mode allowing one to
+experiment with various power management settings. When invoking
+powertop without arguments powertop starts in interactive mode.
+.SH OPTIONS
+.TP
+.B \-\-auto\-tune
+Set all tunable options to their good setting without interaction.
+.TP
+.BR \-c ", " \-\-calibrate
+Runs powertop in calibration mode. When running on battery, powertop can
+track power consumption as well as system activity. When there are
+enough measurements, powertop can start to report power estimates. One
+can get more accurate estimates by using this option to enable a
+calibration cycle. This will cycle through various display levels and
+USB device activities and workloads.
+.TP
+\fB\-C\fR, \fB\-\-csv\fR[=\fIfilename\fR]
+Generate a CSV report. If a
+.I filename
+is not specified then the default name
+.B powertop.csv
+is used. The CSV report can be used for reporting and data analysis.
+.TP
+.B \-\-debug
+Run in debug mode.
+.TP
+\fB\-\-extech\fR=\fIdevnode\fR
+Use the Extech Power Analyzer for measurements. This allows one to
+specify the serial device node of the serial to USB adaptor connecting to
+the Extech Power Analyzer, for example
+.IR /dev/ttyUSB0 .
+.TP
+\fB\-r\fR, \fB\-\-html\fR[=\fIfilename\fR]
+Generate an HTML report. If a
+.I filename
+is not specified then the default name
+.B powertop.html
+is used. The HTML report can be sent to others to help diagnose power
+issues.
+.TP
+\fB\-i\fR, \fB\-\-iteration\fR[=\fIiterations\fR]
+Number of times to run each test.
+.TP
+.BR \-q ", " \-\-quiet
+Suppress stderr output.
+.TP
+\fB\-t\fR, \fB\-\-time\fR[=\fIseconds\fR]
+Generate a report for a specified number of
+.IR seconds .
+.TP
+\fB\-w\fR, \fB\-\-workload\fR[=\fIworkload\fR]
+Execute
+.I workload
+file as a part of calibration before making a report.
+.TP
+.BR \-V ", " \-\-version
+Print version information and exit.
+.TP
+.BR \-h ", " \-\-help
+Show the help message and exit.
+.SH COMMANDS
+In interactive mode, the following key bindings are available:
+.IP
+.TS
+tab(@);
+l l.
+\fBTab\fR@Show next tab
+\fBBackTab\fR@Show previous tab
+\fBRight Arrow\fR@Scroll to the right
+\fBLeft Arrow\fR@Scroll to the left
+\fBUp Arrow\fR, \fBPageUp\fR@Scroll up or select previous item
+\fBDown Arrow\fR, \fBPageDown\fR@Scroll down or select next item
+\fBSpace\fR, \fBReturn\fR@Activate current item
+\fBs\fR@Set refresh timeout
+\fBr\fR@Refresh window
+\fBq\fR, \fBCtrl-C\fR, \fBEscape\fR@Exit powertop
+.TE
+.SH BUGS
+Send bug reports to
+.MT powertop@lists.01.org
+.ME
+.SH SEE ALSO
+The program is more fully described at
+.UR https://01.org/powertop
+.UE
+.SH AUTHOR
+powertop was written by
+.MT arjan@\:linux.\:intel.\:com
+Arjan van de Ven
+.ME ,
+and is currently maintained by
+.MT chris.\:e.\:ferron@\:linux.\:intel.\:com
+Chris E Ferron
+.ME .
diff --git a/m4/ChangeLog b/m4/ChangeLog
new file mode 100644
index 0000000..f415dc0
--- /dev/null
+++ b/m4/ChangeLog
@@ -0,0 +1,11 @@
+2016-08-03 gettextize <bug-gnu-gettext@gnu.org>
+
+ * gettext.m4: New file, from gettext-0.18.2.
+ * iconv.m4: New file, from gettext-0.18.2.
+ * lib-ld.m4: New file, from gettext-0.18.2.
+ * lib-link.m4: New file, from gettext-0.18.2.
+ * lib-prefix.m4: New file, from gettext-0.18.2.
+ * nls.m4: New file, from gettext-0.18.2.
+ * po.m4: New file, from gettext-0.18.2.
+ * progtest.m4: New file, from gettext-0.18.2.
+
diff --git a/patches/linux-2.6.37-ahci-alpm-accounting.patch b/patches/linux-2.6.37-ahci-alpm-accounting.patch
new file mode 100644
index 0000000..dbe897d
--- /dev/null
+++ b/patches/linux-2.6.37-ahci-alpm-accounting.patch
@@ -0,0 +1,302 @@
+From: Arjan van de Ven <arjan@linux.intel.com>
+Subject: [PATCH] libata: Add ALPM power state accounting to the AHCI driver
+
+PowerTOP wants to be able to show the user how effective the ALPM link
+power management is for the user. ALPM is worth around 0.5W on a quiet
+link; PowerTOP wants to be able to find cases where the "quiet link" isn't
+actually quiet.
+
+This patch adds state accounting functionality to the AHCI driver for
+PowerTOP to use.
+The parts of the patch are
+1) the sysfs logic of exposing the stats for each state in sysfs
+2) the basic accounting logic that gets update on link change interrupts
+ (or when the user accesses the info from sysfs)
+3) a "accounting enable" flag; in order to get the accounting to work,
+ the driver needs to get phyrdy interrupts on link status changes.
+ Normally and currently this is disabled by the driver when ALPM is
+ on (to reduce overhead); when PowerTOP is running this will need
+ to be on to get usable statistics... hence the sysfs tunable.
+
+The PowerTOP output currently looks like this:
+
+Recent SATA AHCI link activity statistics
+Active Partial Slumber Device name
+ 0.5% 99.5% 0.0% host0
+
+(work to resolve "host0" to a more human readable name is in progress)
+
+Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
+
+---
+ drivers/ata/ahci.h | 15 ++++
+ drivers/ata/libahci.c | 187 +++++++++++++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 200 insertions(+), 2 deletions(-)
+
+Index: linux-2.6.37/drivers/ata/ahci.h
+===================================================================
+--- linux-2.6.37.orig/drivers/ata/ahci.h
++++ linux-2.6.37/drivers/ata/ahci.h
+@@ -262,6 +262,13 @@ struct ahci_em_priv {
+ unsigned long led_state;
+ };
+
++enum ahci_port_states {
++ AHCI_PORT_NOLINK = 0,
++ AHCI_PORT_ACTIVE = 1,
++ AHCI_PORT_PARTIAL = 2,
++ AHCI_PORT_SLUMBER = 3
++};
++
+ struct ahci_port_priv {
+ struct ata_link *active_link;
+ struct ahci_cmd_hdr *cmd_slot;
+@@ -280,6 +287,14 @@ struct ahci_port_priv {
+ int fbs_last_dev; /* save FBS.DEV of last FIS */
+ /* enclosure management info per PM slot */
+ struct ahci_em_priv em_priv[EM_MAX_SLOTS];
++
++ /* ALPM accounting state and stats */
++ unsigned int accounting_active:1;
++ u64 active_jiffies;
++ u64 partial_jiffies;
++ u64 slumber_jiffies;
++ int previous_state;
++ int previous_jiffies;
+ };
+
+ struct ahci_host_priv {
+Index: linux-2.6.37/drivers/ata/libahci.c
+===================================================================
+--- linux-2.6.37.orig/drivers/ata/libahci.c
++++ linux-2.6.37/drivers/ata/libahci.c
+@@ -58,6 +58,17 @@ MODULE_PARM_DESC(ignore_sss, "Ignore sta
+
+ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+ unsigned hints);
++static ssize_t ahci_alpm_show_active(struct device *dev,
++ struct device_attribute *attr, char *buf);
++static ssize_t ahci_alpm_show_slumber(struct device *dev,
++ struct device_attribute *attr, char *buf);
++static ssize_t ahci_alpm_show_partial(struct device *dev,
++ struct device_attribute *attr, char *buf);
++static ssize_t ahci_alpm_show_accounting(struct device *dev,
++ struct device_attribute *attr, char *buf);
++static ssize_t ahci_alpm_set_accounting(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count);
+ static ssize_t ahci_led_show(struct ata_port *ap, char *buf);
+ static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
+ size_t size);
+@@ -117,6 +128,12 @@ static DEVICE_ATTR(ahci_host_caps, S_IRU
+ static DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL);
+ static DEVICE_ATTR(ahci_host_version, S_IRUGO, ahci_show_host_version, NULL);
+ static DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL);
++static DEVICE_ATTR(ahci_alpm_active, S_IRUGO, ahci_alpm_show_active, NULL);
++static DEVICE_ATTR(ahci_alpm_partial, S_IRUGO, ahci_alpm_show_partial, NULL);
++static DEVICE_ATTR(ahci_alpm_slumber, S_IRUGO, ahci_alpm_show_slumber, NULL);
++static DEVICE_ATTR(ahci_alpm_accounting, S_IRUGO | S_IWUSR,
++ ahci_alpm_show_accounting, ahci_alpm_set_accounting);
++
+ static DEVICE_ATTR(em_buffer, S_IWUSR | S_IRUGO,
+ ahci_read_em_buffer, ahci_store_em_buffer);
+
+@@ -128,6 +145,10 @@ struct device_attribute *ahci_shost_attr
+ &dev_attr_ahci_host_cap2,
+ &dev_attr_ahci_host_version,
+ &dev_attr_ahci_port_cmd,
++ &dev_attr_ahci_alpm_active,
++ &dev_attr_ahci_alpm_partial,
++ &dev_attr_ahci_alpm_slumber,
++ &dev_attr_ahci_alpm_accounting,
+ &dev_attr_em_buffer,
+ NULL
+ };
+@@ -653,9 +674,14 @@ static int ahci_set_lpm(struct ata_link
+ * Disable interrupts on Phy Ready. This keeps us from
+ * getting woken up due to spurious phy ready
+ * interrupts.
++ *
++ * However, when accounting_active is set, we do want
++ * the interrupts for accounting purposes.
+ */
+- pp->intr_mask &= ~PORT_IRQ_PHYRDY;
+- writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
++ if (!pp->accounting_active) {
++ pp->intr_mask &= ~PORT_IRQ_PHYRDY;
++ writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
++ }
+
+ sata_link_scr_lpm(link, policy, false);
+ }
+@@ -1570,6 +1596,162 @@ static void ahci_error_intr(struct ata_p
+ ata_port_abort(ap);
+ }
+
++static int get_current_alpm_state(struct ata_port *ap)
++{
++ u32 status = 0;
++
++ ahci_scr_read(&ap->link, SCR_STATUS, &status);
++
++ /* link status is in bits 11-8 */
++ status = status >> 8;
++ status = status & 0x7;
++
++ if (status == 6)
++ return AHCI_PORT_SLUMBER;
++ if (status == 2)
++ return AHCI_PORT_PARTIAL;
++ if (status == 1)
++ return AHCI_PORT_ACTIVE;
++ return AHCI_PORT_NOLINK;
++}
++
++static void account_alpm_stats(struct ata_port *ap)
++{
++ struct ahci_port_priv *pp;
++
++ int new_state;
++ u64 new_jiffies, jiffies_delta;
++
++ if (ap == NULL)
++ return;
++ pp = ap->private_data;
++
++ if (!pp) return;
++
++ new_state = get_current_alpm_state(ap);
++ new_jiffies = jiffies;
++
++ jiffies_delta = new_jiffies - pp->previous_jiffies;
++
++ switch (pp->previous_state) {
++ case AHCI_PORT_NOLINK:
++ pp->active_jiffies = 0;
++ pp->partial_jiffies = 0;
++ pp->slumber_jiffies = 0;
++ break;
++ case AHCI_PORT_ACTIVE:
++ pp->active_jiffies += jiffies_delta;
++ break;
++ case AHCI_PORT_PARTIAL:
++ pp->partial_jiffies += jiffies_delta;
++ break;
++ case AHCI_PORT_SLUMBER:
++ pp->slumber_jiffies += jiffies_delta;
++ break;
++ default:
++ break;
++ }
++ pp->previous_state = new_state;
++ pp->previous_jiffies = new_jiffies;
++}
++
++static ssize_t ahci_alpm_show_active(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *shost = class_to_shost(dev);
++ struct ata_port *ap = ata_shost_to_port(shost);
++ struct ahci_port_priv *pp;
++
++ if (!ap || ata_port_is_dummy(ap))
++ return -EINVAL;
++ pp = ap->private_data;
++ account_alpm_stats(ap);
++
++ return sprintf(buf, "%u\n", jiffies_to_msecs(pp->active_jiffies));
++}
++
++static ssize_t ahci_alpm_show_partial(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *shost = class_to_shost(dev);
++ struct ata_port *ap = ata_shost_to_port(shost);
++ struct ahci_port_priv *pp;
++
++ if (!ap || ata_port_is_dummy(ap))
++ return -EINVAL;
++
++ pp = ap->private_data;
++ account_alpm_stats(ap);
++
++ return sprintf(buf, "%u\n", jiffies_to_msecs(pp->partial_jiffies));
++}
++
++static ssize_t ahci_alpm_show_slumber(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *shost = class_to_shost(dev);
++ struct ata_port *ap = ata_shost_to_port(shost);
++ struct ahci_port_priv *pp;
++
++ if (!ap || ata_port_is_dummy(ap))
++ return -EINVAL;
++
++ pp = ap->private_data;
++
++ account_alpm_stats(ap);
++
++ return sprintf(buf, "%u\n", jiffies_to_msecs(pp->slumber_jiffies));
++}
++
++static ssize_t ahci_alpm_show_accounting(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *shost = class_to_shost(dev);
++ struct ata_port *ap = ata_shost_to_port(shost);
++ struct ahci_port_priv *pp;
++
++ if (!ap || ata_port_is_dummy(ap))
++ return -EINVAL;
++
++ pp = ap->private_data;
++
++ return sprintf(buf, "%u\n", pp->accounting_active);
++}
++
++static ssize_t ahci_alpm_set_accounting(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ unsigned long flags;
++ struct Scsi_Host *shost = class_to_shost(dev);
++ struct ata_port *ap = ata_shost_to_port(shost);
++ struct ahci_port_priv *pp;
++ void __iomem *port_mmio;
++
++ if (!ap || ata_port_is_dummy(ap))
++ return 1;
++
++ pp = ap->private_data;
++ port_mmio = ahci_port_base(ap);
++
++ if (!pp)
++ return 1;
++ if (buf[0] == '0')
++ pp->accounting_active = 0;
++ if (buf[0] == '1')
++ pp->accounting_active = 1;
++
++ /* we need to enable the PHYRDY interrupt when we want accounting */
++ if (pp->accounting_active) {
++ spin_lock_irqsave(ap->lock, flags);
++ pp->intr_mask |= PORT_IRQ_PHYRDY;
++ writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
++ spin_unlock_irqrestore(ap->lock, flags);
++ }
++ return count;
++}
++
++
+ static void ahci_port_intr(struct ata_port *ap)
+ {
+ void __iomem *port_mmio = ahci_port_base(ap);
+@@ -1590,6 +1772,7 @@ static void ahci_port_intr(struct ata_po
+ /* if LPM is enabled, PHYRDY doesn't mean anything */
+ if (ap->link.lpm_policy > ATA_LPM_MAX_POWER) {
+ status &= ~PORT_IRQ_PHYRDY;
++ account_alpm_stats(ap);
+ ahci_scr_write(&ap->link, SCR_ERROR, SERR_PHYRDY_CHG);
+ }
+
diff --git a/patches/linux-2.6.37-vfs-dirty-inode.patch b/patches/linux-2.6.37-vfs-dirty-inode.patch
new file mode 100644
index 0000000..c218291
--- /dev/null
+++ b/patches/linux-2.6.37-vfs-dirty-inode.patch
@@ -0,0 +1,102 @@
+From 3950d3c04a6bf8ccf9ff912a49bdd242a2fe9e47 Mon Sep 17 00:00:00 2001
+From: Arjan van de Ven <arjan@linux.intel.com>
+Date: Fri, 26 Nov 2010 12:18:03 -0800
+Subject: [PATCH] vfs: Add a trace point in the mark_inode_dirty function
+
+PowerTOP would like to be able to show who is keeping the disk
+busy by dirtying data. The most logical spot for this is in the vfs
+in the mark_inode_dirty() function, doing this on the block level
+is not possible because by the time the IO hits the block layer the
+guilty party can no longer be found ("kjournald" and "pdflush" are not
+useful answers to "who caused this file to be dirty).
+
+The trace point follows the same logic/style as the block_dump code
+and pretty much dumps the same data, just not to dmesg (and thus to
+/var/log/messages) but via the trace events streams.
+
+Eventually we should be able to phase out the block dump code, but that's
+for later on after a transition time.
+
+Signed-of-by: Arjan van de Ven <arjan@linux.intel.com>
+---
+ fs/fs-writeback.c | 3 +++
+ include/linux/fs.h | 12 ++++++++++++
+ include/trace/events/writeback.h | 28 ++++++++++++++++++++++++++++
+ 3 files changed, 43 insertions(+)
+
+Index: linux-2.6.37/fs/fs-writeback.c
+===================================================================
+--- linux-2.6.37.orig/fs/fs-writeback.c
++++ linux-2.6.37/fs/fs-writeback.c
+@@ -952,6 +952,9 @@ void __mark_inode_dirty(struct inode *in
+ if ((inode->i_state & flags) == flags)
+ return;
+
++ if (flags & (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES))
++ trace_writeback_inode_dirty(inode, flags);
++
+ if (unlikely(block_dump))
+ block_dump___mark_inode_dirty(inode);
+
+Index: linux-2.6.37/include/linux/fs.h
+===================================================================
+--- linux-2.6.37.orig/include/linux/fs.h
++++ linux-2.6.37/include/linux/fs.h
+@@ -1677,6 +1677,18 @@ struct super_operations {
+
+ #define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES)
+
++#define INODE_DIRTY_FLAGS \
++ { I_DIRTY_SYNC, "DIRTY-SYNC" }, \
++ { I_DIRTY_DATASYNC, "DIRTY-DATASYNC" }, \
++ { I_DIRTY_PAGES, "DIRTY-PAGES" }, \
++ { I_NEW, "NEW" }, \
++ { I_WILL_FREE, "WILL-FREE" }, \
++ { I_FREEING, "FREEING" }, \
++ { I_CLEAR, "CLEAR" }, \
++ { I_SYNC, "SYNC" }, \
++ { I_REFERENCED, "REFERENCED" }
++
++
+ extern void __mark_inode_dirty(struct inode *, int);
+ static inline void mark_inode_dirty(struct inode *inode)
+ {
+Index: linux-2.6.37/include/trace/events/writeback.h
+===================================================================
+--- linux-2.6.37.orig/include/trace/events/writeback.h
++++ linux-2.6.37/include/trace/events/writeback.h
+@@ -186,6 +186,34 @@ DEFINE_EVENT(writeback_congest_waited_te
+ TP_ARGS(usec_timeout, usec_delayed)
+ );
+
++/*
++ * Tracepoint for dirtying an inode; used by PowerTOP
++ */
++TRACE_EVENT(writeback_inode_dirty,
++
++ TP_PROTO(struct inode *inode, int flags),
++
++ TP_ARGS(inode, flags),
++
++ TP_STRUCT__entry(
++ __field( __kernel_dev_t, dev )
++ __field( ino_t, ino )
++ __field( u32, flags )
++ ),
++
++ TP_fast_assign(
++ __entry->dev = inode->i_sb->s_dev;
++ __entry->ino = inode->i_ino;
++ __entry->flags = flags;
++ ),
++
++ TP_printk("dev %d:%d ino %lu flags %d %s", MAJOR(__entry->dev), MINOR(__entry->dev),
++ (unsigned long) __entry->ino,
++ __entry->flags,
++ __print_flags(__entry->flags, "|", INODE_DIRTY_FLAGS)
++ )
++);
++
+ #endif /* _TRACE_WRITEBACK_H */
+
+ /* This part must be outside protection */
diff --git a/patches/linux-3.15-rc3-ahci-alpm-with-devslp-accounting.patch b/patches/linux-3.15-rc3-ahci-alpm-with-devslp-accounting.patch
new file mode 100644
index 0000000..254f58b
--- /dev/null
+++ b/patches/linux-3.15-rc3-ahci-alpm-with-devslp-accounting.patch
@@ -0,0 +1,340 @@
+From 9022555b1fc7c7a71adf3a0871ba3609fc2f4bc0 Mon Sep 17 00:00:00 2001
+From: David Woodhouse <dwmw2@infradead.org>
+Date: Mon, 1 Apr 2013 20:53:07 +0100
+Subject: [PATCH] Updated PowerTOP AHCI ALPM accounting for Device Sleep.
+
+This patch applies to v3.7 onwards (including 3.9-rc4), and adds devslp
+support to the AHCI state accounting. It's based on the patch at
+https://raw.github.com/fenrus75/powertop/master/patches/linux-3.3.0-ahci-alpm-accounting.patch
+
+From: Arjan van de Ven <arjan@linux.intel.com>
+Subject: libata: Add ALPM power state accounting to the AHCI driver
+
+PowerTOP wants to be able to show the user how effective the ALPM link
+power management is for the user. ALPM is worth around 0.5W on a quiet
+link; PowerTOP wants to be able to find cases where the "quiet link" isn't
+actually quiet.
+
+This patch adds state accounting functionality to the AHCI driver for
+PowerTOP to use.
+The parts of the patch are
+1) the sysfs logic of exposing the stats for each state in sysfs
+2) the basic accounting logic that gets update on link change interrupts
+ (or when the user accesses the info from sysfs)
+3) a "accounting enable" flag; in order to get the accounting to work,
+ the driver needs to get phyrdy interrupts on link status changes.
+ Normally and currently this is disabled by the driver when ALPM is
+ on (to reduce overhead); when PowerTOP is running this will need
+ to be on to get usable statistics... hence the sysfs tunable.
+
+The PowerTOP output currently looks like this:
+
+Recent SATA AHCI link activity statistics
+Active Partial Slumber Device name
+ 0.5% 99.5% 0.0% host0
+
+(work to resolve "host0" to a more human readable name is in progress)
+
+Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
+Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
+Signed-off-by: David E. Box <david.e.box@linux.intel.com>
+---
+ drivers/ata/ahci.h | 17 ++++
+ drivers/ata/libahci.c | 211 ++++++++++++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 226 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
+index 2289efd..7a80e34 100644
+--- a/drivers/ata/ahci.h
++++ b/drivers/ata/ahci.h
+@@ -286,6 +286,14 @@ struct ahci_em_priv {
+ unsigned long led_state;
+ };
+
++enum ahci_port_states {
++ AHCI_PORT_NOLINK = 0,
++ AHCI_PORT_ACTIVE = 1,
++ AHCI_PORT_PARTIAL = 2,
++ AHCI_PORT_SLUMBER = 3,
++ AHCI_PORT_DEVSLP = 4
++};
++
+ struct ahci_port_priv {
+ struct ata_link *active_link;
+ struct ahci_cmd_hdr *cmd_slot;
+@@ -307,6 +315,15 @@ struct ahci_port_priv {
+ /* enclosure management info per PM slot */
+ struct ahci_em_priv em_priv[EM_MAX_SLOTS];
+ char *irq_desc; /* desc in /proc/interrupts */
++
++ /* ALPM accounting state and stats */
++ unsigned int accounting_active:1;
++ u64 active_jiffies;
++ u64 partial_jiffies;
++ u64 slumber_jiffies;
++ u64 devslp_jiffies;
++ int previous_state;
++ int previous_jiffies;
+ };
+
+ struct ahci_host_priv {
+diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
+index 36605ab..4e69272 100644
+--- a/drivers/ata/libahci.c
++++ b/drivers/ata/libahci.c
+@@ -99,6 +99,19 @@ static ssize_t ahci_activity_store(struct ata_device *dev,
+ enum sw_activity val);
+ static void ahci_init_sw_activity(struct ata_link *link);
+
++static ssize_t ahci_alpm_show_active(struct device *dev,
++ struct device_attribute *attr, char *buf);
++static ssize_t ahci_alpm_show_slumber(struct device *dev,
++ struct device_attribute *attr, char *buf);
++static ssize_t ahci_alpm_show_devslp(struct device *dev,
++ struct device_attribute *attr, char *buf);
++static ssize_t ahci_alpm_show_partial(struct device *dev,
++ struct device_attribute *attr, char *buf);
++static ssize_t ahci_alpm_show_accounting(struct device *dev,
++ struct device_attribute *attr, char *buf);
++static ssize_t ahci_alpm_set_accounting(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count);
+ static ssize_t ahci_show_host_caps(struct device *dev,
+ struct device_attribute *attr, char *buf);
+ static ssize_t ahci_show_host_cap2(struct device *dev,
+@@ -119,6 +132,13 @@ static DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL);
+ static DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL);
+ static DEVICE_ATTR(ahci_host_version, S_IRUGO, ahci_show_host_version, NULL);
+ static DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL);
++static DEVICE_ATTR(ahci_alpm_active, S_IRUGO, ahci_alpm_show_active, NULL);
++static DEVICE_ATTR(ahci_alpm_partial, S_IRUGO, ahci_alpm_show_partial, NULL);
++static DEVICE_ATTR(ahci_alpm_slumber, S_IRUGO, ahci_alpm_show_slumber, NULL);
++static DEVICE_ATTR(ahci_alpm_devslp, S_IRUGO, ahci_alpm_show_devslp, NULL);
++static DEVICE_ATTR(ahci_alpm_accounting, S_IRUGO | S_IWUSR,
++ ahci_alpm_show_accounting, ahci_alpm_set_accounting);
++
+ static DEVICE_ATTR(em_buffer, S_IWUSR | S_IRUGO,
+ ahci_read_em_buffer, ahci_store_em_buffer);
+ static DEVICE_ATTR(em_message_supported, S_IRUGO, ahci_show_em_supported, NULL);
+@@ -131,6 +151,11 @@ struct device_attribute *ahci_shost_attrs[] = {
+ &dev_attr_ahci_host_cap2,
+ &dev_attr_ahci_host_version,
+ &dev_attr_ahci_port_cmd,
++ &dev_attr_ahci_alpm_active,
++ &dev_attr_ahci_alpm_partial,
++ &dev_attr_ahci_alpm_slumber,
++ &dev_attr_ahci_alpm_devslp,
++ &dev_attr_ahci_alpm_accounting,
+ &dev_attr_em_buffer,
+ &dev_attr_em_message_supported,
+ NULL
+@@ -225,6 +250,182 @@ static void ahci_enable_ahci(void __iomem *mmio)
+ WARN_ON(1);
+ }
+
++static int get_current_alpm_state(struct ata_port *ap)
++{
++ u32 status = 0;
++
++ ahci_scr_read(&ap->link, SCR_STATUS, &status);
++
++ /* link status is in bits 11-8 */
++ status = status >> 8;
++ status = status & 0xf;
++
++ if (status == 8)
++ return AHCI_PORT_DEVSLP;
++ if (status == 6)
++ return AHCI_PORT_SLUMBER;
++ if (status == 2)
++ return AHCI_PORT_PARTIAL;
++ if (status == 1)
++ return AHCI_PORT_ACTIVE;
++ return AHCI_PORT_NOLINK;
++}
++
++static void account_alpm_stats(struct ata_port *ap)
++{
++ struct ahci_port_priv *pp;
++
++ int new_state;
++ u64 new_jiffies, jiffies_delta;
++
++ if (ap == NULL)
++ return;
++ pp = ap->private_data;
++
++ if (!pp) return;
++
++ new_state = get_current_alpm_state(ap);
++ new_jiffies = jiffies;
++
++ jiffies_delta = new_jiffies - pp->previous_jiffies;
++
++ switch (pp->previous_state) {
++ case AHCI_PORT_NOLINK:
++ pp->active_jiffies = 0;
++ pp->partial_jiffies = 0;
++ pp->slumber_jiffies = 0;
++ break;
++ case AHCI_PORT_ACTIVE:
++ pp->active_jiffies += jiffies_delta;
++ break;
++ case AHCI_PORT_PARTIAL:
++ pp->partial_jiffies += jiffies_delta;
++ break;
++ case AHCI_PORT_SLUMBER:
++ pp->slumber_jiffies += jiffies_delta;
++ break;
++ case AHCI_PORT_DEVSLP:
++ pp->devslp_jiffies += jiffies_delta;
++ break;
++ default:
++ break;
++ }
++ pp->previous_state = new_state;
++ pp->previous_jiffies = new_jiffies;
++}
++
++static ssize_t ahci_alpm_show_active(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *shost = class_to_shost(dev);
++ struct ata_port *ap = ata_shost_to_port(shost);
++ struct ahci_port_priv *pp;
++
++ if (!ap || ata_port_is_dummy(ap))
++ return -EINVAL;
++
++ pp = ap->private_data;
++ account_alpm_stats(ap);
++
++ return sprintf(buf, "%u\n", jiffies_to_msecs(pp->active_jiffies));
++}
++
++static ssize_t ahci_alpm_show_partial(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *shost = class_to_shost(dev);
++ struct ata_port *ap = ata_shost_to_port(shost);
++ struct ahci_port_priv *pp;
++
++ if (!ap || ata_port_is_dummy(ap))
++ return -EINVAL;
++
++ pp = ap->private_data;
++ account_alpm_stats(ap);
++
++ return sprintf(buf, "%u\n", jiffies_to_msecs(pp->partial_jiffies));
++}
++
++static ssize_t ahci_alpm_show_slumber(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *shost = class_to_shost(dev);
++ struct ata_port *ap = ata_shost_to_port(shost);
++ struct ahci_port_priv *pp;
++
++ if (!ap || ata_port_is_dummy(ap))
++ return -EINVAL;
++
++ pp = ap->private_data;
++ account_alpm_stats(ap);
++
++ return sprintf(buf, "%u\n", jiffies_to_msecs(pp->slumber_jiffies));
++}
++
++static ssize_t ahci_alpm_show_devslp(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *shost = class_to_shost(dev);
++ struct ata_port *ap = ata_shost_to_port(shost);
++ struct ahci_port_priv *pp;
++
++ if (!ap || ata_port_is_dummy(ap))
++ return -EINVAL;
++
++ pp = ap->private_data;
++ account_alpm_stats(ap);
++
++ return sprintf(buf, "%u\n", jiffies_to_msecs(pp->devslp_jiffies));
++}
++
++static ssize_t ahci_alpm_show_accounting(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *shost = class_to_shost(dev);
++ struct ata_port *ap = ata_shost_to_port(shost);
++ struct ahci_port_priv *pp;
++
++ if (!ap || ata_port_is_dummy(ap))
++ return -EINVAL;
++
++ pp = ap->private_data;
++
++ return sprintf(buf, "%u\n", pp->accounting_active);
++}
++
++static ssize_t ahci_alpm_set_accounting(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ unsigned long flags;
++ struct Scsi_Host *shost = class_to_shost(dev);
++ struct ata_port *ap = ata_shost_to_port(shost);
++ struct ahci_port_priv *pp;
++ void __iomem *port_mmio;
++
++ if (!ap || ata_port_is_dummy(ap))
++ return 1;
++
++ pp = ap->private_data;
++ port_mmio = ahci_port_base(ap);
++
++ if (!pp)
++ return 1;
++ if (buf[0] == '0')
++ pp->accounting_active = 0;
++ if (buf[0] == '1')
++ pp->accounting_active = 1;
++
++ /* we need to enable the PHYRDY interrupt when we want accounting */
++ if (pp->accounting_active) {
++ spin_lock_irqsave(ap->lock, flags);
++ pp->intr_mask |= PORT_IRQ_PHYRDY;
++ writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
++ spin_unlock_irqrestore(ap->lock, flags);
++ }
++ return count;
++}
++
+ static ssize_t ahci_show_host_caps(struct device *dev,
+ struct device_attribute *attr, char *buf)
+ {
+@@ -680,9 +881,14 @@ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+ * Disable interrupts on Phy Ready. This keeps us from
+ * getting woken up due to spurious phy ready
+ * interrupts.
++ *
++ * However, when accounting_active is set, we do want
++ * the interrupts for accounting purposes.
+ */
+- pp->intr_mask &= ~PORT_IRQ_PHYRDY;
+- writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
++ if (!pp->accounting_active) {
++ pp->intr_mask &= ~PORT_IRQ_PHYRDY;
++ writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
++ }
+
+ sata_link_scr_lpm(link, policy, false);
+ }
+@@ -1696,6 +1902,7 @@ static void ahci_handle_port_interrupt(struct ata_port *ap,
+ /* if LPM is enabled, PHYRDY doesn't mean anything */
+ if (ap->link.lpm_policy > ATA_LPM_MAX_POWER) {
+ status &= ~PORT_IRQ_PHYRDY;
++ account_alpm_stats(ap);
+ ahci_scr_write(&ap->link, SCR_ERROR, SERR_PHYRDY_CHG);
+ }
+
+--
+1.7.10.4
diff --git a/patches/linux-3.3.0-ahci-alpm-accounting.patch b/patches/linux-3.3.0-ahci-alpm-accounting.patch
new file mode 100644
index 0000000..8b2f892
--- /dev/null
+++ b/patches/linux-3.3.0-ahci-alpm-accounting.patch
@@ -0,0 +1,307 @@
+From 3d1f00627a8db9d71091db32cd8109962f69ec43 Mon Sep 17 00:00:00 2001
+From: Arjan van de Ven <arjan at linux.intel.com>
+Date: Sat, 31 Mar 2012 20:35:12 +0200
+Subject: [PATCH 2/2] libata: Add ALPM power state accounting to the AHCI
+ driver
+
+PowerTOP wants to be able to show the user how effective the ALPM link
+power management is for the user. ALPM is worth around 0.5W on a quiet
+link; PowerTOP wants to be able to find cases where the "quiet link" isn't
+actually quiet.
+
+This patch adds state accounting functionality to the AHCI driver for
+PowerTOP to use.
+The parts of the patch are
+1) the sysfs logic of exposing the stats for each state in sysfs
+2) the basic accounting logic that gets update on link change interrupts
+ (or when the user accesses the info from sysfs)
+3) a "accounting enable" flag; in order to get the accounting to work,
+ the driver needs to get phyrdy interrupts on link status changes.
+ Normally and currently this is disabled by the driver when ALPM is
+ on (to reduce overhead); when PowerTOP is running this will need
+ to be on to get usable statistics... hence the sysfs tunable.
+
+The PowerTOP output currently looks like this:
+
+Recent SATA AHCI link activity statistics
+Active Partial Slumber Device name
+ 0.5% 99.5% 0.0% host0
+
+(work to resolve "host0" to a more human readable name is in progress)
+
+Signed-off-by: Arjan van de Ven <arjan at linux.intel.com>
+---
+ drivers/ata/ahci.h | 15 ++++
+ drivers/ata/libahci.c | 187 ++++++++++++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 200 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
+index b175000..38297f9 100644
+--- a/drivers/ata/ahci.h
++++ b/drivers/ata/ahci.h
+@@ -264,6 +264,13 @@ struct ahci_em_priv {
+ unsigned long led_state;
+ };
+
++enum ahci_port_states {
++ AHCI_PORT_NOLINK = 0,
++ AHCI_PORT_ACTIVE = 1,
++ AHCI_PORT_PARTIAL = 2,
++ AHCI_PORT_SLUMBER = 3
++};
++
+ struct ahci_port_priv {
+ struct ata_link *active_link;
+ struct ahci_cmd_hdr *cmd_slot;
+@@ -282,6 +289,14 @@ struct ahci_port_priv {
+ int fbs_last_dev; /* save FBS.DEV of last FIS */
+ /* enclosure management info per PM slot */
+ struct ahci_em_priv em_priv[EM_MAX_SLOTS];
++
++ /* ALPM accounting state and stats */
++ unsigned int accounting_active:1;
++ u64 active_jiffies;
++ u64 partial_jiffies;
++ u64 slumber_jiffies;
++ int previous_state;
++ int previous_jiffies;
+ };
+
+ struct ahci_host_priv {
+diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
+index a72bfd0..5859215 100644
+--- a/drivers/ata/libahci.c
++++ b/drivers/ata/libahci.c
+@@ -58,6 +58,17 @@ MODULE_PARM_DESC(ignore_sss, "Ignore staggered spinup flag (0=don't ignore, 1=ig
+
+ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+ unsigned hints);
++static ssize_t ahci_alpm_show_active(struct device *dev,
++ struct device_attribute *attr, char *buf);
++static ssize_t ahci_alpm_show_slumber(struct device *dev,
++ struct device_attribute *attr, char *buf);
++static ssize_t ahci_alpm_show_partial(struct device *dev,
++ struct device_attribute *attr, char *buf);
++static ssize_t ahci_alpm_show_accounting(struct device *dev,
++ struct device_attribute *attr, char *buf);
++static ssize_t ahci_alpm_set_accounting(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count);
+ static ssize_t ahci_led_show(struct ata_port *ap, char *buf);
+ static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
+ size_t size);
+@@ -118,6 +129,12 @@ static DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL);
+ static DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL);
+ static DEVICE_ATTR(ahci_host_version, S_IRUGO, ahci_show_host_version, NULL);
+ static DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL);
++static DEVICE_ATTR(ahci_alpm_active, S_IRUGO, ahci_alpm_show_active, NULL);
++static DEVICE_ATTR(ahci_alpm_partial, S_IRUGO, ahci_alpm_show_partial, NULL);
++static DEVICE_ATTR(ahci_alpm_slumber, S_IRUGO, ahci_alpm_show_slumber, NULL);
++static DEVICE_ATTR(ahci_alpm_accounting, S_IRUGO | S_IWUSR,
++ ahci_alpm_show_accounting, ahci_alpm_set_accounting);
++
+ static DEVICE_ATTR(em_buffer, S_IWUSR | S_IRUGO,
+ ahci_read_em_buffer, ahci_store_em_buffer);
+ static DEVICE_ATTR(em_message_supported, S_IRUGO, ahci_show_em_supported, NULL);
+@@ -130,6 +147,10 @@ struct device_attribute *ahci_shost_attrs[] = {
+ &dev_attr_ahci_host_cap2,
+ &dev_attr_ahci_host_version,
+ &dev_attr_ahci_port_cmd,
++ &dev_attr_ahci_alpm_active,
++ &dev_attr_ahci_alpm_partial,
++ &dev_attr_ahci_alpm_slumber,
++ &dev_attr_ahci_alpm_accounting,
+ &dev_attr_em_buffer,
+ &dev_attr_em_message_supported,
+ NULL
+@@ -673,9 +694,14 @@ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+ * Disable interrupts on Phy Ready. This keeps us from
+ * getting woken up due to spurious phy ready
+ * interrupts.
++ *
++ * However, when accounting_active is set, we do want
++ * the interrupts for accounting purposes.
+ */
+- pp->intr_mask &= ~PORT_IRQ_PHYRDY;
+- writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
++ if (!pp->accounting_active) {
++ pp->intr_mask &= ~PORT_IRQ_PHYRDY;
++ writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
++ }
+
+ sata_link_scr_lpm(link, policy, false);
+ }
+@@ -1633,6 +1659,162 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
+ ata_port_abort(ap);
+ }
+
++static int get_current_alpm_state(struct ata_port *ap)
++{
++ u32 status = 0;
++
++ ahci_scr_read(&ap->link, SCR_STATUS, &status);
++
++ /* link status is in bits 11-8 */
++ status = status >> 8;
++ status = status & 0x7;
++
++ if (status == 6)
++ return AHCI_PORT_SLUMBER;
++ if (status == 2)
++ return AHCI_PORT_PARTIAL;
++ if (status == 1)
++ return AHCI_PORT_ACTIVE;
++ return AHCI_PORT_NOLINK;
++}
++
++static void account_alpm_stats(struct ata_port *ap)
++{
++ struct ahci_port_priv *pp;
++
++ int new_state;
++ u64 new_jiffies, jiffies_delta;
++
++ if (ap == NULL)
++ return;
++ pp = ap->private_data;
++
++ if (!pp) return;
++
++ new_state = get_current_alpm_state(ap);
++ new_jiffies = jiffies;
++
++ jiffies_delta = new_jiffies - pp->previous_jiffies;
++
++ switch (pp->previous_state) {
++ case AHCI_PORT_NOLINK:
++ pp->active_jiffies = 0;
++ pp->partial_jiffies = 0;
++ pp->slumber_jiffies = 0;
++ break;
++ case AHCI_PORT_ACTIVE:
++ pp->active_jiffies += jiffies_delta;
++ break;
++ case AHCI_PORT_PARTIAL:
++ pp->partial_jiffies += jiffies_delta;
++ break;
++ case AHCI_PORT_SLUMBER:
++ pp->slumber_jiffies += jiffies_delta;
++ break;
++ default:
++ break;
++ }
++ pp->previous_state = new_state;
++ pp->previous_jiffies = new_jiffies;
++}
++
++static ssize_t ahci_alpm_show_active(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *shost = class_to_shost(dev);
++ struct ata_port *ap = ata_shost_to_port(shost);
++ struct ahci_port_priv *pp;
++
++ if (!ap || ata_port_is_dummy(ap))
++ return -EINVAL;
++ pp = ap->private_data;
++ account_alpm_stats(ap);
++
++ return sprintf(buf, "%u\n", jiffies_to_msecs(pp->active_jiffies));
++}
++
++static ssize_t ahci_alpm_show_partial(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *shost = class_to_shost(dev);
++ struct ata_port *ap = ata_shost_to_port(shost);
++ struct ahci_port_priv *pp;
++
++ if (!ap || ata_port_is_dummy(ap))
++ return -EINVAL;
++
++ pp = ap->private_data;
++ account_alpm_stats(ap);
++
++ return sprintf(buf, "%u\n", jiffies_to_msecs(pp->partial_jiffies));
++}
++
++static ssize_t ahci_alpm_show_slumber(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *shost = class_to_shost(dev);
++ struct ata_port *ap = ata_shost_to_port(shost);
++ struct ahci_port_priv *pp;
++
++ if (!ap || ata_port_is_dummy(ap))
++ return -EINVAL;
++
++ pp = ap->private_data;
++
++ account_alpm_stats(ap);
++
++ return sprintf(buf, "%u\n", jiffies_to_msecs(pp->slumber_jiffies));
++}
++
++static ssize_t ahci_alpm_show_accounting(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *shost = class_to_shost(dev);
++ struct ata_port *ap = ata_shost_to_port(shost);
++ struct ahci_port_priv *pp;
++
++ if (!ap || ata_port_is_dummy(ap))
++ return -EINVAL;
++
++ pp = ap->private_data;
++
++ return sprintf(buf, "%u\n", pp->accounting_active);
++}
++
++static ssize_t ahci_alpm_set_accounting(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ unsigned long flags;
++ struct Scsi_Host *shost = class_to_shost(dev);
++ struct ata_port *ap = ata_shost_to_port(shost);
++ struct ahci_port_priv *pp;
++ void __iomem *port_mmio;
++
++ if (!ap || ata_port_is_dummy(ap))
++ return 1;
++
++ pp = ap->private_data;
++ port_mmio = ahci_port_base(ap);
++
++ if (!pp)
++ return 1;
++ if (buf[0] == '0')
++ pp->accounting_active = 0;
++ if (buf[0] == '1')
++ pp->accounting_active = 1;
++
++ /* we need to enable the PHYRDY interrupt when we want accounting */
++ if (pp->accounting_active) {
++ spin_lock_irqsave(ap->lock, flags);
++ pp->intr_mask |= PORT_IRQ_PHYRDY;
++ writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
++ spin_unlock_irqrestore(ap->lock, flags);
++ }
++ return count;
++}
++
++
+ static void ahci_port_intr(struct ata_port *ap)
+ {
+ void __iomem *port_mmio = ahci_port_base(ap);
+@@ -1653,6 +1835,7 @@ static void ahci_port_intr(struct ata_port *ap)
+ /* if LPM is enabled, PHYRDY doesn't mean anything */
+ if (ap->link.lpm_policy > ATA_LPM_MAX_POWER) {
+ status &= ~PORT_IRQ_PHYRDY;
++ account_alpm_stats(ap);
+ ahci_scr_write(&ap->link, SCR_ERROR, SERR_PHYRDY_CHG);
+ }
+
+--
+1.7.8.5
+
diff --git a/patches/linux-3.3.0-vfs-dirty-inode.patch b/patches/linux-3.3.0-vfs-dirty-inode.patch
new file mode 100644
index 0000000..4177093
--- /dev/null
+++ b/patches/linux-3.3.0-vfs-dirty-inode.patch
@@ -0,0 +1,103 @@
+From 9f7c5d04fdee46dbe715f2758152bb1664d4259c Mon Sep 17 00:00:00 2001
+From: Arjan van de Ven <arjan at linux.intel.com>
+Date: Fri, 26 Nov 2010 12:18:03 -0800
+Subject: [PATCH 1/2] vfs: Add a trace point in the mark_inode_dirty function
+
+PowerTOP would like to be able to show who is keeping the disk
+busy by dirtying data. The most logical spot for this is in the vfs
+in the mark_inode_dirty() function, doing this on the block level
+is not possible because by the time the IO hits the block layer the
+guilty party can no longer be found ("kjournald" and "pdflush" are not
+useful answers to "who caused this file to be dirty).
+
+The trace point follows the same logic/style as the block_dump code
+and pretty much dumps the same data, just not to dmesg (and thus to
+/var/log/messages) but via the trace events streams.
+
+Eventually we should be able to phase out the block dump code, but that's
+for later on after a transition time.
+---
+ fs/fs-writeback.c | 3 +++
+ include/linux/fs.h | 11 +++++++++++
+ include/trace/events/writeback.h | 28 ++++++++++++++++++++++++++++
+ 3 files changed, 42 insertions(+), 0 deletions(-)
+
+diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
+index 5b4a936..5ef5bb0 100644
+--- a/fs/fs-writeback.c
++++ b/fs/fs-writeback.c
+@@ -1081,6 +1081,9 @@ void __mark_inode_dirty(struct inode *inode, int flags)
+ if ((inode->i_state & flags) == flags)
+ return;
+
++ if (flags & (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES))
++ trace_writeback_inode_dirty(inode, flags);
++
+ if (unlikely(block_dump))
+ block_dump___mark_inode_dirty(inode);
+
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index 69cd5bb..e0ac37c 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -1768,6 +1768,18 @@ struct super_operations {
+
+ #define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES)
+
++#define INODE_DIRTY_FLAGS \
++ { I_DIRTY_SYNC, "DIRTY-SYNC" }, \
++ { I_DIRTY_DATASYNC, "DIRTY-DATASYNC" }, \
++ { I_DIRTY_PAGES, "DIRTY-PAGES" }, \
++ { I_NEW, "NEW" }, \
++ { I_WILL_FREE, "WILL-FREE" }, \
++ { I_FREEING, "FREEING" }, \
++ { I_CLEAR, "CLEAR" }, \
++ { I_SYNC, "SYNC" }, \
++ { I_REFERENCED, "REFERENCED" }
++
++
+ extern void __mark_inode_dirty(struct inode *, int);
+ static inline void mark_inode_dirty(struct inode *inode)
+ {
+diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h
+index 5973410..5f1e2a3 100644
+--- a/include/trace/events/writeback.h
++++ b/include/trace/events/writeback.h
+@@ -408,6 +408,34 @@ DEFINE_EVENT(writeback_congest_waited_template, writeback_wait_iff_congested,
+ TP_ARGS(usec_timeout, usec_delayed)
+ );
+
++/*
++ * Tracepoint for dirtying an inode; used by PowerTOP
++ */
++TRACE_EVENT(writeback_inode_dirty,
++
++ TP_PROTO(struct inode *inode, int flags),
++
++ TP_ARGS(inode, flags),
++
++ TP_STRUCT__entry(
++ __field( __kernel_dev_t, dev )
++ __field( ino_t, ino )
++ __field( u32, flags )
++ ),
++
++ TP_fast_assign(
++ __entry->dev = inode->i_sb->s_dev;
++ __entry->ino = inode->i_ino;
++ __entry->flags = flags;
++ ),
++
++ TP_printk("dev %d:%d ino %lu flags %d %s", MAJOR(__entry->dev), MINOR(__entry->dev),
++ (unsigned long) __entry->ino,
++ __entry->flags,
++ __print_flags(__entry->flags, "|", INODE_DIRTY_FLAGS)
++ )
++);
++
+ DECLARE_EVENT_CLASS(writeback_single_inode_template,
+
+ TP_PROTO(struct inode *inode,
+--
+1.7.8.5
+
diff --git a/patches/linux-3.9.0-ahci-alpm-accounting.patch b/patches/linux-3.9.0-ahci-alpm-accounting.patch
new file mode 100644
index 0000000..e7d8df6
--- /dev/null
+++ b/patches/linux-3.9.0-ahci-alpm-accounting.patch
@@ -0,0 +1,306 @@
+From 9abcb86b6dffd17a90e841e8ae3ddd1a841f2feb Mon Sep 17 00:00:00 2001
+From: Arjan van de Ven <arjan at linux.intel.com>
+Date: Sat, 31 Mar 2012 20:35:12 +0200
+Subject: [PATCH] libata: Add ALPM power state accounting to the AHCI driver
+
+PowerTOP wants to be able to show the user how effective the ALPM link
+power management is for the user. ALPM is worth around 0.5W on a quiet
+link; PowerTOP wants to be able to find cases where the "quiet link" isn't
+actually quiet.
+
+This patch adds state accounting functionality to the AHCI driver for
+PowerTOP to use.
+The parts of the patch are
+1) the sysfs logic of exposing the stats for each state in sysfs
+2) the basic accounting logic that gets update on link change interrupts
+ (or when the user accesses the info from sysfs)
+3) a "accounting enable" flag; in order to get the accounting to work,
+ the driver needs to get phyrdy interrupts on link status changes.
+ Normally and currently this is disabled by the driver when ALPM is
+ on (to reduce overhead); when PowerTOP is running this will need
+ to be on to get usable statistics... hence the sysfs tunable.
+
+The PowerTOP output currently looks like this:
+
+Recent SATA AHCI link activity statistics
+Active Partial Slumber Device name
+ 0.5% 99.5% 0.0% host0
+
+(work to resolve "host0" to a more human readable name is in progress)
+
+Signed-off-by: Arjan van de Ven <arjan at linux.intel.com>
+---
+ drivers/ata/ahci.h | 15 ++++
+ drivers/ata/libahci.c | 187 +++++++++++++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 200 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
+index b830e6c..b7075da 100644
+--- a/drivers/ata/ahci.h
++++ b/drivers/ata/ahci.h
+@@ -286,6 +286,13 @@ struct ahci_em_priv {
+ unsigned long led_state;
+ };
+
++enum ahci_port_states {
++ AHCI_PORT_NOLINK = 0,
++ AHCI_PORT_ACTIVE = 1,
++ AHCI_PORT_PARTIAL = 2,
++ AHCI_PORT_SLUMBER = 3
++};
++
+ struct ahci_port_priv {
+ struct ata_link *active_link;
+ struct ahci_cmd_hdr *cmd_slot;
+@@ -306,6 +313,14 @@ struct ahci_port_priv {
+ int fbs_last_dev; /* save FBS.DEV of last FIS */
+ /* enclosure management info per PM slot */
+ struct ahci_em_priv em_priv[EM_MAX_SLOTS];
++
++ /* ALPM accounting state and stats */
++ unsigned int accounting_active:1;
++ u64 active_jiffies;
++ u64 partial_jiffies;
++ u64 slumber_jiffies;
++ int previous_state;
++ int previous_jiffies;
+ };
+
+ struct ahci_host_priv {
+diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
+index 34c8216..cf0d61d 100644
+--- a/drivers/ata/libahci.c
++++ b/drivers/ata/libahci.c
+@@ -59,6 +59,17 @@ MODULE_PARM_DESC(ignore_sss, "Ignore staggered spinup flag (0=don't ignore, 1=ig
+
+ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+ unsigned hints);
++static ssize_t ahci_alpm_show_active(struct device *dev,
++ struct device_attribute *attr, char *buf);
++static ssize_t ahci_alpm_show_slumber(struct device *dev,
++ struct device_attribute *attr, char *buf);
++static ssize_t ahci_alpm_show_partial(struct device *dev,
++ struct device_attribute *attr, char *buf);
++static ssize_t ahci_alpm_show_accounting(struct device *dev,
++ struct device_attribute *attr, char *buf);
++static ssize_t ahci_alpm_set_accounting(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count);
+ static ssize_t ahci_led_show(struct ata_port *ap, char *buf);
+ static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
+ size_t size);
+@@ -120,6 +131,12 @@ static DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL);
+ static DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL);
+ static DEVICE_ATTR(ahci_host_version, S_IRUGO, ahci_show_host_version, NULL);
+ static DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL);
++static DEVICE_ATTR(ahci_alpm_active, S_IRUGO, ahci_alpm_show_active, NULL);
++static DEVICE_ATTR(ahci_alpm_partial, S_IRUGO, ahci_alpm_show_partial, NULL);
++static DEVICE_ATTR(ahci_alpm_slumber, S_IRUGO, ahci_alpm_show_slumber, NULL);
++static DEVICE_ATTR(ahci_alpm_accounting, S_IRUGO | S_IWUSR,
++ ahci_alpm_show_accounting, ahci_alpm_set_accounting);
++
+ static DEVICE_ATTR(em_buffer, S_IWUSR | S_IRUGO,
+ ahci_read_em_buffer, ahci_store_em_buffer);
+ static DEVICE_ATTR(em_message_supported, S_IRUGO, ahci_show_em_supported, NULL);
+@@ -132,6 +149,10 @@ struct device_attribute *ahci_shost_attrs[] = {
+ &dev_attr_ahci_host_cap2,
+ &dev_attr_ahci_host_version,
+ &dev_attr_ahci_port_cmd,
++ &dev_attr_ahci_alpm_active,
++ &dev_attr_ahci_alpm_partial,
++ &dev_attr_ahci_alpm_slumber,
++ &dev_attr_ahci_alpm_accounting,
+ &dev_attr_em_buffer,
+ &dev_attr_em_message_supported,
+ NULL
+@@ -679,9 +700,14 @@ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+ * Disable interrupts on Phy Ready. This keeps us from
+ * getting woken up due to spurious phy ready
+ * interrupts.
++ *
++ * However, when accounting_active is set, we do want
++ * the interrupts for accounting purposes.
+ */
+- pp->intr_mask &= ~PORT_IRQ_PHYRDY;
+- writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
++ if (!pp->accounting_active) {
++ pp->intr_mask &= ~PORT_IRQ_PHYRDY;
++ writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
++ }
+
+ sata_link_scr_lpm(link, policy, false);
+ }
+@@ -1655,6 +1681,162 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
+ ata_port_abort(ap);
+ }
+
++static int get_current_alpm_state(struct ata_port *ap)
++{
++ u32 status = 0;
++
++ ahci_scr_read(&ap->link, SCR_STATUS, &status);
++
++ /* link status is in bits 11-8 */
++ status = status >> 8;
++ status = status & 0x7;
++
++ if (status == 6)
++ return AHCI_PORT_SLUMBER;
++ if (status == 2)
++ return AHCI_PORT_PARTIAL;
++ if (status == 1)
++ return AHCI_PORT_ACTIVE;
++ return AHCI_PORT_NOLINK;
++}
++
++static void account_alpm_stats(struct ata_port *ap)
++{
++ struct ahci_port_priv *pp;
++
++ int new_state;
++ u64 new_jiffies, jiffies_delta;
++
++ if (ap == NULL)
++ return;
++ pp = ap->private_data;
++
++ if (!pp) return;
++
++ new_state = get_current_alpm_state(ap);
++ new_jiffies = jiffies;
++
++ jiffies_delta = new_jiffies - pp->previous_jiffies;
++
++ switch (pp->previous_state) {
++ case AHCI_PORT_NOLINK:
++ pp->active_jiffies = 0;
++ pp->partial_jiffies = 0;
++ pp->slumber_jiffies = 0;
++ break;
++ case AHCI_PORT_ACTIVE:
++ pp->active_jiffies += jiffies_delta;
++ break;
++ case AHCI_PORT_PARTIAL:
++ pp->partial_jiffies += jiffies_delta;
++ break;
++ case AHCI_PORT_SLUMBER:
++ pp->slumber_jiffies += jiffies_delta;
++ break;
++ default:
++ break;
++ }
++ pp->previous_state = new_state;
++ pp->previous_jiffies = new_jiffies;
++}
++
++static ssize_t ahci_alpm_show_active(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *shost = class_to_shost(dev);
++ struct ata_port *ap = ata_shost_to_port(shost);
++ struct ahci_port_priv *pp;
++
++ if (!ap || ata_port_is_dummy(ap))
++ return -EINVAL;
++ pp = ap->private_data;
++ account_alpm_stats(ap);
++
++ return sprintf(buf, "%u\n", jiffies_to_msecs(pp->active_jiffies));
++}
++
++static ssize_t ahci_alpm_show_partial(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *shost = class_to_shost(dev);
++ struct ata_port *ap = ata_shost_to_port(shost);
++ struct ahci_port_priv *pp;
++
++ if (!ap || ata_port_is_dummy(ap))
++ return -EINVAL;
++
++ pp = ap->private_data;
++ account_alpm_stats(ap);
++
++ return sprintf(buf, "%u\n", jiffies_to_msecs(pp->partial_jiffies));
++}
++
++static ssize_t ahci_alpm_show_slumber(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *shost = class_to_shost(dev);
++ struct ata_port *ap = ata_shost_to_port(shost);
++ struct ahci_port_priv *pp;
++
++ if (!ap || ata_port_is_dummy(ap))
++ return -EINVAL;
++
++ pp = ap->private_data;
++
++ account_alpm_stats(ap);
++
++ return sprintf(buf, "%u\n", jiffies_to_msecs(pp->slumber_jiffies));
++}
++
++static ssize_t ahci_alpm_show_accounting(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *shost = class_to_shost(dev);
++ struct ata_port *ap = ata_shost_to_port(shost);
++ struct ahci_port_priv *pp;
++
++ if (!ap || ata_port_is_dummy(ap))
++ return -EINVAL;
++
++ pp = ap->private_data;
++
++ return sprintf(buf, "%u\n", pp->accounting_active);
++}
++
++static ssize_t ahci_alpm_set_accounting(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ unsigned long flags;
++ struct Scsi_Host *shost = class_to_shost(dev);
++ struct ata_port *ap = ata_shost_to_port(shost);
++ struct ahci_port_priv *pp;
++ void __iomem *port_mmio;
++
++ if (!ap || ata_port_is_dummy(ap))
++ return 1;
++
++ pp = ap->private_data;
++ port_mmio = ahci_port_base(ap);
++
++ if (!pp)
++ return 1;
++ if (buf[0] == '0')
++ pp->accounting_active = 0;
++ if (buf[0] == '1')
++ pp->accounting_active = 1;
++
++ /* we need to enable the PHYRDY interrupt when we want accounting */
++ if (pp->accounting_active) {
++ spin_lock_irqsave(ap->lock, flags);
++ pp->intr_mask |= PORT_IRQ_PHYRDY;
++ writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
++ spin_unlock_irqrestore(ap->lock, flags);
++ }
++ return count;
++}
++
++
+ static void ahci_handle_port_interrupt(struct ata_port *ap,
+ void __iomem *port_mmio, u32 status)
+ {
+@@ -1672,6 +1854,7 @@ static void ahci_handle_port_interrupt(struct ata_port *ap,
+ /* if LPM is enabled, PHYRDY doesn't mean anything */
+ if (ap->link.lpm_policy > ATA_LPM_MAX_POWER) {
+ status &= ~PORT_IRQ_PHYRDY;
++ account_alpm_stats(ap);
+ ahci_scr_write(&ap->link, SCR_ERROR, SERR_PHYRDY_CHG);
+ }
+
+--
+1.8.0
+
diff --git a/patches/linux-3.9.0-ahci-alpm-with-devslp-accounting.patch b/patches/linux-3.9.0-ahci-alpm-with-devslp-accounting.patch
new file mode 100644
index 0000000..b3f2073
--- /dev/null
+++ b/patches/linux-3.9.0-ahci-alpm-with-devslp-accounting.patch
@@ -0,0 +1,334 @@
+commit 1caeadb62f68b2f7c0e2cfc2b6de1f11b0314752
+Author: David Woodhouse <dwmw2@infradead.org>
+Date: Mon Apr 1 20:53:07 2013 +0100
+
+ Updated PowerTOP AHCI ALPM accounting for Device Sleep.
+
+ This patch applies to v3.7 onwards (including 3.9-rc4), and adds devslp
+ support to the AHCI state accounting. It's based on the patch at
+ https://raw.github.com/fenrus75/powertop/master/patches/linux-3.3.0-ahci-alpm-accounting.patch
+
+ From: Arjan van de Ven <arjan@linux.intel.com>
+ Subject: libata: Add ALPM power state accounting to the AHCI driver
+
+ PowerTOP wants to be able to show the user how effective the ALPM link
+ power management is for the user. ALPM is worth around 0.5W on a quiet
+ link; PowerTOP wants to be able to find cases where the "quiet link" isn't
+ actually quiet.
+
+ This patch adds state accounting functionality to the AHCI driver for
+ PowerTOP to use.
+ The parts of the patch are
+ 1) the sysfs logic of exposing the stats for each state in sysfs
+ 2) the basic accounting logic that gets update on link change interrupts
+ (or when the user accesses the info from sysfs)
+ 3) a "accounting enable" flag; in order to get the accounting to work,
+ the driver needs to get phyrdy interrupts on link status changes.
+ Normally and currently this is disabled by the driver when ALPM is
+ on (to reduce overhead); when PowerTOP is running this will need
+ to be on to get usable statistics... hence the sysfs tunable.
+
+ The PowerTOP output currently looks like this:
+
+ Recent SATA AHCI link activity statistics
+ Active Partial Slumber Device name
+ 0.5% 99.5% 0.0% host0
+
+ (work to resolve "host0" to a more human readable name is in progress)
+
+ Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
+ Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
+
+diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
+index b830e6c..981976b 100644
+--- a/drivers/ata/ahci.h
++++ b/drivers/ata/ahci.h
+@@ -286,6 +286,14 @@ struct ahci_em_priv {
+ unsigned long led_state;
+ };
+
++enum ahci_port_states {
++ AHCI_PORT_NOLINK = 0,
++ AHCI_PORT_ACTIVE = 1,
++ AHCI_PORT_PARTIAL = 2,
++ AHCI_PORT_SLUMBER = 3,
++ AHCI_PORT_DEVSLP = 4
++};
++
+ struct ahci_port_priv {
+ struct ata_link *active_link;
+ struct ahci_cmd_hdr *cmd_slot;
+@@ -306,6 +314,15 @@ struct ahci_port_priv {
+ int fbs_last_dev; /* save FBS.DEV of last FIS */
+ /* enclosure management info per PM slot */
+ struct ahci_em_priv em_priv[EM_MAX_SLOTS];
++
++ /* ALPM accounting state and stats */
++ unsigned int accounting_active:1;
++ u64 active_jiffies;
++ u64 partial_jiffies;
++ u64 slumber_jiffies;
++ u64 devslp_jiffies;
++ int previous_state;
++ int previous_jiffies;
+ };
+
+ struct ahci_host_priv {
+diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
+index 34c8216..3c7331b 100644
+--- a/drivers/ata/libahci.c
++++ b/drivers/ata/libahci.c
+@@ -100,6 +100,19 @@ static ssize_t ahci_activity_store(struct ata_device *dev,
+ enum sw_activity val);
+ static void ahci_init_sw_activity(struct ata_link *link);
+
++static ssize_t ahci_alpm_show_active(struct device *dev,
++ struct device_attribute *attr, char *buf);
++static ssize_t ahci_alpm_show_slumber(struct device *dev,
++ struct device_attribute *attr, char *buf);
++static ssize_t ahci_alpm_show_devslp(struct device *dev,
++ struct device_attribute *attr, char *buf);
++static ssize_t ahci_alpm_show_partial(struct device *dev,
++ struct device_attribute *attr, char *buf);
++static ssize_t ahci_alpm_show_accounting(struct device *dev,
++ struct device_attribute *attr, char *buf);
++static ssize_t ahci_alpm_set_accounting(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count);
+ static ssize_t ahci_show_host_caps(struct device *dev,
+ struct device_attribute *attr, char *buf);
+ static ssize_t ahci_show_host_cap2(struct device *dev,
+@@ -120,6 +133,13 @@ static DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL);
+ static DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL);
+ static DEVICE_ATTR(ahci_host_version, S_IRUGO, ahci_show_host_version, NULL);
+ static DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL);
++static DEVICE_ATTR(ahci_alpm_active, S_IRUGO, ahci_alpm_show_active, NULL);
++static DEVICE_ATTR(ahci_alpm_partial, S_IRUGO, ahci_alpm_show_partial, NULL);
++static DEVICE_ATTR(ahci_alpm_slumber, S_IRUGO, ahci_alpm_show_slumber, NULL);
++static DEVICE_ATTR(ahci_alpm_devslp, S_IRUGO, ahci_alpm_show_devslp, NULL);
++static DEVICE_ATTR(ahci_alpm_accounting, S_IRUGO | S_IWUSR,
++ ahci_alpm_show_accounting, ahci_alpm_set_accounting);
++
+ static DEVICE_ATTR(em_buffer, S_IWUSR | S_IRUGO,
+ ahci_read_em_buffer, ahci_store_em_buffer);
+ static DEVICE_ATTR(em_message_supported, S_IRUGO, ahci_show_em_supported, NULL);
+@@ -132,6 +152,11 @@ struct device_attribute *ahci_shost_attrs[] = {
+ &dev_attr_ahci_host_cap2,
+ &dev_attr_ahci_host_version,
+ &dev_attr_ahci_port_cmd,
++ &dev_attr_ahci_alpm_active,
++ &dev_attr_ahci_alpm_partial,
++ &dev_attr_ahci_alpm_slumber,
++ &dev_attr_ahci_alpm_devslp,
++ &dev_attr_ahci_alpm_accounting,
+ &dev_attr_em_buffer,
+ &dev_attr_em_message_supported,
+ NULL
+@@ -224,6 +249,182 @@ static void ahci_enable_ahci(void __iomem *mmio)
+ WARN_ON(1);
+ }
+
++static int get_current_alpm_state(struct ata_port *ap)
++{
++ u32 status = 0;
++
++ ahci_scr_read(&ap->link, SCR_STATUS, &status);
++
++ /* link status is in bits 11-8 */
++ status = status >> 8;
++ status = status & 0xf;
++
++ if (status == 8)
++ return AHCI_PORT_DEVSLP;
++ if (status == 6)
++ return AHCI_PORT_SLUMBER;
++ if (status == 2)
++ return AHCI_PORT_PARTIAL;
++ if (status == 1)
++ return AHCI_PORT_ACTIVE;
++ return AHCI_PORT_NOLINK;
++}
++
++static void account_alpm_stats(struct ata_port *ap)
++{
++ struct ahci_port_priv *pp;
++
++ int new_state;
++ u64 new_jiffies, jiffies_delta;
++
++ if (ap == NULL)
++ return;
++ pp = ap->private_data;
++
++ if (!pp) return;
++
++ new_state = get_current_alpm_state(ap);
++ new_jiffies = jiffies;
++
++ jiffies_delta = new_jiffies - pp->previous_jiffies;
++
++ switch (pp->previous_state) {
++ case AHCI_PORT_NOLINK:
++ pp->active_jiffies = 0;
++ pp->partial_jiffies = 0;
++ pp->slumber_jiffies = 0;
++ break;
++ case AHCI_PORT_ACTIVE:
++ pp->active_jiffies += jiffies_delta;
++ break;
++ case AHCI_PORT_PARTIAL:
++ pp->partial_jiffies += jiffies_delta;
++ break;
++ case AHCI_PORT_SLUMBER:
++ pp->slumber_jiffies += jiffies_delta;
++ break;
++ case AHCI_PORT_DEVSLP:
++ pp->devslp_jiffies += jiffies_delta;
++ break;
++ default:
++ break;
++ }
++ pp->previous_state = new_state;
++ pp->previous_jiffies = new_jiffies;
++}
++
++static ssize_t ahci_alpm_show_active(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *shost = class_to_shost(dev);
++ struct ata_port *ap = ata_shost_to_port(shost);
++ struct ahci_port_priv *pp;
++
++ if (!ap || ata_port_is_dummy(ap))
++ return -EINVAL;
++
++ pp = ap->private_data;
++ account_alpm_stats(ap);
++
++ return sprintf(buf, "%u\n", jiffies_to_msecs(pp->active_jiffies));
++}
++
++static ssize_t ahci_alpm_show_partial(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *shost = class_to_shost(dev);
++ struct ata_port *ap = ata_shost_to_port(shost);
++ struct ahci_port_priv *pp;
++
++ if (!ap || ata_port_is_dummy(ap))
++ return -EINVAL;
++
++ pp = ap->private_data;
++ account_alpm_stats(ap);
++
++ return sprintf(buf, "%u\n", jiffies_to_msecs(pp->partial_jiffies));
++}
++
++static ssize_t ahci_alpm_show_slumber(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *shost = class_to_shost(dev);
++ struct ata_port *ap = ata_shost_to_port(shost);
++ struct ahci_port_priv *pp;
++
++ if (!ap || ata_port_is_dummy(ap))
++ return -EINVAL;
++
++ pp = ap->private_data;
++ account_alpm_stats(ap);
++
++ return sprintf(buf, "%u\n", jiffies_to_msecs(pp->slumber_jiffies));
++}
++
++static ssize_t ahci_alpm_show_devslp(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *shost = class_to_shost(dev);
++ struct ata_port *ap = ata_shost_to_port(shost);
++ struct ahci_port_priv *pp;
++
++ if (!ap || ata_port_is_dummy(ap))
++ return -EINVAL;
++
++ pp = ap->private_data;
++ account_alpm_stats(ap);
++
++ return sprintf(buf, "%u\n", jiffies_to_msecs(pp->devslp_jiffies));
++}
++
++static ssize_t ahci_alpm_show_accounting(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *shost = class_to_shost(dev);
++ struct ata_port *ap = ata_shost_to_port(shost);
++ struct ahci_port_priv *pp;
++
++ if (!ap || ata_port_is_dummy(ap))
++ return -EINVAL;
++
++ pp = ap->private_data;
++
++ return sprintf(buf, "%u\n", pp->accounting_active);
++}
++
++static ssize_t ahci_alpm_set_accounting(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ unsigned long flags;
++ struct Scsi_Host *shost = class_to_shost(dev);
++ struct ata_port *ap = ata_shost_to_port(shost);
++ struct ahci_port_priv *pp;
++ void __iomem *port_mmio;
++
++ if (!ap || ata_port_is_dummy(ap))
++ return 1;
++
++ pp = ap->private_data;
++ port_mmio = ahci_port_base(ap);
++
++ if (!pp)
++ return 1;
++ if (buf[0] == '0')
++ pp->accounting_active = 0;
++ if (buf[0] == '1')
++ pp->accounting_active = 1;
++
++ /* we need to enable the PHYRDY interrupt when we want accounting */
++ if (pp->accounting_active) {
++ spin_lock_irqsave(ap->lock, flags);
++ pp->intr_mask |= PORT_IRQ_PHYRDY;
++ writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
++ spin_unlock_irqrestore(ap->lock, flags);
++ }
++ return count;
++}
++
+ static ssize_t ahci_show_host_caps(struct device *dev,
+ struct device_attribute *attr, char *buf)
+ {
+@@ -679,9 +880,14 @@ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+ * Disable interrupts on Phy Ready. This keeps us from
+ * getting woken up due to spurious phy ready
+ * interrupts.
++ *
++ * However, when accounting_active is set, we do want
++ * the interrupts for accounting purposes.
+ */
+- pp->intr_mask &= ~PORT_IRQ_PHYRDY;
+- writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
++ if (!pp->accounting_active) {
++ pp->intr_mask &= ~PORT_IRQ_PHYRDY;
++ writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
++ }
+
+ sata_link_scr_lpm(link, policy, false);
+ }
+@@ -1672,6 +1878,7 @@ static void ahci_handle_port_interrupt(struct ata_port *ap,
+ /* if LPM is enabled, PHYRDY doesn't mean anything */
+ if (ap->link.lpm_policy > ATA_LPM_MAX_POWER) {
+ status &= ~PORT_IRQ_PHYRDY;
++ account_alpm_stats(ap);
+ ahci_scr_write(&ap->link, SCR_ERROR, SERR_PHYRDY_CHG);
+ }
+
diff --git a/po/.tx/config b/po/.tx/config
new file mode 100644
index 0000000..f1603f2
--- /dev/null
+++ b/po/.tx/config
@@ -0,0 +1,3 @@
+[main]
+host = https://www.transifex.com
+
diff --git a/po/ChangeLog b/po/ChangeLog
new file mode 100644
index 0000000..11de90c
--- /dev/null
+++ b/po/ChangeLog
@@ -0,0 +1,11 @@
+2016-08-03 gettextize <bug-gnu-gettext@gnu.org>
+
+ * Makefile.in.in: Upgrade to gettext-0.18.2.
+ * boldquot.sed: New file, from gettext-0.18.2.
+ * en@boldquot.header: New file, from gettext-0.18.2.
+ * en@quot.header: New file, from gettext-0.18.2.
+ * insert-header.sin: New file, from gettext-0.18.2.
+ * quot.sed: New file, from gettext-0.18.2.
+ * remove-potcdate.sin: New file, from gettext-0.18.2.
+ * Rules-quot: New file, from gettext-0.18.2.
+
diff --git a/po/LINGUAS b/po/LINGUAS
new file mode 100644
index 0000000..5939602
--- /dev/null
+++ b/po/LINGUAS
@@ -0,0 +1,11 @@
+# set of available languages
+ca
+cs_CZ
+de_DE
+en_GB
+en_US
+es_ES
+hu_HU
+id_ID
+nl_NL
+zh_TW
diff --git a/po/Makefile.in.in b/po/Makefile.in.in
new file mode 100644
index 0000000..fce63a6
--- /dev/null
+++ b/po/Makefile.in.in
@@ -0,0 +1,453 @@
+# Makefile for PO directory in any package using GNU gettext.
+# Copyright (C) 1995-1997, 2000-2007, 2009-2010 by Ulrich Drepper <drepper@gnu.ai.mit.edu>
+#
+# This file can be copied and used freely without restrictions. It can
+# be used in projects which are not available under the GNU General Public
+# License but which still want to provide support for the GNU gettext
+# functionality.
+# Please note that the actual code of GNU gettext is covered by the GNU
+# General Public License and is *not* in the public domain.
+#
+# Origin: gettext-0.18.2
+GETTEXT_MACRO_VERSION = 0.18
+
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+
+SHELL = /bin/sh
+@SET_MAKE@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+datarootdir = @datarootdir@
+datadir = @datadir@
+localedir = @localedir@
+gettextsrcdir = $(datadir)/gettext/po
+
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+
+# We use $(mkdir_p).
+# In automake <= 1.9.x, $(mkdir_p) is defined either as "mkdir -p --" or as
+# "$(mkinstalldirs)" or as "$(install_sh) -d". For these automake versions,
+# @install_sh@ does not start with $(SHELL), so we add it.
+# In automake >= 1.10, @mkdir_p@ is derived from ${MKDIR_P}, which is defined
+# either as "/path/to/mkdir -p" or ".../install-sh -c -d". For these automake
+# versions, $(mkinstalldirs) and $(install_sh) are unused.
+mkinstalldirs = $(SHELL) @install_sh@ -d
+install_sh = $(SHELL) @install_sh@
+MKDIR_P = @MKDIR_P@
+mkdir_p = @mkdir_p@
+
+GMSGFMT_ = @GMSGFMT@
+GMSGFMT_no = @GMSGFMT@
+GMSGFMT_yes = @GMSGFMT_015@
+GMSGFMT = $(GMSGFMT_$(USE_MSGCTXT))
+MSGFMT_ = @MSGFMT@
+MSGFMT_no = @MSGFMT@
+MSGFMT_yes = @MSGFMT_015@
+MSGFMT = $(MSGFMT_$(USE_MSGCTXT))
+XGETTEXT_ = @XGETTEXT@
+XGETTEXT_no = @XGETTEXT@
+XGETTEXT_yes = @XGETTEXT_015@
+XGETTEXT = $(XGETTEXT_$(USE_MSGCTXT))
+MSGMERGE = msgmerge
+MSGMERGE_UPDATE = @MSGMERGE@ --update
+MSGINIT = msginit
+MSGCONV = msgconv
+MSGFILTER = msgfilter
+
+POFILES = @POFILES@
+GMOFILES = @GMOFILES@
+UPDATEPOFILES = @UPDATEPOFILES@
+DUMMYPOFILES = @DUMMYPOFILES@
+DISTFILES.common = Makefile.in.in remove-potcdate.sin \
+$(DISTFILES.common.extra1) $(DISTFILES.common.extra2) $(DISTFILES.common.extra3)
+DISTFILES = $(DISTFILES.common) Makevars POTFILES.in \
+$(POFILES) $(GMOFILES) \
+$(DISTFILES.extra1) $(DISTFILES.extra2) $(DISTFILES.extra3)
+
+POTFILES = \
+
+CATALOGS = @CATALOGS@
+
+# Makevars gets inserted here. (Don't remove this line!)
+
+.SUFFIXES:
+.SUFFIXES: .po .gmo .mo .sed .sin .nop .po-create .po-update
+
+.po.mo:
+ @echo "$(MSGFMT) -c -o $@ $<"; \
+ $(MSGFMT) -c -o t-$@ $< && mv t-$@ $@
+
+.po.gmo:
+ @lang=`echo $* | sed -e 's,.*/,,'`; \
+ test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
+ echo "$${cdcmd}rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics --verbose -o $${lang}.gmo $${lang}.po"; \
+ cd $(srcdir) && rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics --verbose -o t-$${lang}.gmo $${lang}.po && mv t-$${lang}.gmo $${lang}.gmo
+
+.sin.sed:
+ sed -e '/^#/d' $< > t-$@
+ mv t-$@ $@
+
+
+all: all-@USE_NLS@
+
+all-yes: stamp-po
+all-no:
+
+# Ensure that the gettext macros and this Makefile.in.in are in sync.
+CHECK_MACRO_VERSION = \
+ test "$(GETTEXT_MACRO_VERSION)" = "@GETTEXT_MACRO_VERSION@" \
+ || { echo "*** error: gettext infrastructure mismatch: using a Makefile.in.in from gettext version $(GETTEXT_MACRO_VERSION) but the autoconf macros are from gettext version @GETTEXT_MACRO_VERSION@" 1>&2; \
+ exit 1; \
+ }
+
+# $(srcdir)/$(DOMAIN).pot is only created when needed. When xgettext finds no
+# internationalized messages, no $(srcdir)/$(DOMAIN).pot is created (because
+# we don't want to bother translators with empty POT files). We assume that
+# LINGUAS is empty in this case, i.e. $(POFILES) and $(GMOFILES) are empty.
+# In this case, stamp-po is a nop (i.e. a phony target).
+
+# stamp-po is a timestamp denoting the last time at which the CATALOGS have
+# been loosely updated. Its purpose is that when a developer or translator
+# checks out the package via CVS, and the $(DOMAIN).pot file is not in CVS,
+# "make" will update the $(DOMAIN).pot and the $(CATALOGS), but subsequent
+# invocations of "make" will do nothing. This timestamp would not be necessary
+# if updating the $(CATALOGS) would always touch them; however, the rule for
+# $(POFILES) has been designed to not touch files that don't need to be
+# changed.
+stamp-po: $(srcdir)/$(DOMAIN).pot
+ @$(CHECK_MACRO_VERSION)
+ test ! -f $(srcdir)/$(DOMAIN).pot || \
+ test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES)
+ @test ! -f $(srcdir)/$(DOMAIN).pot || { \
+ echo "touch stamp-po" && \
+ echo timestamp > stamp-poT && \
+ mv stamp-poT stamp-po; \
+ }
+
+# Note: Target 'all' must not depend on target '$(DOMAIN).pot-update',
+# otherwise packages like GCC can not be built if only parts of the source
+# have been downloaded.
+
+# This target rebuilds $(DOMAIN).pot; it is an expensive operation.
+# Note that $(DOMAIN).pot is not touched if it doesn't need to be changed.
+# The determination of whether the package xyz is a GNU one is based on the
+# heuristic whether some file in the top level directory mentions "GNU xyz".
+# If GNU 'find' is available, we avoid grepping through monster files.
+$(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in remove-potcdate.sed
+ if { if (LC_ALL=C find --version) 2>/dev/null | grep GNU >/dev/null; then \
+ LC_ALL=C find -L $(top_srcdir) -maxdepth 1 -type f -size -10000000c -exec grep 'GNU @PACKAGE@' /dev/null '{}' ';' 2>/dev/null; \
+ else \
+ LC_ALL=C grep 'GNU @PACKAGE@' $(top_srcdir)/* 2>/dev/null; \
+ fi; \
+ } | grep -v 'libtool:' >/dev/null; then \
+ package_gnu='GNU '; \
+ else \
+ package_gnu=''; \
+ fi; \
+ if test -n '$(MSGID_BUGS_ADDRESS)' || test '$(PACKAGE_BUGREPORT)' = '@'PACKAGE_BUGREPORT'@'; then \
+ msgid_bugs_address='$(MSGID_BUGS_ADDRESS)'; \
+ else \
+ msgid_bugs_address='$(PACKAGE_BUGREPORT)'; \
+ fi; \
+ case `$(XGETTEXT) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
+ '' | 0.[0-9] | 0.[0-9].* | 0.1[0-5] | 0.1[0-5].* | 0.16 | 0.16.[0-1]*) \
+ $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \
+ --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \
+ --files-from=$(srcdir)/POTFILES.in \
+ --copyright-holder='$(COPYRIGHT_HOLDER)' \
+ --msgid-bugs-address="$$msgid_bugs_address" \
+ ;; \
+ *) \
+ $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \
+ --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \
+ --files-from=$(srcdir)/POTFILES.in \
+ --copyright-holder='$(COPYRIGHT_HOLDER)' \
+ --package-name="$${package_gnu}@PACKAGE@" \
+ --package-version='@VERSION@' \
+ --msgid-bugs-address="$$msgid_bugs_address" \
+ ;; \
+ esac
+ test ! -f $(DOMAIN).po || { \
+ if test -f $(srcdir)/$(DOMAIN).pot; then \
+ sed -f remove-potcdate.sed < $(srcdir)/$(DOMAIN).pot > $(DOMAIN).1po && \
+ sed -f remove-potcdate.sed < $(DOMAIN).po > $(DOMAIN).2po && \
+ if cmp $(DOMAIN).1po $(DOMAIN).2po >/dev/null 2>&1; then \
+ rm -f $(DOMAIN).1po $(DOMAIN).2po $(DOMAIN).po; \
+ else \
+ rm -f $(DOMAIN).1po $(DOMAIN).2po $(srcdir)/$(DOMAIN).pot && \
+ mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \
+ fi; \
+ else \
+ mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \
+ fi; \
+ }
+
+# This rule has no dependencies: we don't need to update $(DOMAIN).pot at
+# every "make" invocation, only create it when it is missing.
+# Only "make $(DOMAIN).pot-update" or "make dist" will force an update.
+$(srcdir)/$(DOMAIN).pot:
+ $(MAKE) $(DOMAIN).pot-update
+
+# This target rebuilds a PO file if $(DOMAIN).pot has changed.
+# Note that a PO file is not touched if it doesn't need to be changed.
+$(POFILES): $(srcdir)/$(DOMAIN).pot
+ @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
+ if test -f "$(srcdir)/$${lang}.po"; then \
+ test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
+ echo "$${cdcmd}$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot"; \
+ cd $(srcdir) \
+ && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
+ '' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \
+ $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
+ *) \
+ $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot;; \
+ esac; \
+ }; \
+ else \
+ $(MAKE) $${lang}.po-create; \
+ fi
+
+
+install: install-exec install-data
+install-exec:
+install-data: install-data-@USE_NLS@
+ if test "$(PACKAGE)" = "gettext-tools"; then \
+ $(mkdir_p) $(DESTDIR)$(gettextsrcdir); \
+ for file in $(DISTFILES.common) Makevars.template; do \
+ $(INSTALL_DATA) $(srcdir)/$$file \
+ $(DESTDIR)$(gettextsrcdir)/$$file; \
+ done; \
+ for file in Makevars; do \
+ rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \
+ done; \
+ else \
+ : ; \
+ fi
+install-data-no: all
+install-data-yes: all
+ @catalogs='$(CATALOGS)'; \
+ for cat in $$catalogs; do \
+ cat=`basename $$cat`; \
+ lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \
+ dir=$(localedir)/$$lang/LC_MESSAGES; \
+ $(mkdir_p) $(DESTDIR)$$dir; \
+ if test -r $$cat; then realcat=$$cat; else realcat=$(srcdir)/$$cat; fi; \
+ $(INSTALL_DATA) $$realcat $(DESTDIR)$$dir/$(DOMAIN).mo; \
+ echo "installing $$realcat as $(DESTDIR)$$dir/$(DOMAIN).mo"; \
+ for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \
+ if test -n "$$lc"; then \
+ if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \
+ link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \
+ mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \
+ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \
+ (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \
+ for file in *; do \
+ if test -f $$file; then \
+ ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \
+ fi; \
+ done); \
+ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \
+ else \
+ if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \
+ :; \
+ else \
+ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \
+ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \
+ fi; \
+ fi; \
+ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \
+ ln -s ../LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \
+ ln $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \
+ cp -p $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \
+ echo "installing $$realcat link as $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo"; \
+ fi; \
+ done; \
+ done
+
+install-strip: install
+
+installdirs: installdirs-exec installdirs-data
+installdirs-exec:
+installdirs-data: installdirs-data-@USE_NLS@
+ if test "$(PACKAGE)" = "gettext-tools"; then \
+ $(mkdir_p) $(DESTDIR)$(gettextsrcdir); \
+ else \
+ : ; \
+ fi
+installdirs-data-no:
+installdirs-data-yes:
+ @catalogs='$(CATALOGS)'; \
+ for cat in $$catalogs; do \
+ cat=`basename $$cat`; \
+ lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \
+ dir=$(localedir)/$$lang/LC_MESSAGES; \
+ $(mkdir_p) $(DESTDIR)$$dir; \
+ for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \
+ if test -n "$$lc"; then \
+ if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \
+ link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \
+ mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \
+ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \
+ (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \
+ for file in *; do \
+ if test -f $$file; then \
+ ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \
+ fi; \
+ done); \
+ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \
+ else \
+ if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \
+ :; \
+ else \
+ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \
+ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \
+ fi; \
+ fi; \
+ fi; \
+ done; \
+ done
+
+# Define this as empty until I found a useful application.
+installcheck:
+
+uninstall: uninstall-exec uninstall-data
+uninstall-exec:
+uninstall-data: uninstall-data-@USE_NLS@
+ if test "$(PACKAGE)" = "gettext-tools"; then \
+ for file in $(DISTFILES.common) Makevars.template; do \
+ rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \
+ done; \
+ else \
+ : ; \
+ fi
+uninstall-data-no:
+uninstall-data-yes:
+ catalogs='$(CATALOGS)'; \
+ for cat in $$catalogs; do \
+ cat=`basename $$cat`; \
+ lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \
+ for lc in LC_MESSAGES $(EXTRA_LOCALE_CATEGORIES); do \
+ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \
+ done; \
+ done
+
+check: all
+
+info dvi ps pdf html tags TAGS ctags CTAGS ID:
+
+mostlyclean:
+ rm -f remove-potcdate.sed
+ rm -f stamp-poT
+ rm -f core core.* $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
+ rm -fr *.o
+
+clean: mostlyclean
+
+distclean: clean
+ rm -f Makefile Makefile.in POTFILES *.mo
+
+maintainer-clean: distclean
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+ rm -f stamp-po $(GMOFILES)
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+dist distdir:
+ $(MAKE) update-po
+ @$(MAKE) dist2
+# This is a separate target because 'update-po' must be executed before.
+dist2: stamp-po $(DISTFILES)
+ dists="$(DISTFILES)"; \
+ if test "$(PACKAGE)" = "gettext-tools"; then \
+ dists="$$dists Makevars.template"; \
+ fi; \
+ if test -f $(srcdir)/$(DOMAIN).pot; then \
+ dists="$$dists $(DOMAIN).pot stamp-po"; \
+ fi; \
+ if test -f $(srcdir)/ChangeLog; then \
+ dists="$$dists ChangeLog"; \
+ fi; \
+ for i in 0 1 2 3 4 5 6 7 8 9; do \
+ if test -f $(srcdir)/ChangeLog.$$i; then \
+ dists="$$dists ChangeLog.$$i"; \
+ fi; \
+ done; \
+ if test -f $(srcdir)/LINGUAS; then dists="$$dists LINGUAS"; fi; \
+ for file in $$dists; do \
+ if test -f $$file; then \
+ cp -p $$file $(distdir) || exit 1; \
+ else \
+ cp -p $(srcdir)/$$file $(distdir) || exit 1; \
+ fi; \
+ done
+
+update-po: Makefile
+ $(MAKE) $(DOMAIN).pot-update
+ test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
+ $(MAKE) update-gmo
+
+# General rule for creating PO files.
+
+.nop.po-create:
+ @lang=`echo $@ | sed -e 's/\.po-create$$//'`; \
+ echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
+ exit 1
+
+# General rule for updating PO files.
+
+.nop.po-update:
+ @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
+ if test "$(PACKAGE)" = "gettext-tools"; then PATH=`pwd`/../src:$$PATH; fi; \
+ tmpdir=`pwd`; \
+ echo "$$lang:"; \
+ test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
+ echo "$${cdcmd}$(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
+ cd $(srcdir); \
+ if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
+ '' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \
+ $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
+ *) \
+ $(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
+ esac; \
+ }; then \
+ if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
+ rm -f $$tmpdir/$$lang.new.po; \
+ else \
+ if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
+ :; \
+ else \
+ echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
+ exit 1; \
+ fi; \
+ fi; \
+ else \
+ echo "msgmerge for $$lang.po failed!" 1>&2; \
+ rm -f $$tmpdir/$$lang.new.po; \
+ fi
+
+$(DUMMYPOFILES):
+
+update-gmo: Makefile $(GMOFILES)
+ @:
+
+# Recreate Makefile by invoking config.status. Explicitly invoke the shell,
+# because execution permission bits may not work on the current file system.
+# Use @SHELL@, which is the shell determined by autoconf for the use by its
+# scripts, not $(SHELL) which is hardwired to /bin/sh and may be deficient.
+Makefile: Makefile.in.in Makevars $(top_builddir)/config.status @POMAKEFILEDEPS@
+ cd $(top_builddir) \
+ && @SHELL@ ./config.status $(subdir)/$@.in po-directories
+
+force:
+
+# Tell versions [3.59,3.63) of GNU make not to export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/po/Makevars b/po/Makevars
new file mode 100644
index 0000000..fbf0a76
--- /dev/null
+++ b/po/Makevars
@@ -0,0 +1,53 @@
+# Makefile variables for PO directory in any package using GNU gettext.
+
+# Usually the message domain is the same as the package name.
+DOMAIN = $(PACKAGE)
+
+# These two variables depend on the location of this directory.
+subdir = po
+top_builddir = ..
+
+# These options get passed to xgettext.
+XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ --keyword=__
+
+# This is the copyright holder that gets inserted into the header of the
+# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding
+# package. (Note that the msgstr strings, extracted from the package's
+# sources, belong to the copyright holder of the package.) Translators are
+# expected to transfer the copyright for their translations to this person
+# or entity, or to disclaim their copyright. The empty string stands for
+# the public domain; in this case the translators are expected to disclaim
+# their copyright.
+COPYRIGHT_HOLDER = Intel Corporation
+
+# This is the email address or URL to which the translators shall report
+# bugs in the untranslated strings:
+# - Strings which are not entire sentences, see the maintainer guidelines
+# in the GNU gettext documentation, section 'Preparing Strings'.
+# - Strings which use unclear terms or require additional context to be
+# understood.
+# - Strings which make invalid assumptions about notation of date, time or
+# money.
+# - Pluralisation problems.
+# - Incorrect English spelling.
+# - Incorrect formatting.
+# It can be your email address, or a mailing list address where translators
+# can write to without being subscribed, or the URL of a web page through
+# which the translators can contact you.
+MSGID_BUGS_ADDRESS = "powertop@lists.01.org"
+
+# This is the list of locale categories, beyond LC_MESSAGES, for which the
+# message catalogs shall be used. It is usually empty.
+EXTRA_LOCALE_CATEGORIES =
+
+# This tells whether the $(DOMAIN).pot file contains messages with an 'msgctxt'
+# context. Possible values are "yes" and "no". Set this to yes if the
+# package uses functions taking also a message context, like pgettext(), or
+# if in $(XGETTEXT_OPTIONS) you define keywords with a context argument.
+USE_MSGCTXT = no
+
+# These options get passed to msgmerge.
+# Useful options are in particular:
+# --previous to keep previous msgids of translated messages,
+# --quiet to reduce the verbosity.
+MSGMERGE_OPTIONS =
diff --git a/po/POTFILES.in b/po/POTFILES.in
new file mode 100644
index 0000000..b466978
--- /dev/null
+++ b/po/POTFILES.in
@@ -0,0 +1,45 @@
+# List of source files which contain translatable strings.
+
+src/calibrate/calibrate.cpp
+src/cpu/abstract_cpu.cpp
+src/cpu/cpu_core.cpp
+src/cpu/cpu.cpp
+src/cpu/cpu_linux.cpp
+src/cpu/cpu_package.cpp
+src/cpu/intel_cpus.cpp
+src/cpu/intel_gpu.cpp
+src/devices/ahci.cpp
+src/devices/alsa.cpp
+src/devices/devfreq.cpp
+src/devices/device.cpp
+src/devices/network.cpp
+src/devices/rfkill.cpp
+src/devices/runtime_pm.cpp
+src/devices/usb.cpp
+src/devlist.cpp
+src/display.cpp
+src/lib.cpp
+src/lib.h
+src/main.cpp
+src/parameters/persistent.cpp
+src/perf/perf_bundle.cpp
+src/perf/perf.cpp
+src/process/do_process.cpp
+src/report/report.cpp
+src/report/report-maker.h
+src/tuning/bluetooth.cpp
+src/tuning/ethernet.cpp
+src/tuning/nl80211.h
+src/tuning/runtime.cpp
+src/tuning/tunable.cpp
+src/tuning/tuning.cpp
+src/tuning/tuningi2c.cpp
+src/tuning/tuningsysfs.cpp
+src/tuning/tuningusb.cpp
+src/tuning/wifi.cpp
+src/wakeup/waketab.cpp
+src/wakeup/wakeup.cpp
+src/wakeup/wakeup_ethernet.cpp
+src/wakeup/wakeup_usb.cpp
+traceevent/event-parse.h
+traceevent/parse-utils.c
diff --git a/po/bn_IN.po b/po/bn_IN.po
new file mode 100644
index 0000000..1f083c0
--- /dev/null
+++ b/po/bn_IN.po
@@ -0,0 +1,1037 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Intel Corporation
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# rajeshpro <rajeshdey606@gmail.com>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: PowerTOP\n"
+"Report-Msgid-Bugs-To: powertop@lists.01.org\n"
+"POT-Creation-Date: 2019-01-04 13:55-0800\n"
+"PO-Revision-Date: 2013-11-05 08:40+0000\n"
+"Last-Translator: Margie Foster <margie@linux.intel.com>\n"
+"Language-Team: Bengali (India) (http://www.transifex.com/projects/p/PowerTOP/"
+"language/bn_IN/)\n"
+"Language: bn_IN\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ../src/calibrate/calibrate.cpp:238
+#, c-format
+msgid "Cannot create temp file\n"
+msgstr "সাময়িক ফাইল তৈরি করতে পারবেন না\n"
+
+#: ../src/calibrate/calibrate.cpp:258
+#, c-format
+msgid "Calibrating: CPU usage on %i threads\n"
+msgstr "Calibrating: CPU usage on %i threads\n"
+
+#: ../src/calibrate/calibrate.cpp:273
+#, c-format
+msgid "Calibrating: CPU wakeup power consumption\n"
+msgstr ""
+"Calibrating: সিপিইউ -র ওয়েকআপ ক্ষমতা গ্রহণ\n"
+"\n"
+
+#: ../src/calibrate/calibrate.cpp:290
+#, c-format
+msgid "Calibrating USB devices\n"
+msgstr ""
+"কেলিবেটি ইউএসবি ডিভাইস\n"
+"\n"
+"\n"
+
+#: ../src/calibrate/calibrate.cpp:292 ../src/calibrate/calibrate.cpp:309
+#: ../src/calibrate/calibrate.cpp:317 ../src/calibrate/calibrate.cpp:334
+#, c-format
+msgid ".... device %s \n"
+msgstr ""
+" ... ডিভাইস %s\n"
+"\n"
+"\n"
+
+#: ../src/calibrate/calibrate.cpp:307
+#, c-format
+msgid "Calibrating radio devices\n"
+msgstr ""
+"Calibrating রেডিও ডিভাইস\n"
+"\n"
+
+#: ../src/calibrate/calibrate.cpp:331
+#, c-format
+msgid "Calibrating backlight\n"
+msgstr ""
+"Calibrating বেকলাইট\n"
+"\n"
+
+#: ../src/calibrate/calibrate.cpp:355 ../src/calibrate/calibrate.cpp:365
+#, c-format
+msgid "Calibrating idle\n"
+msgstr ""
+"Calibrating অলস\n"
+"\n"
+
+#: ../src/calibrate/calibrate.cpp:378
+#, c-format
+msgid "Calibrating: disk usage \n"
+msgstr ""
+"Calibrating: ডিস্ক ব্যবহার\n"
+"\n"
+
+#: ../src/calibrate/calibrate.cpp:403
+msgid "Starting PowerTOP power estimate calibration \n"
+msgstr ""
+"পাওষ়ারটপ শক্তি অনুমান ক্রমাঙ্কন শুরু\n"
+"\n"
+
+#: ../src/calibrate/calibrate.cpp:426
+msgid "Finishing PowerTOP power estimate calibration \n"
+msgstr ""
+"পাওষ়ারটপ শক্তি অনুমান ক্রমাঙ্কন সমাপ্তি\n"
+"\n"
+
+#: ../src/calibrate/calibrate.cpp:430
+#, c-format
+msgid "Parameters after calibration:\n"
+msgstr ""
+"ক্রমাঙ্কন-র পরে প্যারামিটারগুলি:\n"
+"\n"
+
+#: ../src/cpu/abstract_cpu.cpp:74
+msgid "Idle"
+msgstr ""
+
+#: ../src/cpu/abstract_cpu.cpp:76
+msgid "Turbo Mode"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(HW)"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(OS)"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:91 ../src/cpu/intel_cpus.cpp:324
+#, c-format
+msgid " Core"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:85
+#, c-format
+msgid "cpu package %i"
+msgstr "সিপিইউ প্যাকেজ %i"
+
+#: ../src/cpu/cpu.cpp:86
+msgid "cpu package"
+msgstr "cpu 'র প্যাকেজ"
+
+#: ../src/cpu/cpu.cpp:89 ../src/cpu/cpu.cpp:96
+#, fuzzy, c-format
+msgid "package-%i"
+msgstr "সিপিইউ প্যাকেজ %i"
+
+#: ../src/cpu/cpu.cpp:90
+msgid "cpu rapl package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:97
+msgid "dram rapl package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:471
+msgid "Processor Idle State Report"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:535 ../src/cpu/cpu.cpp:753
+msgid "Package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:566 ../src/cpu/cpu.cpp:775
+#, c-format
+msgid "Core %d"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:573
+#, c-format
+msgid "GPU %d"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:594
+#, fuzzy
+msgid "CPU"
+msgstr "সিপিইউ-র ব্যবহার"
+
+#: ../src/cpu/cpu.cpp:676
+msgid "Processor Frequency Report"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:796
+#, fuzzy, c-format
+msgid "CPU %d"
+msgstr "সিপিইউ-র ব্যবহার"
+
+#: ../src/cpu/cpu.cpp:997
+#, c-format
+msgid "cpu_idle event returned no state?\n"
+msgstr ""
+"cpu_idle ইভেন্ট কোনও অবস্থাষ় ফিরে আসেনি?\n"
+"\n"
+
+#: ../src/cpu/cpu.cpp:1012
+#, c-format
+msgid "power or cpu_frequency event returned no state?\n"
+msgstr ""
+
+#: ../src/cpu/cpu_linux.cpp:79
+msgid "C0 polling"
+msgstr "C0 polling"
+
+#: ../src/cpu/cpu_linux.cpp:242
+#, c-format
+msgid " CPU(OS) %i"
+msgstr ""
+
+#: ../src/cpu/cpu_linux.cpp:341 ../src/cpu/intel_cpus.cpp:651
+#, c-format
+msgid " CPU %i"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(HW)"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(OS)"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:104 ../src/cpu/intel_cpus.cpp:412
+#, c-format
+msgid " Package"
+msgstr ""
+
+#: ../src/cpu/intel_cpus.cpp:129
+#, c-format
+msgid "read_msr cpu%d 0x%llx : "
+msgstr ""
+
+#: ../src/cpu/intel_cpus.cpp:574
+msgid "C0 active"
+msgstr "C0 সক্রিয়"
+
+#: ../src/cpu/intel_cpus.cpp:632
+#, c-format
+msgid "Average"
+msgstr ""
+
+#: ../src/cpu/intel_gpu.cpp:64
+#, c-format
+msgid " GPU "
+msgstr ""
+
+#: ../src/devices/ahci.cpp:154
+#, c-format
+msgid "SATA link: %s"
+msgstr "SATA সংযোগ: %s"
+
+#: ../src/devices/ahci.cpp:156
+#, c-format
+msgid "SATA disk: %s"
+msgstr "SATA ডিস্ক: %s"
+
+#: ../src/devices/ahci.cpp:374
+msgid "AHCI ALPM Residency Statistics - Not supported on this macine"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:389
+msgid "Link"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:390
+#, fuzzy
+msgid "Active"
+msgstr "C0 সক্রিয়"
+
+#: ../src/devices/ahci.cpp:391
+msgid "Partial"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:392
+msgid "Slumber"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:393
+msgid "Devslp"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:399
+msgid "AHCI ALPM Residency Statistics"
+msgstr ""
+
+#: ../src/devices/alsa.cpp:77
+#, c-format
+msgid "Audio codec %s: %s (%s)"
+msgstr "Audio codec %s: %s (%s)"
+
+#: ../src/devices/alsa.cpp:79 ../src/devices/alsa.cpp:81
+#, c-format
+msgid "Audio codec %s: %s"
+msgstr "অডিও কোডেক %s: %s"
+
+#: ../src/devices/devfreq.cpp:261
+#, fuzzy
+msgid "Device Freq stats"
+msgstr "ডিভাইস পরিসংখ্যান"
+
+#: ../src/devices/devfreq.cpp:279
+msgid " Devfreq is not enabled"
+msgstr ""
+
+#: ../src/devices/devfreq.cpp:284
+msgid " No devfreq devices available"
+msgstr ""
+
+#: ../src/devices/device.cpp:172 ../src/process/do_process.cpp:831
+#, c-format
+msgid "The battery reports a discharge rate of %sW\n"
+msgstr "The battery reports a discharge rate of %sW\n"
+
+#: ../src/devices/device.cpp:174 ../src/process/do_process.cpp:833
+#, c-format
+msgid "The power consumed was %sJ\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:180
+#, c-format
+msgid "System baseline power is estimated at %sW\n"
+msgstr "System baseline power is estimated at %sW\n"
+
+#: ../src/devices/device.cpp:187
+msgid "Power est. Usage Device name\n"
+msgstr ""
+"বিদ্যুৎ est. ব্যবহার ডিভাইস নাম\n"
+"\n"
+
+#: ../src/devices/device.cpp:189
+msgid " Usage Device name\n"
+msgstr ""
+" ব্যবহারের ডিভাইস নাম\n"
+"\n"
+
+#: ../src/devices/device.cpp:256
+#, fuzzy
+msgid "The battery reports a discharge rate of: "
+msgstr "The battery reports a discharge rate of %sW\n"
+
+#: ../src/devices/device.cpp:261
+msgid "The power consumed was : "
+msgstr ""
+
+#: ../src/devices/device.cpp:268
+#, fuzzy
+msgid "The system baseline power is estimated at: "
+msgstr "System baseline power is estimated at %sW\n"
+
+#: ../src/devices/device.cpp:277 ../src/process/do_process.cpp:850
+#: ../src/process/do_process.cpp:852 ../src/process/do_process.cpp:926
+#: ../src/process/do_process.cpp:1077
+msgid "Usage"
+msgstr "ব্যবহার"
+
+#: ../src/devices/device.cpp:278
+#, fuzzy
+msgid "Device Name"
+msgstr "ডিভাইস পরিসংখ্যান"
+
+#: ../src/devices/device.cpp:280 ../src/process/do_process.cpp:935
+#: ../src/process/do_process.cpp:1082
+msgid "PW Estimate"
+msgstr ""
+
+#. Report Output
+#: ../src/devices/device.cpp:317
+msgid "Device Power Report"
+msgstr ""
+
+#: ../src/devices/network.cpp:177
+#, c-format
+msgid "Network interface: %s (%s)"
+msgstr "নেটওয়ার্ক ইন্টারফেস: %s (%s)"
+
+#: ../src/devices/rfkill.cpp:65 ../src/devices/rfkill.cpp:69
+#, c-format
+msgid "Radio device: %s"
+msgstr "রেডিও ডিভাইস: %s"
+
+#: ../src/devices/runtime_pm.cpp:216
+#, c-format
+msgid "I2C %s (%s): %s"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216 ../src/tuning/tuningi2c.cpp:57
+#: ../src/tuning/tuningi2c.cpp:59
+msgid "Adapter"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216 ../src/devlist.cpp:331
+#: ../src/tuning/tuningi2c.cpp:57 ../src/tuning/tuningi2c.cpp:59
+#, fuzzy
+msgid "Device"
+msgstr "ডিভাইস পরিসংখ্যান"
+
+#: ../src/devices/runtime_pm.cpp:241
+#, c-format
+msgid "PCI Device: %s"
+msgstr "পিসিআই ডিভাইস: %s"
+
+#: ../src/devices/usb.cpp:51 ../src/devices/usb.cpp:96
+#: ../src/devices/usb.cpp:98
+#, c-format
+msgid "USB device: %s"
+msgstr "ইউএসবি ডিভাইস: %s"
+
+#: ../src/devices/usb.cpp:94
+#, c-format
+msgid "USB device: %s (%s)"
+msgstr "ইউএসবি ডিভাইস: %s (%s)"
+
+#: ../src/devlist.cpp:330
+msgid "Process"
+msgstr ""
+
+#. Report Output
+#. No div attribute here inherits from device power report
+#: ../src/devlist.cpp:347
+msgid "Process Device Activity"
+msgstr ""
+
+#: ../src/display.cpp:70
+msgid "Overview"
+msgstr "পরিদর্শন"
+
+#: ../src/display.cpp:71
+msgid "Idle stats"
+msgstr "অলস পরিসংখ্যান"
+
+#: ../src/display.cpp:72
+msgid "Frequency stats"
+msgstr "কম্পাংক পরিসংখ্যান"
+
+#: ../src/display.cpp:73
+msgid "Device stats"
+msgstr "ডিভাইস পরিসংখ্যান"
+
+#: ../src/display.cpp:131
+msgid "Exit"
+msgstr "প্রস্থান"
+
+#: ../src/display.cpp:132
+msgid "Navigate"
+msgstr ""
+
+#: ../src/lib.cpp:288
+#, c-format
+msgid "%7sW"
+msgstr "%7sW"
+
+#: ../src/lib.cpp:291
+#, c-format
+msgid " 0 mW"
+msgstr " 0 mW"
+
+#: ../src/lib.cpp:410
+msgid "PS/2 Touchpad / Keyboard / Mouse"
+msgstr "PS / 2, টাচপ্যাড / কীবোর্ড / মাউস"
+
+#: ../src/lib.cpp:411
+msgid "SATA controller"
+msgstr "SATA নিয়ন্ত্রণ"
+
+#: ../src/lib.cpp:412
+msgid "Intel built in USB hub"
+msgstr "ইন্টেল নির্মিত USB হাব"
+
+#: ../src/lib.cpp:467
+#, c-format
+msgid "glob returned GLOB_NOSPACE\n"
+msgstr ""
+
+#: ../src/lib.cpp:471
+#, c-format
+msgid "glob returned GLOB_ABORTED\n"
+msgstr ""
+
+#: ../src/lib.cpp:475
+#, c-format
+msgid "glob returned GLOB_NOMATCH\n"
+msgstr ""
+
+#: ../src/lib.cpp:513 ../src/lib.cpp:549
+#, c-format
+msgid ""
+"Model-specific registers (MSR)\t\t\t not found (try enabling "
+"CONFIG_X86_MSR).\n"
+msgstr ""
+
+#: ../src/main.cpp:103
+#, fuzzy, c-format
+msgid "PowerTOP version "
+msgstr "পাওষ়ারটপ অনুবাদ"
+
+#: ../src/main.cpp:109
+msgid "Set refresh time out"
+msgstr "রিফ্রেশ সময় আউট সেট করুন"
+
+#: ../src/main.cpp:122
+msgid "Usage: powertop [OPTIONS]"
+msgstr "ব্যবহার: পাওষ়ারটপ [বিকল্প]"
+
+#: ../src/main.cpp:123
+msgid "sets all tunable options to their GOOD setting"
+msgstr ""
+
+#: ../src/main.cpp:124
+msgid "runs powertop in calibration mode"
+msgstr "মোডে সঞ্চালিত "
+
+#: ../src/main.cpp:125 ../src/main.cpp:128
+msgid "[=filename]"
+msgstr ""
+
+#: ../src/main.cpp:125
+msgid "generate a csv report"
+msgstr "একটি csv রিপোর্ট তৈরি কর "
+
+#: ../src/main.cpp:126
+msgid "run in \"debug\" mode"
+msgstr "\"ডিবাগ\" মোডে চালানো"
+
+#: ../src/main.cpp:127
+msgid "[=devnode]"
+msgstr "[=ডেভনোড]"
+
+#: ../src/main.cpp:127
+msgid "uses an Extech Power Analyzer for measurements"
+msgstr "পরিমাপের জন্য একটি Extech পাওয়ার বিশ্লেষক ব্যবহার"
+
+#: ../src/main.cpp:128
+msgid "generate a html report"
+msgstr "একটি এইচটিএমএল রিপোর্ট তৈরি কর "
+
+#: ../src/main.cpp:129
+msgid "[=iterations] number of times to run each test"
+msgstr "[= পুনরাবৃত্তিও] প্রত্যেক পরীক্ষা চালাতে সময়ের সংখ্যা"
+
+#: ../src/main.cpp:130
+msgid "suppress stderr output"
+msgstr ""
+
+#: ../src/main.cpp:131 ../src/main.cpp:132
+msgid "[=seconds]"
+msgstr "[=সেকেন্ডস]"
+
+#: ../src/main.cpp:131
+msgid "interval for power consumption measurement"
+msgstr ""
+
+#: ../src/main.cpp:132
+msgid "generate a report for 'x' seconds"
+msgstr "'x' সেকেন্ডের জন্য একটি প্রতিবেদন তৈরি করুন"
+
+#: ../src/main.cpp:133
+msgid "[=workload]"
+msgstr ""
+
+#: ../src/main.cpp:133
+msgid "file to execute for workload"
+msgstr ""
+
+#: ../src/main.cpp:134
+msgid "print version information"
+msgstr "প্রিন্ট সংস্করণ সংক্রান্ত তথ্য"
+
+#: ../src/main.cpp:135
+msgid "print this help menu"
+msgstr "এই সাহায্য মেনু মুদ্রণ কর"
+
+#: ../src/main.cpp:137
+#, fuzzy
+msgid "For more help please refer to the 'man 8 powertop'"
+msgstr "আরও সাহায্যের জন্য README পড়ুন দয়া করে"
+
+#: ../src/main.cpp:232
+#, c-format
+msgid "Unknown issue running workload!\n"
+msgstr ""
+
+#: ../src/main.cpp:289
+msgid "PowerTOP is out of memory. PowerTOP is Aborting"
+msgstr "পাওষ়ারটপ মেমরি হয়ে গেছে । পাওষ়ারটপ বাতিল করছে"
+
+#. one to warm up everything
+#: ../src/main.cpp:297
+#, c-format
+msgid "Preparing to take measurements\n"
+msgstr ""
+"পরিমাপ গ্রহণ করতে প্রস্তুত \n"
+"\n"
+
+#: ../src/main.cpp:302
+#, c-format
+msgid "Taking %d measurement(s) for a duration of %d second(s) each.\n"
+msgstr "প্রতিটি %d সেকেন্ড(গুলি) এর একটি সময়কালের জন্য %d পরিমাপ(গুলি) গ্রহণ করছে\n"
+
+#: ../src/main.cpp:304
+#, c-format
+msgid "Measuring workload %s.\n"
+msgstr ""
+
+#: ../src/main.cpp:329
+#, c-format
+msgid "PowerTOP "
+msgstr "পাওষ়ারটপ "
+
+#: ../src/main.cpp:330 ../src/main.cpp:380
+#, c-format
+msgid "exiting...\n"
+msgstr ""
+"প্রস্থান করছে...\n"
+"\n"
+
+#: ../src/main.cpp:364
+#, c-format
+msgid "modprobe cpufreq_stats failed"
+msgstr ""
+
+#: ../src/main.cpp:367
+#, c-format
+msgid "modprobe msr failed"
+msgstr ""
+
+#: ../src/main.cpp:379 ../src/main.cpp:383
+#, c-format
+msgid "Failed to mount debugfs!\n"
+msgstr ""
+"debugfs মাউন্ট করতে ব্যর্থ!\n"
+"\n"
+
+#: ../src/main.cpp:384
+#, c-format
+msgid "Should still be able to auto tune...\n"
+msgstr ""
+
+#: ../src/main.cpp:466
+#, c-format
+msgid "Invalid CSV filename\n"
+msgstr ""
+
+#: ../src/main.cpp:482
+#, c-format
+msgid "Invalid HTML filename\n"
+msgstr ""
+
+#: ../src/main.cpp:491
+#, c-format
+msgid "Quiet mode failed!\n"
+msgstr ""
+
+#: ../src/main.cpp:559
+msgid "Leaving PowerTOP"
+msgstr "পাওষ়ারটপ বন্ধ হচেছ"
+
+#: ../src/parameters/persistent.cpp:46 ../src/parameters/persistent.cpp:155
+msgid "Cannot save to file"
+msgstr ""
+
+#: ../src/parameters/persistent.cpp:89 ../src/parameters/persistent.cpp:180
+msgid "Cannot load from file"
+msgstr ""
+
+#. '%i" is for count, do not translate
+#: ../src/parameters/persistent.cpp:138
+#, c-format
+msgid "Loaded %i prior measurements\n"
+msgstr ""
+"লোডকৃত %i আগের পরিমাপ\n"
+"\n"
+
+#: ../src/parameters/persistent.cpp:181
+msgid ""
+"File will be loaded after taking minimum number of measurement(s) with "
+"battery only \n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:115
+#, c-format
+msgid ""
+"Too many open files, please increase the limit of open file descriptors.\n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:117
+#, c-format
+msgid "PowerTOP %s needs the kernel to support the 'perf' subsystem\n"
+msgstr ""
+"PowerTOP %s 'perf' সাবসিস্টেম সমর্থন করতে কার্নেল প্রয়োজন বোধ করে\n"
+"\n"
+
+#: ../src/perf/perf.cpp:118
+#, c-format
+msgid "as well as support for trace points in the kernel:\n"
+msgstr ""
+"কার্নেলে ছাপ বিন্দুর জন্য সমর্থন হিসেবে যত ভাল:\n"
+"\n"
+
+#: ../src/process/do_process.cpp:819
+#, c-format
+msgid ""
+"Estimated power: %5.1f Measured power: %5.1f Sum: %5.1f\n"
+"\n"
+msgstr ""
+"Estimated power: %5.1f Measured power: %5.1f Sum: %5.1f\n"
+"\n"
+
+#: ../src/process/do_process.cpp:838
+#, c-format
+msgid "The estimated remaining time is %i hours, %i minutes\n"
+msgstr ""
+"আনুমানিক অবশিষ্ট সময় হল %i ঘন্টা, %i মিনিট\n"
+"\n"
+"\n"
+
+#: ../src/process/do_process.cpp:846
+msgid "Summary"
+msgstr "সারাংশ"
+
+#: ../src/process/do_process.cpp:846
+msgid "wakeups/second"
+msgstr "ওষ়েকআপস/সেকেন্ড"
+
+#: ../src/process/do_process.cpp:846
+msgid "GPU ops/seconds"
+msgstr "জিপিইউ ops/সেকেন্ড"
+
+#: ../src/process/do_process.cpp:846
+msgid "VFS ops/sec and"
+msgstr "ভিএফএস OPS / সেকেন্ড এবং"
+
+#: ../src/process/do_process.cpp:846
+msgid "CPU use"
+msgstr "সিপিইউ-র ব্যবহার"
+
+#: ../src/process/do_process.cpp:850
+msgid "Power est."
+msgstr "শক্তি অনুমান"
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:1078
+msgid "Events/s"
+msgstr "ইভেন্টস / গুলি"
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:931 ../src/process/do_process.cpp:1079
+msgid "Category"
+msgstr "বিভাগ"
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:932 ../src/process/do_process.cpp:1080
+#: ../src/tuning/tuning.cpp:242 ../src/tuning/tuning.cpp:270
+#: ../src/tuning/tuning.cpp:288 ../src/wakeup/waketab.cpp:155
+msgid "Description"
+msgstr "বিবরণ"
+
+#: ../src/process/do_process.cpp:927
+msgid "Wakeups/s"
+msgstr "ওষ়েকআপস/ গুলি"
+
+#: ../src/process/do_process.cpp:928
+msgid "GPU ops/s"
+msgstr "জিপিইউ ops/ গুলি"
+
+#: ../src/process/do_process.cpp:929
+msgid "Disk IO/s"
+msgstr "ডিস্ক IO / গুলি"
+
+#: ../src/process/do_process.cpp:930
+msgid "GFX Wakeups/s"
+msgstr "GFX ওষ়েকআপস/ গুলি"
+
+#: ../src/process/do_process.cpp:1017
+msgid "Overview of Software Power Consumers"
+msgstr "সফ্টওয়্যার পাওয়ার কনজিউমার্স রূপরেখা"
+
+#: ../src/process/do_process.cpp:1057
+msgid "Target:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1058
+msgid "1 units/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1059
+msgid "System: "
+msgstr ""
+
+#: ../src/process/do_process.cpp:1061
+#, fuzzy
+msgid " wakeup/s"
+msgstr "ওষ়েকআপস/ গুলি"
+
+#: ../src/process/do_process.cpp:1062
+msgid "CPU: "
+msgstr ""
+
+#: ../src/process/do_process.cpp:1064
+#, fuzzy, c-format
+msgid "% usage"
+msgstr "ব্যবহার"
+
+#: ../src/process/do_process.cpp:1065
+msgid "GPU:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1067 ../src/process/do_process.cpp:1073
+#, fuzzy
+msgid " ops/s"
+msgstr "জিপিইউ ops/ গুলি"
+
+#: ../src/process/do_process.cpp:1068
+msgid "GFX:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1070
+#, fuzzy
+msgid " wakeups/s"
+msgstr "ওষ়েকআপস/ গুলি"
+
+#: ../src/process/do_process.cpp:1071
+msgid "VFS:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1139
+#, fuzzy
+msgid "Top 10 Power Consumers"
+msgstr "সফ্টওয়্যার পাওয়ার কনজিউমার্স রূপরেখা"
+
+#: ../src/report/report.cpp:122
+#, fuzzy
+msgid "PowerTOP Version"
+msgstr "পাওষ়ারটপ অনুবাদ"
+
+#: ../src/report/report.cpp:131
+#, fuzzy
+msgid "Kernel Version"
+msgstr "পাওষ়ারটপ অনুবাদ"
+
+#: ../src/report/report.cpp:135
+msgid "System Name"
+msgstr ""
+
+#: ../src/report/report.cpp:142
+msgid "CPU Information"
+msgstr ""
+
+#: ../src/report/report.cpp:154
+msgid "OS Information"
+msgstr ""
+
+#: ../src/report/report.cpp:161
+#, fuzzy
+msgid "System Information"
+msgstr "প্রিন্ট সংস্করণ সংক্রান্ত তথ্য"
+
+#: ../src/report/report.cpp:195
+#, fuzzy, c-format
+msgid "Cannot open output file %s (%s)\n"
+msgstr "সাময়িক ফাইল তৈরি করতে পারবেন না\n"
+
+#: ../src/report/report.cpp:211
+#, c-format
+msgid "PowerTOP outputing using base filename %s\n"
+msgstr ""
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:49
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+msgid "Good"
+msgstr "ভাল"
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:50
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+msgid "Bad"
+msgstr "খারাপ"
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:51
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+#: ../src/wakeup/wakeup.cpp:50
+msgid "Unknown"
+msgstr "অজানা"
+
+#: ../src/tuning/bluetooth.cpp:48
+#, c-format
+msgid "Bluetooth device interface status"
+msgstr "ব্লুটুথ ডিভাইসের ইন্টারফেস অবস্থা"
+
+#: ../src/tuning/ethernet.cpp:54 ../src/wakeup/wakeup_ethernet.cpp:51
+#, c-format
+msgid "Wake-on-lan status for device %s"
+msgstr "ডিভাইস %sএর জন্য LAN অবস্থা অন কর"
+
+#: ../src/tuning/runtime.cpp:48
+#, c-format
+msgid "Runtime PM for %s device %s"
+msgstr "Runtime PM for %s device %s"
+
+#: ../src/tuning/runtime.cpp:50
+#, c-format
+msgid "%s device %s has no runtime power management"
+msgstr "%s device %s has no runtime power management"
+
+#: ../src/tuning/runtime.cpp:74
+#, c-format
+msgid "PCI Device %s has no runtime power management"
+msgstr "PCI Device %s has no runtime power management"
+
+#: ../src/tuning/runtime.cpp:76
+#, c-format
+msgid "Runtime PM for PCI Device %s"
+msgstr "পিসিআই ডিভাইস %sএর জন্য রানটাইম PM"
+
+#: ../src/tuning/tuning.cpp:62
+msgid "Enable Audio codec power management"
+msgstr "অডিও কোডেকর অধিকার ব্যবস্থাপনা সক্রিয় করুন"
+
+#: ../src/tuning/tuning.cpp:63
+msgid "NMI watchdog should be turned off"
+msgstr "NMI পাহরাদার বন্ধ করা উচিত"
+
+#: ../src/tuning/tuning.cpp:64
+msgid "Power Aware CPU scheduler"
+msgstr "সিপিইউ সময়-তালিকা নির্ধারণ ব্যবস্থার বিদ্যুৎ সচেতন"
+
+#: ../src/tuning/tuning.cpp:65
+msgid "VM writeback timeout"
+msgstr "VM writeback সময়সীমা"
+
+#: ../src/tuning/tuning.cpp:81
+msgid "Tunables"
+msgstr "সুরেলা "
+
+#: ../src/tuning/tuning.cpp:81
+msgid " <ESC> Exit | <Enter> Toggle tunable | <r> Window refresh"
+msgstr " <ESC> থেকে প্রস্থান করুন | <Enter> টগল করুন সুরেলা | <r> উইন্ডো রিফ্রেশ করুন"
+
+#: ../src/tuning/tuning.cpp:243 ../src/wakeup/waketab.cpp:156
+msgid "Script"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:257
+msgid "Software Settings in Need of Tuning"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:276
+msgid "Untunable Software Issues"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:300
+msgid "Optimal Tuned Software Settings"
+msgstr ""
+
+#: ../src/tuning/tuningi2c.cpp:57
+#, fuzzy, c-format
+msgid "Runtime PM for I2C %s %s (%s)"
+msgstr "Runtime PM for %s device %s"
+
+#: ../src/tuning/tuningi2c.cpp:59
+#, fuzzy, c-format
+msgid "I2C %s %s has no runtime power management"
+msgstr "%s device %s has no runtime power management"
+
+#: ../src/tuning/tuningsysfs.cpp:123
+#, fuzzy, c-format
+msgid "Enable SATA link power management for %s"
+msgstr "অডিও কোডেকর অধিকার ব্যবস্থাপনা সক্রিয় করুন"
+
+#: ../src/tuning/tuningusb.cpp:54
+#, c-format
+msgid "Autosuspend for unknown USB device %s (%s:%s)"
+msgstr "অজানা ইউএসবি ডিভাইস %s.(%s: %s) এর জন্য Autosuspend"
+
+#: ../src/tuning/tuningusb.cpp:71 ../src/tuning/tuningusb.cpp:73
+#: ../src/tuning/tuningusb.cpp:75
+#, c-format
+msgid "Autosuspend for USB device %s [%s]"
+msgstr "ইউএসবি ডিভাইস %s[%s] এর জন্য Autosuspend "
+
+#: ../src/tuning/wifi.cpp:48
+#, c-format
+msgid "Wireless Power Saving for interface %s"
+msgstr "Wireless Power Saving for interface %s"
+
+#: ../src/wakeup/waketab.cpp:42
+#, fuzzy
+msgid "WakeUp"
+msgstr "ওষ়েকআপস/ গুলি"
+
+#: ../src/wakeup/waketab.cpp:42
+#, fuzzy
+msgid " <ESC> Exit | <Enter> Toggle wakeup | <r> Window refresh"
+msgstr " <ESC> থেকে প্রস্থান করুন | <Enter> টগল করুন সুরেলা | <r> উইন্ডো রিফ্রেশ করুন"
+
+#. Report Output
+#: ../src/wakeup/waketab.cpp:170
+#, fuzzy
+msgid "Wake status of the devices"
+msgstr "ডিভাইস %sএর জন্য LAN অবস্থা অন কর"
+
+#: ../src/wakeup/wakeup.cpp:48 ../src/wakeup/wakeup_ethernet.cpp:47
+#: ../src/wakeup/wakeup_usb.cpp:47
+#, fuzzy
+msgid "Enable"
+msgstr "সুরেলা "
+
+#: ../src/wakeup/wakeup.cpp:49 ../src/wakeup/wakeup_ethernet.cpp:47
+#: ../src/wakeup/wakeup_usb.cpp:47
+msgid "Disable"
+msgstr ""
+
+#: ../src/wakeup/wakeup_usb.cpp:51
+#, fuzzy, c-format
+msgid "Wake status for USB device %s"
+msgstr "ডিভাইস %sএর জন্য LAN অবস্থা অন কর"
+
+#~ msgid "Actual"
+#~ msgstr "প্রকৃত"
+
+#~ msgid "Power Consumption Summary"
+#~ msgstr "বিদ্যুত ব্যবহার সারাংশ"
+
+#~ msgid "GPU ops/second"
+#~ msgstr "জিপিইউ ops/সেকেন্ড"
+
+#~ msgid "VFS ops/sec"
+#~ msgstr "VFS ops/sec"
+
+#~ msgid "GFX wakes/sec and"
+#~ msgstr "ভিএফএস OPS / সেকেন্ড "
+
+#~ msgid "Using 'ondemand' cpufreq governor"
+#~ msgstr "'ondemand' cpufreq গভর্নর ব্যবহার করছে"
+
+#~ msgid "[=FILENAME]"
+#~ msgstr "[=ফাইলনেইম]"
diff --git a/po/ca.po b/po/ca.po
new file mode 100644
index 0000000..3f66c8e
--- /dev/null
+++ b/po/ca.po
@@ -0,0 +1,975 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Intel Corporation
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# capimans, 2012
+# Il_Tifossi <lluita_i_no_dorm@hotmail.com>, 2011
+# Juanma Hernández <juanmah@gmail.com>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: PowerTOP\n"
+"Report-Msgid-Bugs-To: \"powertop@lists.01.org\"\n"
+"POT-Creation-Date: 2022-09-29 04:45-0700\n"
+"PO-Revision-Date: 2013-11-05 08:40+0000\n"
+"Last-Translator: Margie Foster <margie@linux.intel.com>\n"
+"Language-Team: Catalan (http://www.transifex.com/projects/p/PowerTOP/"
+"language/ca/)\n"
+"Language: ca\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/calibrate/calibrate.cpp:238
+#, c-format
+msgid "Cannot create temp file\n"
+msgstr "No es pot crear el fitxer temporal\n"
+
+#: src/calibrate/calibrate.cpp:258
+#, c-format
+msgid "Calibrating: CPU usage on %i threads\n"
+msgstr "Calibrant: ús de CPU en %i discussions\n"
+
+#: src/calibrate/calibrate.cpp:273
+#, c-format
+msgid "Calibrating: CPU wakeup power consumption\n"
+msgstr "Calibrant: consum d'energia de l'encesa de CPU\n"
+
+#: src/calibrate/calibrate.cpp:290
+#, c-format
+msgid "Calibrating USB devices\n"
+msgstr "Calibrant dispositius USB\n"
+
+#: src/calibrate/calibrate.cpp:292 src/calibrate/calibrate.cpp:309
+#: src/calibrate/calibrate.cpp:317 src/calibrate/calibrate.cpp:334
+#, c-format
+msgid ".... device %s \n"
+msgstr ".... dispositiu %s\n"
+
+#: src/calibrate/calibrate.cpp:307
+#, c-format
+msgid "Calibrating radio devices\n"
+msgstr "Calibrant dispositius de ràdio\n"
+
+#: src/calibrate/calibrate.cpp:331
+#, c-format
+msgid "Calibrating backlight\n"
+msgstr "Calibrant llum de fons\n"
+
+#: src/calibrate/calibrate.cpp:355 src/calibrate/calibrate.cpp:365
+#, c-format
+msgid "Calibrating idle\n"
+msgstr "Calibrant repòs\n"
+
+#: src/calibrate/calibrate.cpp:378
+#, c-format
+msgid "Calibrating: disk usage \n"
+msgstr "Calibrant: ús de disc\n"
+
+#: src/calibrate/calibrate.cpp:403
+msgid "Starting PowerTOP power estimate calibration \n"
+msgstr "Iniciant calibrat d'estimació d'energia PowerTOP\n"
+
+#: src/calibrate/calibrate.cpp:426
+msgid "Finishing PowerTOP power estimate calibration \n"
+msgstr "Finalitzant calibració d'estimació d'energia de PowerTOP\n"
+
+#: src/calibrate/calibrate.cpp:430
+#, c-format
+msgid "Parameters after calibration:\n"
+msgstr "Paràmetres després del calibrat:\n"
+
+#: src/cpu/abstract_cpu.cpp:74
+msgid "Idle"
+msgstr ""
+
+#: src/cpu/abstract_cpu.cpp:76
+msgid "Turbo Mode"
+msgstr ""
+
+#: src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(HW)"
+msgstr ""
+
+#: src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(OS)"
+msgstr ""
+
+#: src/cpu/cpu_core.cpp:91 src/cpu/intel_cpus.cpp:367
+#, c-format
+msgid " Core"
+msgstr ""
+
+#: src/cpu/cpu.cpp:85
+#, c-format
+msgid "cpu package %i"
+msgstr "Paquet CPU %i"
+
+#: src/cpu/cpu.cpp:86
+msgid "cpu package"
+msgstr "paquet cpu"
+
+#: src/cpu/cpu.cpp:89 src/cpu/cpu.cpp:96
+#, fuzzy, c-format
+msgid "package-%i"
+msgstr "Paquet CPU %i"
+
+#: src/cpu/cpu.cpp:90
+msgid "cpu rapl package"
+msgstr ""
+
+#: src/cpu/cpu.cpp:97
+msgid "dram rapl package"
+msgstr ""
+
+#: src/cpu/cpu.cpp:471
+msgid "Processor Idle State Report"
+msgstr ""
+
+#: src/cpu/cpu.cpp:535 src/cpu/cpu.cpp:761
+msgid "Package"
+msgstr ""
+
+#: src/cpu/cpu.cpp:572 src/cpu/cpu.cpp:783
+#, c-format
+msgid "Core %d"
+msgstr ""
+
+#: src/cpu/cpu.cpp:579
+#, c-format
+msgid "GPU %d"
+msgstr ""
+
+#: src/cpu/cpu.cpp:602
+msgid "CPU"
+msgstr ""
+
+#: src/cpu/cpu.cpp:684
+msgid "Processor Frequency Report"
+msgstr ""
+
+#: src/cpu/cpu.cpp:804
+#, c-format
+msgid "CPU %d"
+msgstr ""
+
+#: src/cpu/cpu.cpp:1005
+#, c-format
+msgid "cpu_idle event returned no state?\n"
+msgstr "l'event cpu_idle no ha retornat cap estat?\n"
+
+#: src/cpu/cpu.cpp:1020
+#, c-format
+msgid "power or cpu_frequency event returned no state?\n"
+msgstr ""
+
+#: src/cpu/cpu_linux.cpp:79
+msgid "C0 polling"
+msgstr "C0 sondejant"
+
+#: src/cpu/cpu_linux.cpp:242
+#, c-format
+msgid " CPU(OS) %i"
+msgstr ""
+
+#: src/cpu/cpu_linux.cpp:341 src/cpu/intel_cpus.cpp:733
+#, c-format
+msgid " CPU %i"
+msgstr ""
+
+#: src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(HW)"
+msgstr ""
+
+#: src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(OS)"
+msgstr ""
+
+#: src/cpu/cpu_package.cpp:104 src/cpu/intel_cpus.cpp:498
+#, c-format
+msgid " Package"
+msgstr ""
+
+#: src/cpu/intel_cpus.cpp:152
+#, c-format
+msgid "read_msr cpu%d 0x%llx : "
+msgstr ""
+
+#: src/cpu/intel_cpus.cpp:656
+msgid "C0 active"
+msgstr "C0 actiu"
+
+#: src/cpu/intel_cpus.cpp:714
+#, c-format
+msgid "Average"
+msgstr ""
+
+#: src/cpu/intel_gpu.cpp:64
+#, c-format
+msgid " GPU "
+msgstr ""
+
+#: src/devices/ahci.cpp:154
+#, c-format
+msgid "SATA link: %s"
+msgstr "Connexió SATA: %s"
+
+#: src/devices/ahci.cpp:156
+#, c-format
+msgid "SATA disk: %s"
+msgstr "Disc SATA: %s"
+
+#: src/devices/ahci.cpp:374
+msgid "AHCI ALPM Residency Statistics - Not supported on this macine"
+msgstr ""
+
+#: src/devices/ahci.cpp:389
+msgid "Link"
+msgstr ""
+
+#: src/devices/ahci.cpp:390
+#, fuzzy
+msgid "Active"
+msgstr "C0 actiu"
+
+#: src/devices/ahci.cpp:391
+msgid "Partial"
+msgstr ""
+
+#: src/devices/ahci.cpp:392
+msgid "Slumber"
+msgstr ""
+
+#: src/devices/ahci.cpp:393
+msgid "Devslp"
+msgstr ""
+
+#: src/devices/ahci.cpp:399
+msgid "AHCI ALPM Residency Statistics"
+msgstr ""
+
+#: src/devices/alsa.cpp:77
+#, c-format
+msgid "Audio codec %s: %s (%s)"
+msgstr "Còdec d'àudio %s: %s (%s)"
+
+#: src/devices/alsa.cpp:79 src/devices/alsa.cpp:81
+#, c-format
+msgid "Audio codec %s: %s"
+msgstr "Còdec d'àudio %s: %s"
+
+#: src/devices/devfreq.cpp:260
+#, fuzzy
+msgid "Device Freq stats"
+msgstr "Estadístiques del dispositiu"
+
+#: src/devices/devfreq.cpp:278
+msgid " Devfreq is not enabled"
+msgstr ""
+
+#: src/devices/devfreq.cpp:283
+msgid " No devfreq devices available"
+msgstr ""
+
+#: src/devices/device.cpp:172 src/process/do_process.cpp:831
+#, c-format
+msgid "The battery reports a discharge rate of %sW\n"
+msgstr "La bateria reporta un nivell de descàrrega de %sW\n"
+
+#: src/devices/device.cpp:174 src/process/do_process.cpp:833
+#, c-format
+msgid "The energy consumed was %sJ\n"
+msgstr ""
+
+#: src/devices/device.cpp:180
+#, c-format
+msgid "System baseline power is estimated at %sW\n"
+msgstr "La línia base d'energia del sistema està estimada en %sW\n"
+
+#: src/devices/device.cpp:187
+msgid "Power est. Usage Device name\n"
+msgstr "Energia est. Ús Nom del dispositiu\n"
+
+#: src/devices/device.cpp:189
+msgid " Usage Device name\n"
+msgstr " Ús Nom del dispositiu\n"
+
+#: src/devices/device.cpp:256
+#, fuzzy
+msgid "The battery reports a discharge rate of: "
+msgstr "La bateria reporta un nivell de descàrrega de %sW\n"
+
+#: src/devices/device.cpp:261
+msgid "The energy consumed was : "
+msgstr ""
+
+#: src/devices/device.cpp:268
+#, fuzzy
+msgid "The system baseline power is estimated at: "
+msgstr "La línia base d'energia del sistema està estimada en %sW\n"
+
+#: src/devices/device.cpp:277 src/process/do_process.cpp:850
+#: src/process/do_process.cpp:852 src/process/do_process.cpp:926
+#: src/process/do_process.cpp:1077
+msgid "Usage"
+msgstr ""
+
+#: src/devices/device.cpp:278
+#, fuzzy
+msgid "Device Name"
+msgstr "Estadístiques del dispositiu"
+
+#: src/devices/device.cpp:280 src/process/do_process.cpp:935
+#: src/process/do_process.cpp:1082
+msgid "PW Estimate"
+msgstr ""
+
+#: src/devices/device.cpp:317
+msgid "Device Power Report"
+msgstr ""
+
+#: src/devices/network.cpp:177
+#, c-format
+msgid "Network interface: %s (%s)"
+msgstr "Interfície de xarxa: %s(%s)"
+
+#: src/devices/rfkill.cpp:65 src/devices/rfkill.cpp:69
+#, c-format
+msgid "Radio device: %s"
+msgstr "Dispositiu de ràdio: %s"
+
+#: src/devices/runtime_pm.cpp:216
+#, c-format
+msgid "I2C %s (%s): %s"
+msgstr ""
+
+#: src/devices/runtime_pm.cpp:216 src/tuning/tuningi2c.cpp:57
+#: src/tuning/tuningi2c.cpp:59
+msgid "Adapter"
+msgstr ""
+
+#: src/devices/runtime_pm.cpp:216 src/devlist.cpp:331
+#: src/tuning/tuningi2c.cpp:57 src/tuning/tuningi2c.cpp:59
+#, fuzzy
+msgid "Device"
+msgstr "Estadístiques del dispositiu"
+
+#: src/devices/runtime_pm.cpp:241
+#, c-format
+msgid "PCI Device: %s"
+msgstr "Dispositiu PCI: %s"
+
+#: src/devices/usb.cpp:51 src/devices/usb.cpp:96 src/devices/usb.cpp:98
+#, c-format
+msgid "USB device: %s"
+msgstr "Dispositiu USB: %s"
+
+#: src/devices/usb.cpp:94
+#, c-format
+msgid "USB device: %s (%s)"
+msgstr "Dispositiu USB: %s (%s)"
+
+#: src/devlist.cpp:330
+msgid "Process"
+msgstr ""
+
+#: src/devlist.cpp:347
+msgid "Process Device Activity"
+msgstr ""
+
+#: src/display.cpp:70
+msgid "Overview"
+msgstr "Informació general"
+
+#: src/display.cpp:71
+msgid "Idle stats"
+msgstr "Estadístiques de repòs"
+
+#: src/display.cpp:72
+msgid "Frequency stats"
+msgstr "Estadístiques de freqüència"
+
+#: src/display.cpp:73
+msgid "Device stats"
+msgstr "Estadístiques del dispositiu"
+
+#: src/display.cpp:131
+msgid "Exit"
+msgstr "Surt"
+
+#: src/display.cpp:132
+msgid "Navigate"
+msgstr ""
+
+#: src/lib.cpp:288
+#, c-format
+msgid "%7sW"
+msgstr "%7sW"
+
+#: src/lib.cpp:291
+#, c-format
+msgid " 0 mW"
+msgstr " 0 mW"
+
+#: src/lib.cpp:410
+msgid "PS/2 Touchpad / Keyboard / Mouse"
+msgstr "PS/2 Touchpad / Teclat / Ratolí"
+
+#: src/lib.cpp:411
+msgid "SATA controller"
+msgstr "Controlador SATA"
+
+#: src/lib.cpp:412
+msgid "Intel built in USB hub"
+msgstr "Intel connectat a port USB"
+
+#: src/lib.cpp:467
+#, c-format
+msgid "glob returned GLOB_NOSPACE\n"
+msgstr ""
+
+#: src/lib.cpp:471
+#, c-format
+msgid "glob returned GLOB_ABORTED\n"
+msgstr ""
+
+#: src/lib.cpp:475
+#, c-format
+msgid "glob returned GLOB_NOMATCH\n"
+msgstr ""
+
+#: src/lib.cpp:513 src/lib.cpp:549
+#, c-format
+msgid ""
+"Model-specific registers (MSR)\t\t\t not found (try enabling "
+"CONFIG_X86_MSR).\n"
+msgstr ""
+
+#: src/main.cpp:104
+#, fuzzy, c-format
+msgid "PowerTOP version "
+msgstr "PowerTOP "
+
+#: src/main.cpp:110
+msgid "Set refresh time out"
+msgstr ""
+
+#: src/main.cpp:123
+msgid "Usage: powertop [OPTIONS]"
+msgstr ""
+
+#: src/main.cpp:124
+msgid "sets all tunable options to their GOOD setting"
+msgstr ""
+
+#: src/main.cpp:125
+msgid "runs powertop in calibration mode"
+msgstr ""
+
+#: src/main.cpp:126 src/main.cpp:129
+msgid "[=filename]"
+msgstr ""
+
+#: src/main.cpp:126
+msgid "generate a csv report"
+msgstr ""
+
+#: src/main.cpp:127
+msgid "run in \"debug\" mode"
+msgstr ""
+
+#: src/main.cpp:128
+msgid "[=devnode]"
+msgstr ""
+
+#: src/main.cpp:128
+msgid "uses an Extech Power Analyzer for measurements"
+msgstr ""
+
+#: src/main.cpp:129
+msgid "generate a html report"
+msgstr ""
+
+#: src/main.cpp:130
+msgid "[=iterations] number of times to run each test"
+msgstr ""
+
+#: src/main.cpp:131
+msgid "suppress stderr output"
+msgstr ""
+
+#: src/main.cpp:132 src/main.cpp:133
+msgid "[=seconds]"
+msgstr ""
+
+#: src/main.cpp:132
+msgid "interval for power consumption measurement"
+msgstr ""
+
+#: src/main.cpp:133
+msgid "generate a report for 'x' seconds"
+msgstr ""
+
+#: src/main.cpp:134
+msgid "[=workload]"
+msgstr ""
+
+#: src/main.cpp:134
+msgid "file to execute for workload"
+msgstr ""
+
+#: src/main.cpp:135
+msgid "print version information"
+msgstr ""
+
+#: src/main.cpp:136
+msgid "print this help menu"
+msgstr ""
+
+#: src/main.cpp:138
+msgid "For more help please refer to the 'man 8 powertop'"
+msgstr ""
+
+#: src/main.cpp:233
+#, c-format
+msgid "Unknown issue running workload!\n"
+msgstr ""
+
+#: src/main.cpp:290
+msgid "PowerTOP is out of memory. PowerTOP is Aborting"
+msgstr ""
+
+#: src/main.cpp:298
+#, c-format
+msgid "Preparing to take measurements\n"
+msgstr ""
+
+#: src/main.cpp:303
+#, c-format
+msgid "Taking %d measurement(s) for a duration of %d second(s) each.\n"
+msgstr ""
+
+#: src/main.cpp:305
+#, c-format
+msgid "Measuring workload %s.\n"
+msgstr ""
+
+#: src/main.cpp:330
+#, c-format
+msgid "PowerTOP "
+msgstr "PowerTOP "
+
+#: src/main.cpp:331 src/main.cpp:381
+#, c-format
+msgid "exiting...\n"
+msgstr "sortint...\n"
+
+#: src/main.cpp:365
+#, c-format
+msgid "modprobe cpufreq_stats failed\n"
+msgstr ""
+
+#: src/main.cpp:368
+#, c-format
+msgid "modprobe msr failed\n"
+msgstr ""
+
+#: src/main.cpp:380 src/main.cpp:384
+#, c-format
+msgid "Failed to mount debugfs!\n"
+msgstr ""
+
+#: src/main.cpp:385
+#, c-format
+msgid "Should still be able to auto tune...\n"
+msgstr ""
+
+#: src/main.cpp:467
+#, c-format
+msgid "Invalid CSV filename\n"
+msgstr ""
+
+#: src/main.cpp:483
+#, c-format
+msgid "Invalid HTML filename\n"
+msgstr ""
+
+#: src/main.cpp:492
+#, c-format
+msgid "Quiet mode failed!\n"
+msgstr ""
+
+#: src/main.cpp:560
+msgid "Leaving PowerTOP"
+msgstr ""
+
+#: src/parameters/persistent.cpp:46 src/parameters/persistent.cpp:155
+msgid "Cannot save to file"
+msgstr ""
+
+#: src/parameters/persistent.cpp:89 src/parameters/persistent.cpp:180
+msgid "Cannot load from file"
+msgstr ""
+
+#: src/parameters/persistent.cpp:138
+#, c-format
+msgid "Loaded %i prior measurements\n"
+msgstr "Últimes mesuracions de %i carregades\n"
+
+#: src/parameters/persistent.cpp:181
+msgid ""
+"File will be loaded after taking minimum number of measurement(s) with "
+"battery only \n"
+msgstr ""
+
+#: src/perf/perf.cpp:115
+#, c-format
+msgid ""
+"Too many open files, please increase the limit of open file descriptors.\n"
+msgstr ""
+
+#: src/perf/perf.cpp:117
+#, c-format
+msgid "PowerTOP %s needs the kernel to support the 'perf' subsystem\n"
+msgstr "PowerTOP %s necessita que el kernel suporti el subsistema 'perf'\n"
+
+#: src/perf/perf.cpp:118
+#, c-format
+msgid "as well as support for trace points in the kernel:\n"
+msgstr "així com suport per a punts de seguiment en el kernel:\n"
+
+#: src/process/do_process.cpp:819
+#, c-format
+msgid ""
+"Estimated power: %5.1f Measured power: %5.1f Sum: %5.1f\n"
+"\n"
+msgstr ""
+"Potència estimada: %5.1f Potència mesurada: %5.1f Suma: %5.1f\n"
+"\n"
+
+#: src/process/do_process.cpp:838
+#, c-format
+msgid "The estimated remaining time is %i hours, %i minutes\n"
+msgstr ""
+
+#: src/process/do_process.cpp:846
+msgid "Summary"
+msgstr ""
+
+#: src/process/do_process.cpp:846
+msgid "wakeups/second"
+msgstr ""
+
+#: src/process/do_process.cpp:846
+msgid "GPU ops/seconds"
+msgstr ""
+
+#: src/process/do_process.cpp:846
+msgid "VFS ops/sec and"
+msgstr ""
+
+#: src/process/do_process.cpp:846
+msgid "CPU use"
+msgstr ""
+
+#: src/process/do_process.cpp:850
+msgid "Power est."
+msgstr ""
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:1078
+msgid "Events/s"
+msgstr ""
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:931 src/process/do_process.cpp:1079
+msgid "Category"
+msgstr ""
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:932 src/process/do_process.cpp:1080
+#: src/tuning/tuning.cpp:242 src/tuning/tuning.cpp:270
+#: src/tuning/tuning.cpp:295 src/wakeup/waketab.cpp:155
+msgid "Description"
+msgstr ""
+
+#: src/process/do_process.cpp:927
+msgid "Wakeups/s"
+msgstr ""
+
+#: src/process/do_process.cpp:928
+msgid "GPU ops/s"
+msgstr ""
+
+#: src/process/do_process.cpp:929
+msgid "Disk IO/s"
+msgstr ""
+
+#: src/process/do_process.cpp:930
+msgid "GFX Wakeups/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1017
+msgid "Overview of Software Power Consumers"
+msgstr ""
+
+#: src/process/do_process.cpp:1057
+msgid "Target:"
+msgstr ""
+
+#: src/process/do_process.cpp:1058
+msgid "1 units/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1059
+msgid "System: "
+msgstr ""
+
+#: src/process/do_process.cpp:1061
+msgid " wakeup/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1062
+msgid "CPU: "
+msgstr ""
+
+#: src/process/do_process.cpp:1064
+#, c-format
+msgid "% usage"
+msgstr ""
+
+#: src/process/do_process.cpp:1065
+msgid "GPU:"
+msgstr ""
+
+#: src/process/do_process.cpp:1067 src/process/do_process.cpp:1073
+msgid " ops/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1068
+msgid "GFX:"
+msgstr ""
+
+#: src/process/do_process.cpp:1070
+msgid " wakeups/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1071
+msgid "VFS:"
+msgstr ""
+
+#: src/process/do_process.cpp:1139
+msgid "Top 10 Power Consumers"
+msgstr ""
+
+#: src/report/report.cpp:122
+#, fuzzy
+msgid "PowerTOP Version"
+msgstr "PowerTOP "
+
+#: src/report/report.cpp:131
+msgid "Kernel Version"
+msgstr ""
+
+#: src/report/report.cpp:135
+msgid "System Name"
+msgstr ""
+
+#: src/report/report.cpp:142
+msgid "CPU Information"
+msgstr ""
+
+#: src/report/report.cpp:154
+msgid "OS Information"
+msgstr ""
+
+#: src/report/report.cpp:161
+msgid "System Information"
+msgstr ""
+
+#: src/report/report.cpp:195
+#, fuzzy, c-format
+msgid "Cannot open output file %s (%s)\n"
+msgstr "No es pot crear el fitxer temporal\n"
+
+#: src/report/report.cpp:211
+#, c-format
+msgid "PowerTOP outputting using base filename %s\n"
+msgstr ""
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:49
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45
+msgid "Good"
+msgstr "Bo"
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:50
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45
+msgid "Bad"
+msgstr "Malament"
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:51
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45 src/wakeup/wakeup.cpp:50
+msgid "Unknown"
+msgstr "Desconegut"
+
+#: src/tuning/bluetooth.cpp:48
+#, c-format
+msgid "Bluetooth device interface status"
+msgstr "Estat de la interfície del dispositiu Bluetooth"
+
+#: src/tuning/ethernet.cpp:54 src/wakeup/wakeup_ethernet.cpp:51
+#, c-format
+msgid "Wake-on-lan status for device %s"
+msgstr "Estat Wake-on-lan per a dispositiu %s"
+
+#: src/tuning/runtime.cpp:48
+#, c-format
+msgid "Runtime PM for %s device %s"
+msgstr "Temps d'execució PM per %s dispositiu %s"
+
+#: src/tuning/runtime.cpp:50
+#, c-format
+msgid "%s device %s has no runtime power management"
+msgstr "%s dispositiu %s no té administració d'energia en el funcionament"
+
+#: src/tuning/runtime.cpp:74
+#, c-format
+msgid "PCI Device %s has no runtime power management"
+msgstr "El dispositiu PCI %s no té administració d'energia en temps d'execució"
+
+#: src/tuning/runtime.cpp:76
+#, c-format
+msgid "Runtime PM for PCI Device %s"
+msgstr "Temps d'execució PM per dispositiu PCI %s"
+
+#: src/tuning/runtime.cpp:80
+#, fuzzy, c-format
+msgid "Runtime PM for port %s of PCI device: %s"
+msgstr "Temps d'execució PM per %s dispositiu %s"
+
+#: src/tuning/runtime.cpp:83
+#, fuzzy, c-format
+msgid "Runtime PM for disk %s"
+msgstr "Temps d'execució PM per %s dispositiu %s"
+
+#: src/tuning/tuning.cpp:62
+msgid "Enable Audio codec power management"
+msgstr "Habilita administració d'energia del còdec d'àudio"
+
+#: src/tuning/tuning.cpp:63
+msgid "NMI watchdog should be turned off"
+msgstr "S'hauria d'apagar la vigilància NMI"
+
+#: src/tuning/tuning.cpp:64
+msgid "Power Aware CPU scheduler"
+msgstr "Planificador de CPU conscient d'energia"
+
+#: src/tuning/tuning.cpp:65
+msgid "VM writeback timeout"
+msgstr "Temps límint de reescriptura VM"
+
+#: src/tuning/tuning.cpp:81
+msgid "Tunables"
+msgstr "Optimitzables"
+
+#: src/tuning/tuning.cpp:81
+msgid " <ESC> Exit | <Enter> Toggle tunable | <r> Window refresh"
+msgstr "<ESC> Sortir | <ENTRAR> canvia optimitzable | <r> Actualitza finestra"
+
+#: src/tuning/tuning.cpp:243 src/wakeup/waketab.cpp:156
+msgid "Script"
+msgstr ""
+
+#: src/tuning/tuning.cpp:257
+msgid "Software Settings in Need of Tuning"
+msgstr ""
+
+#: src/tuning/tuning.cpp:276
+msgid "Untunable Software Issues"
+msgstr ""
+
+#: src/tuning/tuning.cpp:307
+msgid "Optimal Tuned Software Settings"
+msgstr ""
+
+#: src/tuning/tuningi2c.cpp:57
+#, fuzzy, c-format
+msgid "Runtime PM for I2C %s %s (%s)"
+msgstr "Temps d'execució PM per %s dispositiu %s"
+
+#: src/tuning/tuningi2c.cpp:59
+#, fuzzy, c-format
+msgid "I2C %s %s has no runtime power management"
+msgstr "%s dispositiu %s no té administració d'energia en el funcionament"
+
+#: src/tuning/tuningsysfs.cpp:123
+#, fuzzy, c-format
+msgid "Enable SATA link power management for %s"
+msgstr "Habilita administració d'energia del còdec d'àudio"
+
+#: src/tuning/tuningusb.cpp:54
+#, c-format
+msgid "Autosuspend for unknown USB device %s (%s:%s)"
+msgstr "Autosuspès per a dispositiu USB desconegut %s (%s:%s)"
+
+#: src/tuning/tuningusb.cpp:71 src/tuning/tuningusb.cpp:73
+#: src/tuning/tuningusb.cpp:75
+#, c-format
+msgid "Autosuspend for USB device %s [%s]"
+msgstr "Autosuspès per a dipositiu USB %s [%s]"
+
+#: src/tuning/wifi.cpp:48
+#, c-format
+msgid "Wireless Power Saving for interface %s"
+msgstr "Estalvi d'energia sense cable per a interfície %s"
+
+#: src/wakeup/waketab.cpp:42
+msgid "WakeUp"
+msgstr ""
+
+#: src/wakeup/waketab.cpp:42
+#, fuzzy
+msgid " <ESC> Exit | <Enter> Toggle wakeup | <r> Window refresh"
+msgstr "<ESC> Sortir | <ENTRAR> canvia optimitzable | <r> Actualitza finestra"
+
+#: src/wakeup/waketab.cpp:170
+#, fuzzy
+msgid "Wake status of the devices"
+msgstr "Estat Wake-on-lan per a dispositiu %s"
+
+#: src/wakeup/wakeup.cpp:48 src/wakeup/wakeup_ethernet.cpp:47
+#: src/wakeup/wakeup_usb.cpp:47
+#, fuzzy
+msgid "Enabled"
+msgstr "Optimitzables"
+
+#: src/wakeup/wakeup.cpp:49 src/wakeup/wakeup_ethernet.cpp:47
+#: src/wakeup/wakeup_usb.cpp:47
+msgid "Disabled"
+msgstr ""
+
+#: src/wakeup/wakeup_usb.cpp:51
+#, fuzzy, c-format
+msgid "Wake status for USB device %s"
+msgstr "Estat Wake-on-lan per a dispositiu %s"
+
+#~ msgid "Actual"
+#~ msgstr "Autèntic"
+
+#, fuzzy
+#~ msgid "I2C Device: %s"
+#~ msgstr "Dispositiu PCI: %s"
+
+#~ msgid "Using 'ondemand' cpufreq governor"
+#~ msgstr "Utilitzant governador de la freqüència CPU 'ondemand'"
diff --git a/po/cs_CZ.po b/po/cs_CZ.po
new file mode 100644
index 0000000..18cc30a
--- /dev/null
+++ b/po/cs_CZ.po
@@ -0,0 +1,1002 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Intel Corporation
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Alois Nešpor <info@aloisnespor.info>, 2013
+# Otto Bříza <otto.briza@gmail.com>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: PowerTOP\n"
+"Report-Msgid-Bugs-To: \"powertop@lists.01.org\"\n"
+"POT-Creation-Date: 2022-09-29 04:45-0700\n"
+"PO-Revision-Date: 2013-11-05 08:40+0000\n"
+"Last-Translator: Margie Foster <margie@linux.intel.com>\n"
+"Language-Team: Czech (Czech Republic) (http://www.transifex.com/projects/p/"
+"PowerTOP/language/cs_CZ/)\n"
+"Language: cs_CZ\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
+
+#: src/calibrate/calibrate.cpp:238
+#, c-format
+msgid "Cannot create temp file\n"
+msgstr "Nelze vytvořit dočasný soubor\n"
+
+#: src/calibrate/calibrate.cpp:258
+#, c-format
+msgid "Calibrating: CPU usage on %i threads\n"
+msgstr "Kalibrace: CPU použito na %i vláken\n"
+
+#: src/calibrate/calibrate.cpp:273
+#, c-format
+msgid "Calibrating: CPU wakeup power consumption\n"
+msgstr "Kalibrace: spotřeba energie na probuzení CPU\n"
+
+#: src/calibrate/calibrate.cpp:290
+#, c-format
+msgid "Calibrating USB devices\n"
+msgstr "Kalibrace USB zařízení\n"
+
+#: src/calibrate/calibrate.cpp:292 src/calibrate/calibrate.cpp:309
+#: src/calibrate/calibrate.cpp:317 src/calibrate/calibrate.cpp:334
+#, c-format
+msgid ".... device %s \n"
+msgstr ".... zařízení %s \n"
+
+#: src/calibrate/calibrate.cpp:307
+#, c-format
+msgid "Calibrating radio devices\n"
+msgstr "Kalibrace radio zařízení\n"
+
+#: src/calibrate/calibrate.cpp:331
+#, c-format
+msgid "Calibrating backlight\n"
+msgstr "Kalibrace podsvícení\n"
+
+#: src/calibrate/calibrate.cpp:355 src/calibrate/calibrate.cpp:365
+#, c-format
+msgid "Calibrating idle\n"
+msgstr "Kalibrace nečinnosti\n"
+
+#: src/calibrate/calibrate.cpp:378
+#, c-format
+msgid "Calibrating: disk usage \n"
+msgstr "Kalibrace: užití disku \n"
+
+#: src/calibrate/calibrate.cpp:403
+msgid "Starting PowerTOP power estimate calibration \n"
+msgstr "Začínání kalibrace odhadování energie PowerTOP\n"
+
+#: src/calibrate/calibrate.cpp:426
+msgid "Finishing PowerTOP power estimate calibration \n"
+msgstr "Ukončování kalibrace odhadování energie PowerTOP\n"
+
+#: src/calibrate/calibrate.cpp:430
+#, c-format
+msgid "Parameters after calibration:\n"
+msgstr "Parametry po kalibraci:\n"
+
+#: src/cpu/abstract_cpu.cpp:74
+msgid "Idle"
+msgstr ""
+
+#: src/cpu/abstract_cpu.cpp:76
+msgid "Turbo Mode"
+msgstr ""
+
+#: src/cpu/cpu_core.cpp:37
+#, fuzzy, c-format
+msgid " Core(HW)"
+msgstr " Jádro"
+
+#: src/cpu/cpu_core.cpp:37
+#, fuzzy, c-format
+msgid " Core(OS)"
+msgstr " Jádro"
+
+#: src/cpu/cpu_core.cpp:91 src/cpu/intel_cpus.cpp:367
+#, c-format
+msgid " Core"
+msgstr " Jádro"
+
+#: src/cpu/cpu.cpp:85
+#, c-format
+msgid "cpu package %i"
+msgstr "cpu svazek %i"
+
+#: src/cpu/cpu.cpp:86
+msgid "cpu package"
+msgstr "cpu svazek"
+
+#: src/cpu/cpu.cpp:89 src/cpu/cpu.cpp:96
+#, fuzzy, c-format
+msgid "package-%i"
+msgstr "Balíček %i"
+
+#: src/cpu/cpu.cpp:90
+msgid "cpu rapl package"
+msgstr ""
+
+#: src/cpu/cpu.cpp:97
+msgid "dram rapl package"
+msgstr ""
+
+#: src/cpu/cpu.cpp:471
+msgid "Processor Idle State Report"
+msgstr ""
+
+#: src/cpu/cpu.cpp:535 src/cpu/cpu.cpp:761
+msgid "Package"
+msgstr "Balíček"
+
+#: src/cpu/cpu.cpp:572 src/cpu/cpu.cpp:783
+#, fuzzy, c-format
+msgid "Core %d"
+msgstr "Jádro %i"
+
+#: src/cpu/cpu.cpp:579
+#, fuzzy, c-format
+msgid "GPU %d"
+msgstr "GPU %i"
+
+#: src/cpu/cpu.cpp:602
+#, fuzzy
+msgid "CPU"
+msgstr "GPU %i"
+
+#: src/cpu/cpu.cpp:684
+msgid "Processor Frequency Report"
+msgstr ""
+
+#: src/cpu/cpu.cpp:804
+#, fuzzy, c-format
+msgid "CPU %d"
+msgstr "GPU %i"
+
+#: src/cpu/cpu.cpp:1005
+#, c-format
+msgid "cpu_idle event returned no state?\n"
+msgstr "cpu_idle událost nevrátila stav?\n"
+
+#: src/cpu/cpu.cpp:1020
+#, c-format
+msgid "power or cpu_frequency event returned no state?\n"
+msgstr ""
+"power nebo cpu_frequecny událost nevrátila žádný stav?\n"
+"\n"
+
+#: src/cpu/cpu_linux.cpp:79
+msgid "C0 polling"
+msgstr "C0 sdílení"
+
+#: src/cpu/cpu_linux.cpp:242
+#, fuzzy, c-format
+msgid " CPU(OS) %i"
+msgstr " CPU %i"
+
+#: src/cpu/cpu_linux.cpp:341 src/cpu/intel_cpus.cpp:733
+#, c-format
+msgid " CPU %i"
+msgstr " CPU %i"
+
+#: src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(HW)"
+msgstr ""
+
+#: src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(OS)"
+msgstr ""
+
+#: src/cpu/cpu_package.cpp:104 src/cpu/intel_cpus.cpp:498
+#, c-format
+msgid " Package"
+msgstr " Balíček"
+
+#: src/cpu/intel_cpus.cpp:152
+#, c-format
+msgid "read_msr cpu%d 0x%llx : "
+msgstr ""
+
+#: src/cpu/intel_cpus.cpp:656
+msgid "C0 active"
+msgstr "C0 aktivní"
+
+#: src/cpu/intel_cpus.cpp:714
+#, c-format
+msgid "Average"
+msgstr ""
+
+#: src/cpu/intel_gpu.cpp:64
+#, fuzzy, c-format
+msgid " GPU "
+msgstr "GPU %i"
+
+#: src/devices/ahci.cpp:154
+#, c-format
+msgid "SATA link: %s"
+msgstr "SATA link: %s"
+
+#: src/devices/ahci.cpp:156
+#, c-format
+msgid "SATA disk: %s"
+msgstr "SATA disk: %s"
+
+#: src/devices/ahci.cpp:374
+msgid "AHCI ALPM Residency Statistics - Not supported on this macine"
+msgstr ""
+
+#: src/devices/ahci.cpp:389
+msgid "Link"
+msgstr ""
+
+#: src/devices/ahci.cpp:390
+#, fuzzy
+msgid "Active"
+msgstr "C0 aktivní"
+
+#: src/devices/ahci.cpp:391
+msgid "Partial"
+msgstr ""
+
+#: src/devices/ahci.cpp:392
+msgid "Slumber"
+msgstr ""
+
+#: src/devices/ahci.cpp:393
+msgid "Devslp"
+msgstr ""
+
+#: src/devices/ahci.cpp:399
+msgid "AHCI ALPM Residency Statistics"
+msgstr ""
+
+#: src/devices/alsa.cpp:77
+#, c-format
+msgid "Audio codec %s: %s (%s)"
+msgstr "Audio kodek %s: %s (%s)"
+
+#: src/devices/alsa.cpp:79 src/devices/alsa.cpp:81
+#, c-format
+msgid "Audio codec %s: %s"
+msgstr "Audio kodek %s: %s"
+
+#: src/devices/devfreq.cpp:260
+#, fuzzy
+msgid "Device Freq stats"
+msgstr "Zařízení"
+
+#: src/devices/devfreq.cpp:278
+msgid " Devfreq is not enabled"
+msgstr ""
+
+#: src/devices/devfreq.cpp:283
+msgid " No devfreq devices available"
+msgstr ""
+
+#: src/devices/device.cpp:172 src/process/do_process.cpp:831
+#, c-format
+msgid "The battery reports a discharge rate of %sW\n"
+msgstr "Spotřeba při chodu na baterii: %sW\n"
+
+#: src/devices/device.cpp:174 src/process/do_process.cpp:833
+#, c-format
+msgid "The energy consumed was %sJ\n"
+msgstr ""
+
+#: src/devices/device.cpp:180
+#, c-format
+msgid "System baseline power is estimated at %sW\n"
+msgstr "Systém základního napájení je odhadován na %sW\n"
+
+#: src/devices/device.cpp:187
+msgid "Power est. Usage Device name\n"
+msgstr "Energie zbývá Použití Jméno zařízení\n"
+
+#: src/devices/device.cpp:189
+msgid " Usage Device name\n"
+msgstr " Použití Jméno zařízení\n"
+
+#: src/devices/device.cpp:256
+#, fuzzy
+msgid "The battery reports a discharge rate of: "
+msgstr "Spotřeba při chodu na baterii: %sW\n"
+
+#: src/devices/device.cpp:261
+msgid "The energy consumed was : "
+msgstr ""
+
+#: src/devices/device.cpp:268
+#, fuzzy
+msgid "The system baseline power is estimated at: "
+msgstr "Systém základního napájení je odhadován na %sW\n"
+
+#: src/devices/device.cpp:277 src/process/do_process.cpp:850
+#: src/process/do_process.cpp:852 src/process/do_process.cpp:926
+#: src/process/do_process.cpp:1077
+msgid "Usage"
+msgstr "Využití"
+
+#: src/devices/device.cpp:278
+#, fuzzy
+msgid "Device Name"
+msgstr "Zařízení"
+
+#: src/devices/device.cpp:280 src/process/do_process.cpp:935
+#: src/process/do_process.cpp:1082
+msgid "PW Estimate"
+msgstr ""
+
+#: src/devices/device.cpp:317
+msgid "Device Power Report"
+msgstr ""
+
+#: src/devices/network.cpp:177
+#, c-format
+msgid "Network interface: %s (%s)"
+msgstr "Síťové rozhraní: %s (%s)"
+
+#: src/devices/rfkill.cpp:65 src/devices/rfkill.cpp:69
+#, c-format
+msgid "Radio device: %s"
+msgstr "Radio zařízení: %s"
+
+#: src/devices/runtime_pm.cpp:216
+#, c-format
+msgid "I2C %s (%s): %s"
+msgstr ""
+
+#: src/devices/runtime_pm.cpp:216 src/tuning/tuningi2c.cpp:57
+#: src/tuning/tuningi2c.cpp:59
+msgid "Adapter"
+msgstr ""
+
+#: src/devices/runtime_pm.cpp:216 src/devlist.cpp:331
+#: src/tuning/tuningi2c.cpp:57 src/tuning/tuningi2c.cpp:59
+#, fuzzy
+msgid "Device"
+msgstr "Zařízení"
+
+#: src/devices/runtime_pm.cpp:241
+#, c-format
+msgid "PCI Device: %s"
+msgstr "PCI Zařízení: %s"
+
+#: src/devices/usb.cpp:51 src/devices/usb.cpp:96 src/devices/usb.cpp:98
+#, c-format
+msgid "USB device: %s"
+msgstr "USB zařízení: %s"
+
+#: src/devices/usb.cpp:94
+#, c-format
+msgid "USB device: %s (%s)"
+msgstr "USB zařízení: %s (%s)"
+
+#: src/devlist.cpp:330
+msgid "Process"
+msgstr ""
+
+#: src/devlist.cpp:347
+msgid "Process Device Activity"
+msgstr ""
+
+#: src/display.cpp:70
+msgid "Overview"
+msgstr "Přehled"
+
+#: src/display.cpp:71
+msgid "Idle stats"
+msgstr "Nečinné"
+
+#: src/display.cpp:72
+msgid "Frequency stats"
+msgstr "Frekvence"
+
+#: src/display.cpp:73
+msgid "Device stats"
+msgstr "Zařízení"
+
+#: src/display.cpp:131
+msgid "Exit"
+msgstr "Konec"
+
+#: src/display.cpp:132
+msgid "Navigate"
+msgstr ""
+
+#: src/lib.cpp:288
+#, c-format
+msgid "%7sW"
+msgstr "%7sW"
+
+#: src/lib.cpp:291
+#, c-format
+msgid " 0 mW"
+msgstr " 0 mW"
+
+#: src/lib.cpp:410
+msgid "PS/2 Touchpad / Keyboard / Mouse"
+msgstr "PS/2 Touchpad / Klávesnice / Myš"
+
+#: src/lib.cpp:411
+msgid "SATA controller"
+msgstr "SATA ovladač"
+
+#: src/lib.cpp:412
+msgid "Intel built in USB hub"
+msgstr "Intel vestavěný v USB hubu"
+
+#: src/lib.cpp:467
+#, c-format
+msgid "glob returned GLOB_NOSPACE\n"
+msgstr ""
+
+#: src/lib.cpp:471
+#, c-format
+msgid "glob returned GLOB_ABORTED\n"
+msgstr ""
+
+#: src/lib.cpp:475
+#, c-format
+msgid "glob returned GLOB_NOMATCH\n"
+msgstr ""
+
+#: src/lib.cpp:513 src/lib.cpp:549
+#, c-format
+msgid ""
+"Model-specific registers (MSR)\t\t\t not found (try enabling "
+"CONFIG_X86_MSR).\n"
+msgstr ""
+
+#: src/main.cpp:104
+#, fuzzy, c-format
+msgid "PowerTOP version "
+msgstr "PowerTOP verze"
+
+#: src/main.cpp:110
+msgid "Set refresh time out"
+msgstr "Nastavit čas obnovení"
+
+#: src/main.cpp:123
+msgid "Usage: powertop [OPTIONS]"
+msgstr "Použití: powertop [VOLBY]"
+
+#: src/main.cpp:124
+msgid "sets all tunable options to their GOOD setting"
+msgstr ""
+
+#: src/main.cpp:125
+msgid "runs powertop in calibration mode"
+msgstr "spustit powertop v kalibračním režimu"
+
+#: src/main.cpp:126 src/main.cpp:129
+msgid "[=filename]"
+msgstr ""
+
+#: src/main.cpp:126
+msgid "generate a csv report"
+msgstr "vytvoření csv hlášení"
+
+#: src/main.cpp:127
+msgid "run in \"debug\" mode"
+msgstr "spustit v \"debug\" módu"
+
+#: src/main.cpp:128
+msgid "[=devnode]"
+msgstr "[=devnode]"
+
+#: src/main.cpp:128
+msgid "uses an Extech Power Analyzer for measurements"
+msgstr "využití Extech Power Analyzéru pro měření"
+
+#: src/main.cpp:129
+msgid "generate a html report"
+msgstr "vytvoření html hlášení"
+
+#: src/main.cpp:130
+msgid "[=iterations] number of times to run each test"
+msgstr "[=iterace] počet spuštění každého testu"
+
+#: src/main.cpp:131
+msgid "suppress stderr output"
+msgstr ""
+
+#: src/main.cpp:132 src/main.cpp:133
+msgid "[=seconds]"
+msgstr "[=sekundy]"
+
+#: src/main.cpp:132
+msgid "interval for power consumption measurement"
+msgstr ""
+
+#: src/main.cpp:133
+msgid "generate a report for 'x' seconds"
+msgstr "vytvoření hlášení pro \"x\" sekund"
+
+#: src/main.cpp:134
+msgid "[=workload]"
+msgstr "[=zatížení]"
+
+#: src/main.cpp:134
+msgid "file to execute for workload"
+msgstr "soubor ke spuštění pro zatížení"
+
+#: src/main.cpp:135
+msgid "print version information"
+msgstr "vypíše informace o verzi"
+
+#: src/main.cpp:136
+msgid "print this help menu"
+msgstr "vypíše tuto nápovědu"
+
+#: src/main.cpp:138
+#, fuzzy
+msgid "For more help please refer to the 'man 8 powertop'"
+msgstr "Pro více nápovědy přejděte prosím do README"
+
+#: src/main.cpp:233
+#, c-format
+msgid "Unknown issue running workload!\n"
+msgstr "Neznámý problém při spuštění zatížení!\n"
+
+#: src/main.cpp:290
+msgid "PowerTOP is out of memory. PowerTOP is Aborting"
+msgstr "PowerTOPu došla paměť. Power TOP je přerušen."
+
+#: src/main.cpp:298
+#, c-format
+msgid "Preparing to take measurements\n"
+msgstr "Příprava k měření\n"
+
+#: src/main.cpp:303
+#, c-format
+msgid "Taking %d measurement(s) for a duration of %d second(s) each.\n"
+msgstr "Změřeno %d výsledků za dobu trvání %d vteřin každý.\n"
+
+#: src/main.cpp:305
+#, c-format
+msgid "Measuring workload %s.\n"
+msgstr "Měření zatížení %s.\n"
+
+#: src/main.cpp:330
+#, c-format
+msgid "PowerTOP "
+msgstr "PowerTOP "
+
+#: src/main.cpp:331 src/main.cpp:381
+#, c-format
+msgid "exiting...\n"
+msgstr "ukončuji...\n"
+
+#: src/main.cpp:365
+#, c-format
+msgid "modprobe cpufreq_stats failed\n"
+msgstr ""
+
+#: src/main.cpp:368
+#, fuzzy, c-format
+msgid "modprobe msr failed\n"
+msgstr "Selhal tichý mód!\n"
+
+#: src/main.cpp:380 src/main.cpp:384
+#, c-format
+msgid "Failed to mount debugfs!\n"
+msgstr "Selhalo připojení debugfs!\n"
+
+#: src/main.cpp:385
+#, c-format
+msgid "Should still be able to auto tune...\n"
+msgstr ""
+
+#: src/main.cpp:467
+#, c-format
+msgid "Invalid CSV filename\n"
+msgstr ""
+
+#: src/main.cpp:483
+#, c-format
+msgid "Invalid HTML filename\n"
+msgstr ""
+
+#: src/main.cpp:492
+#, fuzzy, c-format
+msgid "Quiet mode failed!\n"
+msgstr "Selhal tichý mód!\n"
+
+#: src/main.cpp:560
+msgid "Leaving PowerTOP"
+msgstr "Ukončuji PowerTOP"
+
+#: src/parameters/persistent.cpp:46 src/parameters/persistent.cpp:155
+msgid "Cannot save to file"
+msgstr "Nelze uložit soubor"
+
+#: src/parameters/persistent.cpp:89 src/parameters/persistent.cpp:180
+msgid "Cannot load from file"
+msgstr "Nelze načíst ze souboru"
+
+#: src/parameters/persistent.cpp:138
+#, c-format
+msgid "Loaded %i prior measurements\n"
+msgstr ""
+"Nahráno %i měření\n"
+"\n"
+
+#: src/parameters/persistent.cpp:181
+msgid ""
+"File will be loaded after taking minimum number of measurement(s) with "
+"battery only \n"
+msgstr ""
+
+#: src/perf/perf.cpp:115
+#, c-format
+msgid ""
+"Too many open files, please increase the limit of open file descriptors.\n"
+msgstr ""
+
+#: src/perf/perf.cpp:117
+#, c-format
+msgid "PowerTOP %s needs the kernel to support the 'perf' subsystem\n"
+msgstr "PowerTOP %s potřebuje jádro k podpoře 'perf' subsystému\n"
+
+#: src/perf/perf.cpp:118
+#, c-format
+msgid "as well as support for trace points in the kernel:\n"
+msgstr "stejně jako podpora pro sledované body v jádru:\n"
+
+#: src/process/do_process.cpp:819
+#, c-format
+msgid ""
+"Estimated power: %5.1f Measured power: %5.1f Sum: %5.1f\n"
+"\n"
+msgstr ""
+"Odhad energie: %5.1f Změřená energie: %5.1f Součet: %5.1f\n"
+"\n"
+
+#: src/process/do_process.cpp:838
+#, c-format
+msgid "The estimated remaining time is %i hours, %i minutes\n"
+msgstr "Odhadovaný zbývající čas do vybití baterie je %i hodin, %i minut\n"
+
+#: src/process/do_process.cpp:846
+msgid "Summary"
+msgstr "Souhrn"
+
+#: src/process/do_process.cpp:846
+msgid "wakeups/second"
+msgstr "probuzení/sekund"
+
+#: src/process/do_process.cpp:846
+msgid "GPU ops/seconds"
+msgstr "GPU ops/sekund"
+
+#: src/process/do_process.cpp:846
+msgid "VFS ops/sec and"
+msgstr "VFS ops/sec a"
+
+#: src/process/do_process.cpp:846
+msgid "CPU use"
+msgstr "využití CPU"
+
+#: src/process/do_process.cpp:850
+msgid "Power est."
+msgstr "Energie zbývá"
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:1078
+msgid "Events/s"
+msgstr "Událost/i"
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:931 src/process/do_process.cpp:1079
+msgid "Category"
+msgstr "Kategorie"
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:932 src/process/do_process.cpp:1080
+#: src/tuning/tuning.cpp:242 src/tuning/tuning.cpp:270
+#: src/tuning/tuning.cpp:295 src/wakeup/waketab.cpp:155
+msgid "Description"
+msgstr "Popis"
+
+#: src/process/do_process.cpp:927
+msgid "Wakeups/s"
+msgstr "Probuzení/s"
+
+#: src/process/do_process.cpp:928
+msgid "GPU ops/s"
+msgstr "GPU ops/s"
+
+#: src/process/do_process.cpp:929
+msgid "Disk IO/s"
+msgstr "Disk IO/s"
+
+#: src/process/do_process.cpp:930
+msgid "GFX Wakeups/s"
+msgstr "GFX Probuzení/s"
+
+#: src/process/do_process.cpp:1017
+msgid "Overview of Software Power Consumers"
+msgstr "Přehled Software Power uživatelů"
+
+#: src/process/do_process.cpp:1057
+msgid "Target:"
+msgstr ""
+
+#: src/process/do_process.cpp:1058
+msgid "1 units/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1059
+msgid "System: "
+msgstr ""
+
+#: src/process/do_process.cpp:1061
+#, fuzzy
+msgid " wakeup/s"
+msgstr "Probuzení/s"
+
+#: src/process/do_process.cpp:1062
+msgid "CPU: "
+msgstr ""
+
+#: src/process/do_process.cpp:1064
+#, fuzzy, c-format
+msgid "% usage"
+msgstr "Využití"
+
+#: src/process/do_process.cpp:1065
+msgid "GPU:"
+msgstr ""
+
+#: src/process/do_process.cpp:1067 src/process/do_process.cpp:1073
+#, fuzzy
+msgid " ops/s"
+msgstr "GPU ops/s"
+
+#: src/process/do_process.cpp:1068
+msgid "GFX:"
+msgstr ""
+
+#: src/process/do_process.cpp:1070
+#, fuzzy
+msgid " wakeups/s"
+msgstr "Probuzení/s"
+
+#: src/process/do_process.cpp:1071
+msgid "VFS:"
+msgstr ""
+
+#: src/process/do_process.cpp:1139
+#, fuzzy
+msgid "Top 10 Power Consumers"
+msgstr "Přehled Software Power uživatelů"
+
+#: src/report/report.cpp:122
+#, fuzzy
+msgid "PowerTOP Version"
+msgstr "PowerTOP verze"
+
+#: src/report/report.cpp:131
+#, fuzzy
+msgid "Kernel Version"
+msgstr "PowerTOP verze"
+
+#: src/report/report.cpp:135
+msgid "System Name"
+msgstr ""
+
+#: src/report/report.cpp:142
+msgid "CPU Information"
+msgstr ""
+
+#: src/report/report.cpp:154
+msgid "OS Information"
+msgstr ""
+
+#: src/report/report.cpp:161
+#, fuzzy
+msgid "System Information"
+msgstr "vypíše informace o verzi"
+
+#: src/report/report.cpp:195
+#, fuzzy, c-format
+msgid "Cannot open output file %s (%s)\n"
+msgstr "Nelze vytvořit dočasný soubor\n"
+
+#: src/report/report.cpp:211
+#, c-format
+msgid "PowerTOP outputting using base filename %s\n"
+msgstr ""
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:49
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45
+msgid "Good"
+msgstr "Dobré"
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:50
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45
+msgid "Bad"
+msgstr "Špatné"
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:51
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45 src/wakeup/wakeup.cpp:50
+msgid "Unknown"
+msgstr "Neznámé"
+
+#: src/tuning/bluetooth.cpp:48
+#, c-format
+msgid "Bluetooth device interface status"
+msgstr "Status rozhraní zařízení Bluetooth"
+
+#: src/tuning/ethernet.cpp:54 src/wakeup/wakeup_ethernet.cpp:51
+#, c-format
+msgid "Wake-on-lan status for device %s"
+msgstr "Wake-on-lan status zařízení %s"
+
+#: src/tuning/runtime.cpp:48
+#, c-format
+msgid "Runtime PM for %s device %s"
+msgstr "Runtime PM pro %s zařízení %s"
+
+#: src/tuning/runtime.cpp:50
+#, c-format
+msgid "%s device %s has no runtime power management"
+msgstr "%s zařízení %s nemá spustitelnou správu napájení"
+
+#: src/tuning/runtime.cpp:74
+#, c-format
+msgid "PCI Device %s has no runtime power management"
+msgstr "PCI Zařízení %s nemá spustitelnou správu napájení"
+
+#: src/tuning/runtime.cpp:76
+#, c-format
+msgid "Runtime PM for PCI Device %s"
+msgstr "Trvání PM pro PCI zařízení %s"
+
+#: src/tuning/runtime.cpp:80
+#, fuzzy, c-format
+msgid "Runtime PM for port %s of PCI device: %s"
+msgstr "Runtime PM pro %s zařízení %s"
+
+#: src/tuning/runtime.cpp:83
+#, fuzzy, c-format
+msgid "Runtime PM for disk %s"
+msgstr "Runtime PM pro %s zařízení %s"
+
+#: src/tuning/tuning.cpp:62
+msgid "Enable Audio codec power management"
+msgstr "Zapnout správu napájení audio kodeku"
+
+#: src/tuning/tuning.cpp:63
+msgid "NMI watchdog should be turned off"
+msgstr "Hlídací pes NMI by měl být vypnutý"
+
+#: src/tuning/tuning.cpp:64
+msgid "Power Aware CPU scheduler"
+msgstr "Power Aware CPU plánovač"
+
+#: src/tuning/tuning.cpp:65
+msgid "VM writeback timeout"
+msgstr "VM writeback timeout"
+
+#: src/tuning/tuning.cpp:81
+msgid "Tunables"
+msgstr "Možnosti vyladění"
+
+#: src/tuning/tuning.cpp:81
+msgid " <ESC> Exit | <Enter> Toggle tunable | <r> Window refresh"
+msgstr " <ESC> Konec | <Enter> Přepnout změnitelné | <r> Obnovit okno"
+
+#: src/tuning/tuning.cpp:243 src/wakeup/waketab.cpp:156
+msgid "Script"
+msgstr ""
+
+#: src/tuning/tuning.cpp:257
+msgid "Software Settings in Need of Tuning"
+msgstr ""
+
+#: src/tuning/tuning.cpp:276
+msgid "Untunable Software Issues"
+msgstr ""
+
+#: src/tuning/tuning.cpp:307
+msgid "Optimal Tuned Software Settings"
+msgstr ""
+
+#: src/tuning/tuningi2c.cpp:57
+#, fuzzy, c-format
+msgid "Runtime PM for I2C %s %s (%s)"
+msgstr "Runtime PM pro %s zařízení %s"
+
+#: src/tuning/tuningi2c.cpp:59
+#, fuzzy, c-format
+msgid "I2C %s %s has no runtime power management"
+msgstr "%s zařízení %s nemá spustitelnou správu napájení"
+
+#: src/tuning/tuningsysfs.cpp:123
+#, fuzzy, c-format
+msgid "Enable SATA link power management for %s"
+msgstr "Zapnout správu napájení SATA linku pro %s"
+
+#: src/tuning/tuningusb.cpp:54
+#, c-format
+msgid "Autosuspend for unknown USB device %s (%s:%s)"
+msgstr "Automatické uspání pro neznámé USB zařízení %s (%s:%s)"
+
+#: src/tuning/tuningusb.cpp:71 src/tuning/tuningusb.cpp:73
+#: src/tuning/tuningusb.cpp:75
+#, c-format
+msgid "Autosuspend for USB device %s [%s]"
+msgstr "Automatické uspání pro USB zařízení %s [%s]"
+
+#: src/tuning/wifi.cpp:48
+#, c-format
+msgid "Wireless Power Saving for interface %s"
+msgstr "Úspora energie bezdrátových zařízení %s"
+
+#: src/wakeup/waketab.cpp:42
+#, fuzzy
+msgid "WakeUp"
+msgstr "Probuzení/s"
+
+#: src/wakeup/waketab.cpp:42
+#, fuzzy
+msgid " <ESC> Exit | <Enter> Toggle wakeup | <r> Window refresh"
+msgstr " <ESC> Konec | <Enter> Přepnout změnitelné | <r> Obnovit okno"
+
+#: src/wakeup/waketab.cpp:170
+#, fuzzy
+msgid "Wake status of the devices"
+msgstr "Wake-on-lan status zařízení %s"
+
+#: src/wakeup/wakeup.cpp:48 src/wakeup/wakeup_ethernet.cpp:47
+#: src/wakeup/wakeup_usb.cpp:47
+#, fuzzy
+msgid "Enabled"
+msgstr "Možnosti vyladění"
+
+#: src/wakeup/wakeup.cpp:49 src/wakeup/wakeup_ethernet.cpp:47
+#: src/wakeup/wakeup_usb.cpp:47
+msgid "Disabled"
+msgstr ""
+
+#: src/wakeup/wakeup_usb.cpp:51
+#, fuzzy, c-format
+msgid "Wake status for USB device %s"
+msgstr "Wake-on-lan status zařízení %s"
+
+#~ msgid "Actual"
+#~ msgstr "Aktuální"
+
+#, fuzzy
+#~ msgid "I2C Device: %s"
+#~ msgstr "PCI Zařízení: %s"
+
+#~ msgid "[=FILENAME]"
+#~ msgstr "[=JMENOSOUBORU]"
+
+#~ msgid "Using 'ondemand' cpufreq governor"
+#~ msgstr "Užití 'ondemand' cpufreq regulátoru"
+
+#~ msgid "Power Consumption Summary"
+#~ msgstr "Souhrn spotřeby energie"
+
+#~ msgid "GPU ops/second"
+#~ msgstr "GPU ops/sekund"
+
+#~ msgid "VFS ops/sec"
+#~ msgstr "VFS ops/sekund"
+
+#~ msgid "GFX wakes/sec and"
+#~ msgstr "GFX probuzení/sek a"
diff --git a/po/da_DK.po b/po/da_DK.po
new file mode 100644
index 0000000..9301e91
--- /dev/null
+++ b/po/da_DK.po
@@ -0,0 +1,951 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Intel Corporation
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: PowerTOP\n"
+"Report-Msgid-Bugs-To: powertop@lists.01.org\n"
+"POT-Creation-Date: 2019-01-04 13:55-0800\n"
+"PO-Revision-Date: 2013-11-05 08:40+0000\n"
+"Last-Translator: Margie Foster <margie@linux.intel.com>\n"
+"Language-Team: Danish (Denmark) (http://www.transifex.com/projects/p/"
+"PowerTOP/language/da_DK/)\n"
+"Language: da_DK\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ../src/calibrate/calibrate.cpp:238
+#, c-format
+msgid "Cannot create temp file\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:258
+#, c-format
+msgid "Calibrating: CPU usage on %i threads\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:273
+#, c-format
+msgid "Calibrating: CPU wakeup power consumption\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:290
+#, c-format
+msgid "Calibrating USB devices\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:292 ../src/calibrate/calibrate.cpp:309
+#: ../src/calibrate/calibrate.cpp:317 ../src/calibrate/calibrate.cpp:334
+#, c-format
+msgid ".... device %s \n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:307
+#, c-format
+msgid "Calibrating radio devices\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:331
+#, c-format
+msgid "Calibrating backlight\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:355 ../src/calibrate/calibrate.cpp:365
+#, c-format
+msgid "Calibrating idle\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:378
+#, c-format
+msgid "Calibrating: disk usage \n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:403
+msgid "Starting PowerTOP power estimate calibration \n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:426
+msgid "Finishing PowerTOP power estimate calibration \n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:430
+#, c-format
+msgid "Parameters after calibration:\n"
+msgstr ""
+
+#: ../src/cpu/abstract_cpu.cpp:74
+msgid "Idle"
+msgstr ""
+
+#: ../src/cpu/abstract_cpu.cpp:76
+msgid "Turbo Mode"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(HW)"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(OS)"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:91 ../src/cpu/intel_cpus.cpp:324
+#, c-format
+msgid " Core"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:85
+#, c-format
+msgid "cpu package %i"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:86
+msgid "cpu package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:89 ../src/cpu/cpu.cpp:96
+#, c-format
+msgid "package-%i"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:90
+msgid "cpu rapl package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:97
+msgid "dram rapl package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:471
+msgid "Processor Idle State Report"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:535 ../src/cpu/cpu.cpp:753
+msgid "Package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:566 ../src/cpu/cpu.cpp:775
+#, c-format
+msgid "Core %d"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:573
+#, c-format
+msgid "GPU %d"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:594
+msgid "CPU"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:676
+msgid "Processor Frequency Report"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:796
+#, c-format
+msgid "CPU %d"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:997
+#, c-format
+msgid "cpu_idle event returned no state?\n"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:1012
+#, c-format
+msgid "power or cpu_frequency event returned no state?\n"
+msgstr ""
+
+#: ../src/cpu/cpu_linux.cpp:79
+msgid "C0 polling"
+msgstr ""
+
+#: ../src/cpu/cpu_linux.cpp:242
+#, c-format
+msgid " CPU(OS) %i"
+msgstr ""
+
+#: ../src/cpu/cpu_linux.cpp:341 ../src/cpu/intel_cpus.cpp:651
+#, c-format
+msgid " CPU %i"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(HW)"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(OS)"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:104 ../src/cpu/intel_cpus.cpp:412
+#, c-format
+msgid " Package"
+msgstr ""
+
+#: ../src/cpu/intel_cpus.cpp:129
+#, c-format
+msgid "read_msr cpu%d 0x%llx : "
+msgstr ""
+
+#: ../src/cpu/intel_cpus.cpp:574
+msgid "C0 active"
+msgstr ""
+
+#: ../src/cpu/intel_cpus.cpp:632
+#, c-format
+msgid "Average"
+msgstr ""
+
+#: ../src/cpu/intel_gpu.cpp:64
+#, c-format
+msgid " GPU "
+msgstr ""
+
+#: ../src/devices/ahci.cpp:154
+#, c-format
+msgid "SATA link: %s"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:156
+#, c-format
+msgid "SATA disk: %s"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:374
+msgid "AHCI ALPM Residency Statistics - Not supported on this macine"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:389
+msgid "Link"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:390
+msgid "Active"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:391
+msgid "Partial"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:392
+msgid "Slumber"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:393
+msgid "Devslp"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:399
+msgid "AHCI ALPM Residency Statistics"
+msgstr ""
+
+#: ../src/devices/alsa.cpp:77
+#, c-format
+msgid "Audio codec %s: %s (%s)"
+msgstr ""
+
+#: ../src/devices/alsa.cpp:79 ../src/devices/alsa.cpp:81
+#, c-format
+msgid "Audio codec %s: %s"
+msgstr ""
+
+#: ../src/devices/devfreq.cpp:261
+msgid "Device Freq stats"
+msgstr ""
+
+#: ../src/devices/devfreq.cpp:279
+msgid " Devfreq is not enabled"
+msgstr ""
+
+#: ../src/devices/devfreq.cpp:284
+msgid " No devfreq devices available"
+msgstr ""
+
+#: ../src/devices/device.cpp:172 ../src/process/do_process.cpp:831
+#, c-format
+msgid "The battery reports a discharge rate of %sW\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:174 ../src/process/do_process.cpp:833
+#, c-format
+msgid "The power consumed was %sJ\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:180
+#, c-format
+msgid "System baseline power is estimated at %sW\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:187
+msgid "Power est. Usage Device name\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:189
+msgid " Usage Device name\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:256
+msgid "The battery reports a discharge rate of: "
+msgstr ""
+
+#: ../src/devices/device.cpp:261
+msgid "The power consumed was : "
+msgstr ""
+
+#: ../src/devices/device.cpp:268
+msgid "The system baseline power is estimated at: "
+msgstr ""
+
+#: ../src/devices/device.cpp:277 ../src/process/do_process.cpp:850
+#: ../src/process/do_process.cpp:852 ../src/process/do_process.cpp:926
+#: ../src/process/do_process.cpp:1077
+msgid "Usage"
+msgstr ""
+
+#: ../src/devices/device.cpp:278
+msgid "Device Name"
+msgstr ""
+
+#: ../src/devices/device.cpp:280 ../src/process/do_process.cpp:935
+#: ../src/process/do_process.cpp:1082
+msgid "PW Estimate"
+msgstr ""
+
+#. Report Output
+#: ../src/devices/device.cpp:317
+msgid "Device Power Report"
+msgstr ""
+
+#: ../src/devices/network.cpp:177
+#, c-format
+msgid "Network interface: %s (%s)"
+msgstr ""
+
+#: ../src/devices/rfkill.cpp:65 ../src/devices/rfkill.cpp:69
+#, c-format
+msgid "Radio device: %s"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216
+#, c-format
+msgid "I2C %s (%s): %s"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216 ../src/tuning/tuningi2c.cpp:57
+#: ../src/tuning/tuningi2c.cpp:59
+msgid "Adapter"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216 ../src/devlist.cpp:331
+#: ../src/tuning/tuningi2c.cpp:57 ../src/tuning/tuningi2c.cpp:59
+msgid "Device"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:241
+#, c-format
+msgid "PCI Device: %s"
+msgstr ""
+
+#: ../src/devices/usb.cpp:51 ../src/devices/usb.cpp:96
+#: ../src/devices/usb.cpp:98
+#, c-format
+msgid "USB device: %s"
+msgstr ""
+
+#: ../src/devices/usb.cpp:94
+#, c-format
+msgid "USB device: %s (%s)"
+msgstr ""
+
+#: ../src/devlist.cpp:330
+msgid "Process"
+msgstr ""
+
+#. Report Output
+#. No div attribute here inherits from device power report
+#: ../src/devlist.cpp:347
+msgid "Process Device Activity"
+msgstr ""
+
+#: ../src/display.cpp:70
+msgid "Overview"
+msgstr ""
+
+#: ../src/display.cpp:71
+msgid "Idle stats"
+msgstr ""
+
+#: ../src/display.cpp:72
+msgid "Frequency stats"
+msgstr ""
+
+#: ../src/display.cpp:73
+msgid "Device stats"
+msgstr ""
+
+#: ../src/display.cpp:131
+msgid "Exit"
+msgstr ""
+
+#: ../src/display.cpp:132
+msgid "Navigate"
+msgstr ""
+
+#: ../src/lib.cpp:288
+#, c-format
+msgid "%7sW"
+msgstr ""
+
+#: ../src/lib.cpp:291
+#, c-format
+msgid " 0 mW"
+msgstr ""
+
+#: ../src/lib.cpp:410
+msgid "PS/2 Touchpad / Keyboard / Mouse"
+msgstr ""
+
+#: ../src/lib.cpp:411
+msgid "SATA controller"
+msgstr ""
+
+#: ../src/lib.cpp:412
+msgid "Intel built in USB hub"
+msgstr ""
+
+#: ../src/lib.cpp:467
+#, c-format
+msgid "glob returned GLOB_NOSPACE\n"
+msgstr ""
+
+#: ../src/lib.cpp:471
+#, c-format
+msgid "glob returned GLOB_ABORTED\n"
+msgstr ""
+
+#: ../src/lib.cpp:475
+#, c-format
+msgid "glob returned GLOB_NOMATCH\n"
+msgstr ""
+
+#: ../src/lib.cpp:513 ../src/lib.cpp:549
+#, c-format
+msgid ""
+"Model-specific registers (MSR)\t\t\t not found (try enabling "
+"CONFIG_X86_MSR).\n"
+msgstr ""
+
+#: ../src/main.cpp:103
+#, c-format
+msgid "PowerTOP version "
+msgstr ""
+
+#: ../src/main.cpp:109
+msgid "Set refresh time out"
+msgstr ""
+
+#: ../src/main.cpp:122
+msgid "Usage: powertop [OPTIONS]"
+msgstr ""
+
+#: ../src/main.cpp:123
+msgid "sets all tunable options to their GOOD setting"
+msgstr ""
+
+#: ../src/main.cpp:124
+msgid "runs powertop in calibration mode"
+msgstr ""
+
+#: ../src/main.cpp:125 ../src/main.cpp:128
+msgid "[=filename]"
+msgstr ""
+
+#: ../src/main.cpp:125
+msgid "generate a csv report"
+msgstr ""
+
+#: ../src/main.cpp:126
+msgid "run in \"debug\" mode"
+msgstr ""
+
+#: ../src/main.cpp:127
+msgid "[=devnode]"
+msgstr ""
+
+#: ../src/main.cpp:127
+msgid "uses an Extech Power Analyzer for measurements"
+msgstr ""
+
+#: ../src/main.cpp:128
+msgid "generate a html report"
+msgstr ""
+
+#: ../src/main.cpp:129
+msgid "[=iterations] number of times to run each test"
+msgstr ""
+
+#: ../src/main.cpp:130
+msgid "suppress stderr output"
+msgstr ""
+
+#: ../src/main.cpp:131 ../src/main.cpp:132
+msgid "[=seconds]"
+msgstr ""
+
+#: ../src/main.cpp:131
+msgid "interval for power consumption measurement"
+msgstr ""
+
+#: ../src/main.cpp:132
+msgid "generate a report for 'x' seconds"
+msgstr ""
+
+#: ../src/main.cpp:133
+msgid "[=workload]"
+msgstr ""
+
+#: ../src/main.cpp:133
+msgid "file to execute for workload"
+msgstr ""
+
+#: ../src/main.cpp:134
+msgid "print version information"
+msgstr ""
+
+#: ../src/main.cpp:135
+msgid "print this help menu"
+msgstr ""
+
+#: ../src/main.cpp:137
+msgid "For more help please refer to the 'man 8 powertop'"
+msgstr ""
+
+#: ../src/main.cpp:232
+#, c-format
+msgid "Unknown issue running workload!\n"
+msgstr ""
+
+#: ../src/main.cpp:289
+msgid "PowerTOP is out of memory. PowerTOP is Aborting"
+msgstr ""
+
+#. one to warm up everything
+#: ../src/main.cpp:297
+#, c-format
+msgid "Preparing to take measurements\n"
+msgstr ""
+
+#: ../src/main.cpp:302
+#, c-format
+msgid "Taking %d measurement(s) for a duration of %d second(s) each.\n"
+msgstr ""
+
+#: ../src/main.cpp:304
+#, c-format
+msgid "Measuring workload %s.\n"
+msgstr ""
+
+#: ../src/main.cpp:329
+#, c-format
+msgid "PowerTOP "
+msgstr ""
+
+#: ../src/main.cpp:330 ../src/main.cpp:380
+#, c-format
+msgid "exiting...\n"
+msgstr ""
+
+#: ../src/main.cpp:364
+#, c-format
+msgid "modprobe cpufreq_stats failed"
+msgstr ""
+
+#: ../src/main.cpp:367
+#, c-format
+msgid "modprobe msr failed"
+msgstr ""
+
+#: ../src/main.cpp:379 ../src/main.cpp:383
+#, c-format
+msgid "Failed to mount debugfs!\n"
+msgstr ""
+
+#: ../src/main.cpp:384
+#, c-format
+msgid "Should still be able to auto tune...\n"
+msgstr ""
+
+#: ../src/main.cpp:466
+#, c-format
+msgid "Invalid CSV filename\n"
+msgstr ""
+
+#: ../src/main.cpp:482
+#, c-format
+msgid "Invalid HTML filename\n"
+msgstr ""
+
+#: ../src/main.cpp:491
+#, c-format
+msgid "Quiet mode failed!\n"
+msgstr ""
+
+#: ../src/main.cpp:559
+msgid "Leaving PowerTOP"
+msgstr ""
+
+#: ../src/parameters/persistent.cpp:46 ../src/parameters/persistent.cpp:155
+msgid "Cannot save to file"
+msgstr ""
+
+#: ../src/parameters/persistent.cpp:89 ../src/parameters/persistent.cpp:180
+msgid "Cannot load from file"
+msgstr ""
+
+#. '%i" is for count, do not translate
+#: ../src/parameters/persistent.cpp:138
+#, c-format
+msgid "Loaded %i prior measurements\n"
+msgstr ""
+
+#: ../src/parameters/persistent.cpp:181
+msgid ""
+"File will be loaded after taking minimum number of measurement(s) with "
+"battery only \n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:115
+#, c-format
+msgid ""
+"Too many open files, please increase the limit of open file descriptors.\n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:117
+#, c-format
+msgid "PowerTOP %s needs the kernel to support the 'perf' subsystem\n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:118
+#, c-format
+msgid "as well as support for trace points in the kernel:\n"
+msgstr ""
+
+#: ../src/process/do_process.cpp:819
+#, c-format
+msgid ""
+"Estimated power: %5.1f Measured power: %5.1f Sum: %5.1f\n"
+"\n"
+msgstr ""
+
+#: ../src/process/do_process.cpp:838
+#, c-format
+msgid "The estimated remaining time is %i hours, %i minutes\n"
+msgstr ""
+
+#: ../src/process/do_process.cpp:846
+msgid "Summary"
+msgstr ""
+
+#: ../src/process/do_process.cpp:846
+msgid "wakeups/second"
+msgstr ""
+
+#: ../src/process/do_process.cpp:846
+msgid "GPU ops/seconds"
+msgstr ""
+
+#: ../src/process/do_process.cpp:846
+msgid "VFS ops/sec and"
+msgstr ""
+
+#: ../src/process/do_process.cpp:846
+msgid "CPU use"
+msgstr ""
+
+#: ../src/process/do_process.cpp:850
+msgid "Power est."
+msgstr ""
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:1078
+msgid "Events/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:931 ../src/process/do_process.cpp:1079
+msgid "Category"
+msgstr ""
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:932 ../src/process/do_process.cpp:1080
+#: ../src/tuning/tuning.cpp:242 ../src/tuning/tuning.cpp:270
+#: ../src/tuning/tuning.cpp:288 ../src/wakeup/waketab.cpp:155
+msgid "Description"
+msgstr ""
+
+#: ../src/process/do_process.cpp:927
+msgid "Wakeups/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:928
+msgid "GPU ops/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:929
+msgid "Disk IO/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:930
+msgid "GFX Wakeups/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1017
+msgid "Overview of Software Power Consumers"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1057
+msgid "Target:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1058
+msgid "1 units/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1059
+msgid "System: "
+msgstr ""
+
+#: ../src/process/do_process.cpp:1061
+msgid " wakeup/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1062
+msgid "CPU: "
+msgstr ""
+
+#: ../src/process/do_process.cpp:1064
+#, c-format
+msgid "% usage"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1065
+msgid "GPU:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1067 ../src/process/do_process.cpp:1073
+msgid " ops/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1068
+msgid "GFX:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1070
+msgid " wakeups/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1071
+msgid "VFS:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1139
+msgid "Top 10 Power Consumers"
+msgstr ""
+
+#: ../src/report/report.cpp:122
+msgid "PowerTOP Version"
+msgstr ""
+
+#: ../src/report/report.cpp:131
+msgid "Kernel Version"
+msgstr ""
+
+#: ../src/report/report.cpp:135
+msgid "System Name"
+msgstr ""
+
+#: ../src/report/report.cpp:142
+msgid "CPU Information"
+msgstr ""
+
+#: ../src/report/report.cpp:154
+msgid "OS Information"
+msgstr ""
+
+#: ../src/report/report.cpp:161
+msgid "System Information"
+msgstr ""
+
+#: ../src/report/report.cpp:195
+#, c-format
+msgid "Cannot open output file %s (%s)\n"
+msgstr ""
+
+#: ../src/report/report.cpp:211
+#, c-format
+msgid "PowerTOP outputing using base filename %s\n"
+msgstr ""
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:49
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+msgid "Good"
+msgstr ""
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:50
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+msgid "Bad"
+msgstr ""
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:51
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+#: ../src/wakeup/wakeup.cpp:50
+msgid "Unknown"
+msgstr ""
+
+#: ../src/tuning/bluetooth.cpp:48
+#, c-format
+msgid "Bluetooth device interface status"
+msgstr ""
+
+#: ../src/tuning/ethernet.cpp:54 ../src/wakeup/wakeup_ethernet.cpp:51
+#, c-format
+msgid "Wake-on-lan status for device %s"
+msgstr ""
+
+#: ../src/tuning/runtime.cpp:48
+#, c-format
+msgid "Runtime PM for %s device %s"
+msgstr ""
+
+#: ../src/tuning/runtime.cpp:50
+#, c-format
+msgid "%s device %s has no runtime power management"
+msgstr ""
+
+#: ../src/tuning/runtime.cpp:74
+#, c-format
+msgid "PCI Device %s has no runtime power management"
+msgstr ""
+
+#: ../src/tuning/runtime.cpp:76
+#, c-format
+msgid "Runtime PM for PCI Device %s"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:62
+msgid "Enable Audio codec power management"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:63
+msgid "NMI watchdog should be turned off"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:64
+msgid "Power Aware CPU scheduler"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:65
+msgid "VM writeback timeout"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:81
+msgid "Tunables"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:81
+msgid " <ESC> Exit | <Enter> Toggle tunable | <r> Window refresh"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:243 ../src/wakeup/waketab.cpp:156
+msgid "Script"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:257
+msgid "Software Settings in Need of Tuning"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:276
+msgid "Untunable Software Issues"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:300
+msgid "Optimal Tuned Software Settings"
+msgstr ""
+
+#: ../src/tuning/tuningi2c.cpp:57
+#, c-format
+msgid "Runtime PM for I2C %s %s (%s)"
+msgstr ""
+
+#: ../src/tuning/tuningi2c.cpp:59
+#, c-format
+msgid "I2C %s %s has no runtime power management"
+msgstr ""
+
+#: ../src/tuning/tuningsysfs.cpp:123
+#, c-format
+msgid "Enable SATA link power management for %s"
+msgstr ""
+
+#: ../src/tuning/tuningusb.cpp:54
+#, c-format
+msgid "Autosuspend for unknown USB device %s (%s:%s)"
+msgstr ""
+
+#: ../src/tuning/tuningusb.cpp:71 ../src/tuning/tuningusb.cpp:73
+#: ../src/tuning/tuningusb.cpp:75
+#, c-format
+msgid "Autosuspend for USB device %s [%s]"
+msgstr ""
+
+#: ../src/tuning/wifi.cpp:48
+#, c-format
+msgid "Wireless Power Saving for interface %s"
+msgstr ""
+
+#: ../src/wakeup/waketab.cpp:42
+msgid "WakeUp"
+msgstr ""
+
+#: ../src/wakeup/waketab.cpp:42
+msgid " <ESC> Exit | <Enter> Toggle wakeup | <r> Window refresh"
+msgstr ""
+
+#. Report Output
+#: ../src/wakeup/waketab.cpp:170
+msgid "Wake status of the devices"
+msgstr ""
+
+#: ../src/wakeup/wakeup.cpp:48 ../src/wakeup/wakeup_ethernet.cpp:47
+#: ../src/wakeup/wakeup_usb.cpp:47
+msgid "Enable"
+msgstr ""
+
+#: ../src/wakeup/wakeup.cpp:49 ../src/wakeup/wakeup_ethernet.cpp:47
+#: ../src/wakeup/wakeup_usb.cpp:47
+msgid "Disable"
+msgstr ""
+
+#: ../src/wakeup/wakeup_usb.cpp:51
+#, c-format
+msgid "Wake status for USB device %s"
+msgstr ""
diff --git a/po/de_DE.po b/po/de_DE.po
new file mode 100644
index 0000000..66d894d
--- /dev/null
+++ b/po/de_DE.po
@@ -0,0 +1,1011 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Intel Corporation
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Ettore Atalan <atalanttore@googlemail.com>, 2012-2013
+# Fabian Affolter <fab@fedoraproject.org>, 2011
+# uhofemei <ulf.hofemeier@intel.com>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: PowerTOP\n"
+"Report-Msgid-Bugs-To: \"powertop@lists.01.org\"\n"
+"POT-Creation-Date: 2022-09-29 04:45-0700\n"
+"PO-Revision-Date: 2013-11-05 19:48+0000\n"
+"Last-Translator: Ettore Atalan <atalanttore@googlemail.com>\n"
+"Language-Team: German (Germany) (http://www.transifex.com/projects/p/"
+"PowerTOP/language/de_DE/)\n"
+"Language: de_DE\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/calibrate/calibrate.cpp:238
+#, c-format
+msgid "Cannot create temp file\n"
+msgstr "Temporäre Datei konnte nicht erzeugt werden\n"
+
+#: src/calibrate/calibrate.cpp:258
+#, c-format
+msgid "Calibrating: CPU usage on %i threads\n"
+msgstr "Kalibriere CPU-Auslastung bei %i Thread\n"
+
+#: src/calibrate/calibrate.cpp:273
+#, c-format
+msgid "Calibrating: CPU wakeup power consumption\n"
+msgstr "Kalibriere CPU-Aufwach-Leistungsaufnahme\n"
+
+#: src/calibrate/calibrate.cpp:290
+#, c-format
+msgid "Calibrating USB devices\n"
+msgstr "Kalibriere USB-Geräte\n"
+
+#: src/calibrate/calibrate.cpp:292 src/calibrate/calibrate.cpp:309
+#: src/calibrate/calibrate.cpp:317 src/calibrate/calibrate.cpp:334
+#, c-format
+msgid ".... device %s \n"
+msgstr ".... Gerät %s\n"
+
+#: src/calibrate/calibrate.cpp:307
+#, c-format
+msgid "Calibrating radio devices\n"
+msgstr "Kalibriere Funkvorrichtungen\n"
+
+#: src/calibrate/calibrate.cpp:331
+#, c-format
+msgid "Calibrating backlight\n"
+msgstr "Kalibriere Hintergrundbeleuchtung\n"
+
+#: src/calibrate/calibrate.cpp:355 src/calibrate/calibrate.cpp:365
+#, c-format
+msgid "Calibrating idle\n"
+msgstr "Kalibriere Leerlauf\n"
+
+#: src/calibrate/calibrate.cpp:378
+#, c-format
+msgid "Calibrating: disk usage \n"
+msgstr "Kalibriere Festplattennutzung\n"
+
+#: src/calibrate/calibrate.cpp:403
+msgid "Starting PowerTOP power estimate calibration \n"
+msgstr "Starte Kalibrierung der PowerTOP-Leistungsschätzung\n"
+
+#: src/calibrate/calibrate.cpp:426
+msgid "Finishing PowerTOP power estimate calibration \n"
+msgstr "Schließe Kalibrierung der PowerTOP-Leistungsschätzung ab\n"
+
+#: src/calibrate/calibrate.cpp:430
+#, c-format
+msgid "Parameters after calibration:\n"
+msgstr "Parameter nach der Kalibrierung:\n"
+
+#: src/cpu/abstract_cpu.cpp:74
+msgid "Idle"
+msgstr ""
+
+#: src/cpu/abstract_cpu.cpp:76
+msgid "Turbo Mode"
+msgstr ""
+
+#: src/cpu/cpu_core.cpp:37
+#, fuzzy, c-format
+msgid " Core(HW)"
+msgstr "Kern"
+
+#: src/cpu/cpu_core.cpp:37
+#, fuzzy, c-format
+msgid " Core(OS)"
+msgstr "Kern"
+
+#: src/cpu/cpu_core.cpp:91 src/cpu/intel_cpus.cpp:367
+#, c-format
+msgid " Core"
+msgstr "Kern"
+
+#: src/cpu/cpu.cpp:85
+#, c-format
+msgid "cpu package %i"
+msgstr "CPU-Paket %i"
+
+#: src/cpu/cpu.cpp:86
+msgid "cpu package"
+msgstr "CPU-Paket"
+
+#: src/cpu/cpu.cpp:89 src/cpu/cpu.cpp:96
+#, fuzzy, c-format
+msgid "package-%i"
+msgstr "Paket %i"
+
+#: src/cpu/cpu.cpp:90
+msgid "cpu rapl package"
+msgstr ""
+
+#: src/cpu/cpu.cpp:97
+msgid "dram rapl package"
+msgstr ""
+
+#: src/cpu/cpu.cpp:471
+msgid "Processor Idle State Report"
+msgstr ""
+
+#: src/cpu/cpu.cpp:535 src/cpu/cpu.cpp:761
+msgid "Package"
+msgstr "Paket"
+
+#: src/cpu/cpu.cpp:572 src/cpu/cpu.cpp:783
+#, fuzzy, c-format
+msgid "Core %d"
+msgstr "Kern %i"
+
+#: src/cpu/cpu.cpp:579
+#, fuzzy, c-format
+msgid "GPU %d"
+msgstr "GPU %i"
+
+#: src/cpu/cpu.cpp:602
+#, fuzzy
+msgid "CPU"
+msgstr "GPU %i"
+
+#: src/cpu/cpu.cpp:684
+msgid "Processor Frequency Report"
+msgstr ""
+
+#: src/cpu/cpu.cpp:804
+#, fuzzy, c-format
+msgid "CPU %d"
+msgstr "GPU %i"
+
+#: src/cpu/cpu.cpp:1005
+#, c-format
+msgid "cpu_idle event returned no state?\n"
+msgstr "cpu_idle-Ereignis gab keinen Status zurück?\n"
+
+#: src/cpu/cpu.cpp:1020
+#, c-format
+msgid "power or cpu_frequency event returned no state?\n"
+msgstr "power- oder cpu_frequency-Ereignis gab kein Status zurück?\n"
+
+#: src/cpu/cpu_linux.cpp:79
+msgid "C0 polling"
+msgstr "C0 sammeln"
+
+#: src/cpu/cpu_linux.cpp:242
+#, fuzzy, c-format
+msgid " CPU(OS) %i"
+msgstr "CPU %i"
+
+#: src/cpu/cpu_linux.cpp:341 src/cpu/intel_cpus.cpp:733
+#, c-format
+msgid " CPU %i"
+msgstr "CPU %i"
+
+#: src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(HW)"
+msgstr ""
+
+#: src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(OS)"
+msgstr ""
+
+#: src/cpu/cpu_package.cpp:104 src/cpu/intel_cpus.cpp:498
+#, c-format
+msgid " Package"
+msgstr "Paket"
+
+#: src/cpu/intel_cpus.cpp:152
+#, c-format
+msgid "read_msr cpu%d 0x%llx : "
+msgstr ""
+
+#: src/cpu/intel_cpus.cpp:656
+msgid "C0 active"
+msgstr "C0 aktiv"
+
+#: src/cpu/intel_cpus.cpp:714
+#, c-format
+msgid "Average"
+msgstr ""
+
+#: src/cpu/intel_gpu.cpp:64
+#, fuzzy, c-format
+msgid " GPU "
+msgstr "GPU %i"
+
+#: src/devices/ahci.cpp:154
+#, c-format
+msgid "SATA link: %s"
+msgstr "SATA-Verbindung: %s"
+
+#: src/devices/ahci.cpp:156
+#, c-format
+msgid "SATA disk: %s"
+msgstr "SATA-Festplatte: %s"
+
+#: src/devices/ahci.cpp:374
+msgid "AHCI ALPM Residency Statistics - Not supported on this macine"
+msgstr ""
+
+#: src/devices/ahci.cpp:389
+msgid "Link"
+msgstr ""
+
+#: src/devices/ahci.cpp:390
+#, fuzzy
+msgid "Active"
+msgstr "C0 aktiv"
+
+#: src/devices/ahci.cpp:391
+msgid "Partial"
+msgstr ""
+
+#: src/devices/ahci.cpp:392
+msgid "Slumber"
+msgstr ""
+
+#: src/devices/ahci.cpp:393
+msgid "Devslp"
+msgstr ""
+
+#: src/devices/ahci.cpp:399
+msgid "AHCI ALPM Residency Statistics"
+msgstr ""
+
+#: src/devices/alsa.cpp:77
+#, c-format
+msgid "Audio codec %s: %s (%s)"
+msgstr "Audiocodec %s: %s (%s)"
+
+#: src/devices/alsa.cpp:79 src/devices/alsa.cpp:81
+#, c-format
+msgid "Audio codec %s: %s"
+msgstr "Audiocodec %s: %s"
+
+#: src/devices/devfreq.cpp:260
+#, fuzzy
+msgid "Device Freq stats"
+msgstr "Gerät-Statistiken"
+
+#: src/devices/devfreq.cpp:278
+msgid " Devfreq is not enabled"
+msgstr ""
+
+#: src/devices/devfreq.cpp:283
+msgid " No devfreq devices available"
+msgstr ""
+
+#: src/devices/device.cpp:172 src/process/do_process.cpp:831
+#, c-format
+msgid "The battery reports a discharge rate of %sW\n"
+msgstr "Die Batterie meldet eine Entladungsrate von %sW\n"
+
+#: src/devices/device.cpp:174 src/process/do_process.cpp:833
+#, c-format
+msgid "The energy consumed was %sJ\n"
+msgstr ""
+
+#: src/devices/device.cpp:180
+#, c-format
+msgid "System baseline power is estimated at %sW\n"
+msgstr "Leistungsaufnahme bei Grundauslastung beträgt %sW\n"
+
+#: src/devices/device.cpp:187
+msgid "Power est. Usage Device name\n"
+msgstr "Gesch. Leistung Auslastung Gerätename\n"
+
+#: src/devices/device.cpp:189
+msgid " Usage Device name\n"
+msgstr " Auslastung Gerätename\n"
+
+#: src/devices/device.cpp:256
+#, fuzzy
+msgid "The battery reports a discharge rate of: "
+msgstr "Die Batterie meldet eine Entladungsrate von %sW\n"
+
+#: src/devices/device.cpp:261
+msgid "The energy consumed was : "
+msgstr ""
+
+#: src/devices/device.cpp:268
+#, fuzzy
+msgid "The system baseline power is estimated at: "
+msgstr "Leistungsaufnahme bei Grundauslastung beträgt %sW\n"
+
+#: src/devices/device.cpp:277 src/process/do_process.cpp:850
+#: src/process/do_process.cpp:852 src/process/do_process.cpp:926
+#: src/process/do_process.cpp:1077
+msgid "Usage"
+msgstr "Auslastung"
+
+#: src/devices/device.cpp:278
+#, fuzzy
+msgid "Device Name"
+msgstr "Gerät-Statistiken"
+
+#: src/devices/device.cpp:280 src/process/do_process.cpp:935
+#: src/process/do_process.cpp:1082
+msgid "PW Estimate"
+msgstr ""
+
+#: src/devices/device.cpp:317
+msgid "Device Power Report"
+msgstr ""
+
+#: src/devices/network.cpp:177
+#, c-format
+msgid "Network interface: %s (%s)"
+msgstr "Netzwerkschnittstelle: %s (%s)"
+
+#: src/devices/rfkill.cpp:65 src/devices/rfkill.cpp:69
+#, c-format
+msgid "Radio device: %s"
+msgstr "Funk-Gerät:%s"
+
+#: src/devices/runtime_pm.cpp:216
+#, c-format
+msgid "I2C %s (%s): %s"
+msgstr ""
+
+#: src/devices/runtime_pm.cpp:216 src/tuning/tuningi2c.cpp:57
+#: src/tuning/tuningi2c.cpp:59
+msgid "Adapter"
+msgstr ""
+
+#: src/devices/runtime_pm.cpp:216 src/devlist.cpp:331
+#: src/tuning/tuningi2c.cpp:57 src/tuning/tuningi2c.cpp:59
+#, fuzzy
+msgid "Device"
+msgstr "Gerät-Statistiken"
+
+#: src/devices/runtime_pm.cpp:241
+#, c-format
+msgid "PCI Device: %s"
+msgstr "PCI-Gerät: %s"
+
+#: src/devices/usb.cpp:51 src/devices/usb.cpp:96 src/devices/usb.cpp:98
+#, c-format
+msgid "USB device: %s"
+msgstr "USB-Gerät: %s"
+
+#: src/devices/usb.cpp:94
+#, c-format
+msgid "USB device: %s (%s)"
+msgstr "USB-Gerät: %s (%s)"
+
+#: src/devlist.cpp:330
+msgid "Process"
+msgstr ""
+
+#: src/devlist.cpp:347
+msgid "Process Device Activity"
+msgstr ""
+
+#: src/display.cpp:70
+msgid "Overview"
+msgstr "Übersicht"
+
+#: src/display.cpp:71
+msgid "Idle stats"
+msgstr "Leerlauf-Statistiken"
+
+#: src/display.cpp:72
+msgid "Frequency stats"
+msgstr "Frequenz-Statistiken"
+
+#: src/display.cpp:73
+msgid "Device stats"
+msgstr "Gerät-Statistiken"
+
+#: src/display.cpp:131
+msgid "Exit"
+msgstr "Beenden"
+
+#: src/display.cpp:132
+msgid "Navigate"
+msgstr ""
+
+#: src/lib.cpp:288
+#, c-format
+msgid "%7sW"
+msgstr "%7sW"
+
+#: src/lib.cpp:291
+#, c-format
+msgid " 0 mW"
+msgstr " 0 mW"
+
+#: src/lib.cpp:410
+msgid "PS/2 Touchpad / Keyboard / Mouse"
+msgstr "PS/2-Tastfeld / Tastatur / Maus"
+
+#: src/lib.cpp:411
+msgid "SATA controller"
+msgstr "SATA-Controller"
+
+#: src/lib.cpp:412
+msgid "Intel built in USB hub"
+msgstr "Intel integrierter USB Hub"
+
+#: src/lib.cpp:467
+#, c-format
+msgid "glob returned GLOB_NOSPACE\n"
+msgstr ""
+
+#: src/lib.cpp:471
+#, c-format
+msgid "glob returned GLOB_ABORTED\n"
+msgstr ""
+
+#: src/lib.cpp:475
+#, c-format
+msgid "glob returned GLOB_NOMATCH\n"
+msgstr ""
+
+#: src/lib.cpp:513 src/lib.cpp:549
+#, c-format
+msgid ""
+"Model-specific registers (MSR)\t\t\t not found (try enabling "
+"CONFIG_X86_MSR).\n"
+msgstr ""
+
+#: src/main.cpp:104
+#, fuzzy, c-format
+msgid "PowerTOP version "
+msgstr "PowerTOP-Version"
+
+#: src/main.cpp:110
+msgid "Set refresh time out"
+msgstr "Aktualisierungs-Zeitüberschreitung festlegen"
+
+#: src/main.cpp:123
+msgid "Usage: powertop [OPTIONS]"
+msgstr "Verwendung: powertop [OPTIONEN]"
+
+#: src/main.cpp:124
+#, fuzzy
+msgid "sets all tunable options to their GOOD setting"
+msgstr "Legt für alle einstellbaren Optionen die jeweils GUTE Einstellung fest"
+
+#: src/main.cpp:125
+msgid "runs powertop in calibration mode"
+msgstr "führt Powertop im Kalibrierungsmodus aus"
+
+#: src/main.cpp:126 src/main.cpp:129
+msgid "[=filename]"
+msgstr ""
+
+#: src/main.cpp:126
+msgid "generate a csv report"
+msgstr "Einen CSV-Bericht generieren"
+
+#: src/main.cpp:127
+msgid "run in \"debug\" mode"
+msgstr "in \"Debug\"-Modus ausführen"
+
+#: src/main.cpp:128
+msgid "[=devnode]"
+msgstr "[=Entwicklungsmodus]"
+
+#: src/main.cpp:128
+msgid "uses an Extech Power Analyzer for measurements"
+msgstr "verwendet einen Extech Leistungsanalysator für Messungen"
+
+#: src/main.cpp:129
+msgid "generate a html report"
+msgstr "Einen HTML-Bericht generieren"
+
+#: src/main.cpp:130
+msgid "[=iterations] number of times to run each test"
+msgstr "[=Wiederholungen] Anzahl der Wiederholungen für jeden Testlauf"
+
+#: src/main.cpp:131
+msgid "suppress stderr output"
+msgstr "stderr-Ausgabe unterdrücken"
+
+#: src/main.cpp:132 src/main.cpp:133
+msgid "[=seconds]"
+msgstr "[=Sekunden]"
+
+#: src/main.cpp:132
+msgid "interval for power consumption measurement"
+msgstr ""
+
+#: src/main.cpp:133
+msgid "generate a report for 'x' seconds"
+msgstr "Einen Bericht für 'x'-Sekunden generieren"
+
+#: src/main.cpp:134
+msgid "[=workload]"
+msgstr "[=Auslastung]"
+
+#: src/main.cpp:134
+msgid "file to execute for workload"
+msgstr "Für Auslastung auszuführende Datei"
+
+#: src/main.cpp:135
+msgid "print version information"
+msgstr "Versionsinformation ausgeben"
+
+#: src/main.cpp:136
+msgid "print this help menu"
+msgstr "Dieses Hilfemenü ausgeben"
+
+#: src/main.cpp:138
+#, fuzzy
+msgid "For more help please refer to the 'man 8 powertop'"
+msgstr "Für weitere Hilfe ziehen Sie bitte die README zu Rate"
+
+#: src/main.cpp:233
+#, c-format
+msgid "Unknown issue running workload!\n"
+msgstr "Unbekanntes Ergebnis beim Ausführen der Arbeitsbelastung\n"
+
+#: src/main.cpp:290
+msgid "PowerTOP is out of memory. PowerTOP is Aborting"
+msgstr ""
+"PowerTOP hat keinen Speicherplatz mehr im Hauptspeicher. PowerTOP wird "
+"abgebrochen"
+
+#: src/main.cpp:298
+#, c-format
+msgid "Preparing to take measurements\n"
+msgstr "Das Vornehmen von Messungen wird vorbereitet\n"
+
+#: src/main.cpp:303
+#, c-format
+msgid "Taking %d measurement(s) for a duration of %d second(s) each.\n"
+msgstr ""
+"%d Messung(en) mit einer Dauer von je %d Sekunde(n) wird/werden "
+"vorgenommen.\n"
+
+#: src/main.cpp:305
+#, c-format
+msgid "Measuring workload %s.\n"
+msgstr "Auslastung %s wird gemessen.\n"
+
+#: src/main.cpp:330
+#, c-format
+msgid "PowerTOP "
+msgstr "PowerTOP "
+
+#: src/main.cpp:331 src/main.cpp:381
+#, c-format
+msgid "exiting...\n"
+msgstr "Verlassen ...\n"
+
+#: src/main.cpp:365
+#, c-format
+msgid "modprobe cpufreq_stats failed\n"
+msgstr ""
+
+#: src/main.cpp:368
+#, c-format
+msgid "modprobe msr failed\n"
+msgstr ""
+
+#: src/main.cpp:380 src/main.cpp:384
+#, c-format
+msgid "Failed to mount debugfs!\n"
+msgstr "Das Einhängen von debugfs ist gescheitert!\n"
+
+#: src/main.cpp:385
+#, c-format
+msgid "Should still be able to auto tune...\n"
+msgstr ""
+
+#: src/main.cpp:467
+#, c-format
+msgid "Invalid CSV filename\n"
+msgstr ""
+
+#: src/main.cpp:483
+#, c-format
+msgid "Invalid HTML filename\n"
+msgstr ""
+
+#: src/main.cpp:492
+#, c-format
+msgid "Quiet mode failed!\n"
+msgstr ""
+
+#: src/main.cpp:560
+msgid "Leaving PowerTOP"
+msgstr "PowerTOP wird verlassen"
+
+#: src/parameters/persistent.cpp:46 src/parameters/persistent.cpp:155
+msgid "Cannot save to file"
+msgstr "Kann Datei nicht abspeichern"
+
+#: src/parameters/persistent.cpp:89 src/parameters/persistent.cpp:180
+msgid "Cannot load from file"
+msgstr "Kann nicht von Datei laden"
+
+#: src/parameters/persistent.cpp:138
+#, c-format
+msgid "Loaded %i prior measurements\n"
+msgstr "%i geladene vorherige Messungen\n"
+
+#: src/parameters/persistent.cpp:181
+msgid ""
+"File will be loaded after taking minimum number of measurement(s) with "
+"battery only \n"
+msgstr ""
+
+#: src/perf/perf.cpp:115
+#, c-format
+msgid ""
+"Too many open files, please increase the limit of open file descriptors.\n"
+msgstr ""
+"Zu viele offene Dateien. Bitte erhöhen Sie die Begrenzung von offenen "
+"Dateideskriptoren.\n"
+
+#: src/perf/perf.cpp:117
+#, c-format
+msgid "PowerTOP %s needs the kernel to support the 'perf' subsystem\n"
+msgstr ""
+"PowerTOP %s benötigt einen Kernel der das 'perf'-Subsystem unterstützt\n"
+
+#: src/perf/perf.cpp:118
+#, c-format
+msgid "as well as support for trace points in the kernel:\n"
+msgstr "sowie Unterstützung für Ablaufverfolgungspunkte im Kernel:\n"
+
+#: src/process/do_process.cpp:819
+#, c-format
+msgid ""
+"Estimated power: %5.1f Measured power: %5.1f Sum: %5.1f\n"
+"\n"
+msgstr ""
+"Geschätzter Stromverbrauch: %5.1f Gemessener Stromverbrauch: %5.1f "
+"Summe: %5.1f\\n\n"
+
+#: src/process/do_process.cpp:838
+#, c-format
+msgid "The estimated remaining time is %i hours, %i minutes\n"
+msgstr "Die geschätzte Restzeit beträgt %i Stunden, %i Minuten\n"
+
+#: src/process/do_process.cpp:846
+msgid "Summary"
+msgstr "Zusammenfassung"
+
+#: src/process/do_process.cpp:846
+msgid "wakeups/second"
+msgstr "Aufwachvorgänge/Sekunde"
+
+#: src/process/do_process.cpp:846
+msgid "GPU ops/seconds"
+msgstr "GPU-Operationen/Sekunde"
+
+#: src/process/do_process.cpp:846
+msgid "VFS ops/sec and"
+msgstr "VFS-Operationen/Sekunde und"
+
+#: src/process/do_process.cpp:846
+msgid "CPU use"
+msgstr "CPU-Nutzung"
+
+#: src/process/do_process.cpp:850
+msgid "Power est."
+msgstr "Gesch. Leistung"
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:1078
+msgid "Events/s"
+msgstr "Ereignisse/s"
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:931 src/process/do_process.cpp:1079
+msgid "Category"
+msgstr "Kategorie"
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:932 src/process/do_process.cpp:1080
+#: src/tuning/tuning.cpp:242 src/tuning/tuning.cpp:270
+#: src/tuning/tuning.cpp:295 src/wakeup/waketab.cpp:155
+msgid "Description"
+msgstr "Beschreibung"
+
+#: src/process/do_process.cpp:927
+msgid "Wakeups/s"
+msgstr "Aufwachvorgänge/s"
+
+#: src/process/do_process.cpp:928
+msgid "GPU ops/s"
+msgstr "GPU-Operationen/s"
+
+#: src/process/do_process.cpp:929
+msgid "Disk IO/s"
+msgstr "Platten-Ein-/Ausgabe/s"
+
+#: src/process/do_process.cpp:930
+msgid "GFX Wakeups/s"
+msgstr "GFX-Aufwachvorgänge/s"
+
+#: src/process/do_process.cpp:1017
+msgid "Overview of Software Power Consumers"
+msgstr "Übersicht der Software-Leistungsverbraucher"
+
+#: src/process/do_process.cpp:1057
+msgid "Target:"
+msgstr ""
+
+#: src/process/do_process.cpp:1058
+msgid "1 units/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1059
+msgid "System: "
+msgstr ""
+
+#: src/process/do_process.cpp:1061
+#, fuzzy
+msgid " wakeup/s"
+msgstr "Aufwachvorgänge/s"
+
+#: src/process/do_process.cpp:1062
+msgid "CPU: "
+msgstr ""
+
+#: src/process/do_process.cpp:1064
+#, fuzzy, c-format
+msgid "% usage"
+msgstr "Auslastung"
+
+#: src/process/do_process.cpp:1065
+msgid "GPU:"
+msgstr ""
+
+#: src/process/do_process.cpp:1067 src/process/do_process.cpp:1073
+#, fuzzy
+msgid " ops/s"
+msgstr "GPU-Operationen/s"
+
+#: src/process/do_process.cpp:1068
+msgid "GFX:"
+msgstr ""
+
+#: src/process/do_process.cpp:1070
+#, fuzzy
+msgid " wakeups/s"
+msgstr "Aufwachvorgänge/s"
+
+#: src/process/do_process.cpp:1071
+msgid "VFS:"
+msgstr ""
+
+#: src/process/do_process.cpp:1139
+#, fuzzy
+msgid "Top 10 Power Consumers"
+msgstr "Übersicht der Software-Leistungsverbraucher"
+
+#: src/report/report.cpp:122
+#, fuzzy
+msgid "PowerTOP Version"
+msgstr "PowerTOP-Version"
+
+#: src/report/report.cpp:131
+#, fuzzy
+msgid "Kernel Version"
+msgstr "PowerTOP-Version"
+
+#: src/report/report.cpp:135
+msgid "System Name"
+msgstr ""
+
+#: src/report/report.cpp:142
+msgid "CPU Information"
+msgstr ""
+
+#: src/report/report.cpp:154
+msgid "OS Information"
+msgstr ""
+
+#: src/report/report.cpp:161
+#, fuzzy
+msgid "System Information"
+msgstr "Versionsinformation ausgeben"
+
+#: src/report/report.cpp:195
+#, fuzzy, c-format
+msgid "Cannot open output file %s (%s)\n"
+msgstr "Temporäre Datei konnte nicht erzeugt werden\n"
+
+#: src/report/report.cpp:211
+#, c-format
+msgid "PowerTOP outputting using base filename %s\n"
+msgstr ""
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:49
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45
+msgid "Good"
+msgstr "Gut"
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:50
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45
+msgid "Bad"
+msgstr "Schlecht"
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:51
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45 src/wakeup/wakeup.cpp:50
+msgid "Unknown"
+msgstr "Unbekannt"
+
+#: src/tuning/bluetooth.cpp:48
+#, c-format
+msgid "Bluetooth device interface status"
+msgstr "Bluetooth-Gerät Schnittstellenstatus"
+
+#: src/tuning/ethernet.cpp:54 src/wakeup/wakeup_ethernet.cpp:51
+#, c-format
+msgid "Wake-on-lan status for device %s"
+msgstr "Wake-On-LAN-Status für Gerät %s"
+
+#: src/tuning/runtime.cpp:48
+#, c-format
+msgid "Runtime PM for %s device %s"
+msgstr "Laufzeit-Energieverwaltung für %s Gerät %s"
+
+#: src/tuning/runtime.cpp:50
+#, c-format
+msgid "%s device %s has no runtime power management"
+msgstr "%s Gerät %s hat keine Energieverwaltung zur Laufzeit"
+
+#: src/tuning/runtime.cpp:74
+#, c-format
+msgid "PCI Device %s has no runtime power management"
+msgstr "PCI-Gerät %s hat keine Energieverwaltung zur Laufzeit"
+
+#: src/tuning/runtime.cpp:76
+#, c-format
+msgid "Runtime PM for PCI Device %s"
+msgstr "Laufzeit-Energieverwaltung für PCI-Gerät %s"
+
+#: src/tuning/runtime.cpp:80
+#, fuzzy, c-format
+msgid "Runtime PM for port %s of PCI device: %s"
+msgstr "Laufzeit-Energieverwaltung für %s Gerät %s"
+
+#: src/tuning/runtime.cpp:83
+#, fuzzy, c-format
+msgid "Runtime PM for disk %s"
+msgstr "Laufzeit-Energieverwaltung für %s Gerät %s"
+
+#: src/tuning/tuning.cpp:62
+msgid "Enable Audio codec power management"
+msgstr "Energieverwaltung für Audiocodec aktivieren"
+
+#: src/tuning/tuning.cpp:63
+msgid "NMI watchdog should be turned off"
+msgstr "NMI watchdog sollte ausgeschaltet sein"
+
+#: src/tuning/tuning.cpp:64
+msgid "Power Aware CPU scheduler"
+msgstr "Leistungsbewusster CPU-Scheduler"
+
+#: src/tuning/tuning.cpp:65
+msgid "VM writeback timeout"
+msgstr "Zeitüberschreitung beim VM zurückschreiben"
+
+#: src/tuning/tuning.cpp:81
+msgid "Tunables"
+msgstr "Abstimmbare Optionen"
+
+#: src/tuning/tuning.cpp:81
+msgid " <ESC> Exit | <Enter> Toggle tunable | <r> Window refresh"
+msgstr ""
+" <ESC> Beenden | <Enter> Abstimmbare Option umschalten | <r> Fenster "
+"aktualisieren"
+
+#: src/tuning/tuning.cpp:243 src/wakeup/waketab.cpp:156
+msgid "Script"
+msgstr ""
+
+#: src/tuning/tuning.cpp:257
+msgid "Software Settings in Need of Tuning"
+msgstr ""
+
+#: src/tuning/tuning.cpp:276
+msgid "Untunable Software Issues"
+msgstr ""
+
+#: src/tuning/tuning.cpp:307
+msgid "Optimal Tuned Software Settings"
+msgstr ""
+
+#: src/tuning/tuningi2c.cpp:57
+#, fuzzy, c-format
+msgid "Runtime PM for I2C %s %s (%s)"
+msgstr "Laufzeit-Energieverwaltung für %s Gerät %s"
+
+#: src/tuning/tuningi2c.cpp:59
+#, fuzzy, c-format
+msgid "I2C %s %s has no runtime power management"
+msgstr "%s Gerät %s hat keine Energieverwaltung zur Laufzeit"
+
+#: src/tuning/tuningsysfs.cpp:123
+#, fuzzy, c-format
+msgid "Enable SATA link power management for %s"
+msgstr "Energieverwaltung für SATA-Verbindung %s aktivieren"
+
+#: src/tuning/tuningusb.cpp:54
+#, c-format
+msgid "Autosuspend for unknown USB device %s (%s:%s)"
+msgstr "AutoSuspend für unbekanntes USB-Gerät %s (%s:%s)"
+
+#: src/tuning/tuningusb.cpp:71 src/tuning/tuningusb.cpp:73
+#: src/tuning/tuningusb.cpp:75
+#, c-format
+msgid "Autosuspend for USB device %s [%s]"
+msgstr "AutoSuspend für USB-Gerät %s [%s]"
+
+#: src/tuning/wifi.cpp:48
+#, c-format
+msgid "Wireless Power Saving for interface %s"
+msgstr "Drahtloses Stromsparen für Schnittstelle %s"
+
+#: src/wakeup/waketab.cpp:42
+#, fuzzy
+msgid "WakeUp"
+msgstr "Aufwachvorgänge/s"
+
+#: src/wakeup/waketab.cpp:42
+#, fuzzy
+msgid " <ESC> Exit | <Enter> Toggle wakeup | <r> Window refresh"
+msgstr ""
+" <ESC> Beenden | <Enter> Abstimmbare Option umschalten | <r> Fenster "
+"aktualisieren"
+
+#: src/wakeup/waketab.cpp:170
+#, fuzzy
+msgid "Wake status of the devices"
+msgstr "Wake-On-LAN-Status für Gerät %s"
+
+#: src/wakeup/wakeup.cpp:48 src/wakeup/wakeup_ethernet.cpp:47
+#: src/wakeup/wakeup_usb.cpp:47
+#, fuzzy
+msgid "Enabled"
+msgstr "Abstimmbare Optionen"
+
+#: src/wakeup/wakeup.cpp:49 src/wakeup/wakeup_ethernet.cpp:47
+#: src/wakeup/wakeup_usb.cpp:47
+msgid "Disabled"
+msgstr ""
+
+#: src/wakeup/wakeup_usb.cpp:51
+#, fuzzy, c-format
+msgid "Wake status for USB device %s"
+msgstr "Wake-On-LAN-Status für Gerät %s"
+
+#~ msgid "Actual"
+#~ msgstr "Aktuell"
+
+#, fuzzy
+#~ msgid "I2C Device: %s"
+#~ msgstr "PCI-Gerät: %s"
+
+#~ msgid "[=FILENAME]"
+#~ msgstr "[=DATEINAME]"
+
+#~ msgid "Using 'ondemand' cpufreq governor"
+#~ msgstr "CPU-Frequenzregler 'bei Bedarf' verwenden"
+
+#~ msgid "Power Consumption Summary"
+#~ msgstr "Zusammenfassung der Leistungsaufnahme"
+
+#~ msgid "GPU ops/second"
+#~ msgstr "GPU-Operationen/Sekunde"
+
+#~ msgid "VFS ops/sec"
+#~ msgstr "VFS-Operationen/Sek"
+
+#~ msgid "GFX wakes/sec and"
+#~ msgstr "GFX-Aufwachen/Sek und"
diff --git a/po/en_GB.po b/po/en_GB.po
new file mode 100644
index 0000000..f3b6c1e
--- /dev/null
+++ b/po/en_GB.po
@@ -0,0 +1,967 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Intel Corporation
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Margie Foster <margie@linux.intel.com>, 2012
+# Patrick McCarty <patrick.mccarty@linux.intel.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: PowerTOP\n"
+"Report-Msgid-Bugs-To: \"powertop@lists.01.org\"\n"
+"POT-Creation-Date: 2022-09-29 04:45-0700\n"
+"PO-Revision-Date: 2013-11-05 08:40+0000\n"
+"Last-Translator: Margie Foster <margie@linux.intel.com>\n"
+"Language-Team: English (United Kingdom) (http://www.transifex.com/projects/p/"
+"PowerTOP/language/en_GB/)\n"
+"Language: en_GB\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/calibrate/calibrate.cpp:238
+#, c-format
+msgid "Cannot create temp file\n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:258
+#, c-format
+msgid "Calibrating: CPU usage on %i threads\n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:273
+#, c-format
+msgid "Calibrating: CPU wakeup power consumption\n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:290
+#, c-format
+msgid "Calibrating USB devices\n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:292 src/calibrate/calibrate.cpp:309
+#: src/calibrate/calibrate.cpp:317 src/calibrate/calibrate.cpp:334
+#, c-format
+msgid ".... device %s \n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:307
+#, c-format
+msgid "Calibrating radio devices\n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:331
+#, c-format
+msgid "Calibrating backlight\n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:355 src/calibrate/calibrate.cpp:365
+#, c-format
+msgid "Calibrating idle\n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:378
+#, c-format
+msgid "Calibrating: disk usage \n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:403
+msgid "Starting PowerTOP power estimate calibration \n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:426
+msgid "Finishing PowerTOP power estimate calibration \n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:430
+#, c-format
+msgid "Parameters after calibration:\n"
+msgstr ""
+
+#: src/cpu/abstract_cpu.cpp:74
+msgid "Idle"
+msgstr ""
+
+#: src/cpu/abstract_cpu.cpp:76
+msgid "Turbo Mode"
+msgstr ""
+
+#: src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(HW)"
+msgstr ""
+
+#: src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(OS)"
+msgstr ""
+
+#: src/cpu/cpu_core.cpp:91 src/cpu/intel_cpus.cpp:367
+#, c-format
+msgid " Core"
+msgstr ""
+
+#: src/cpu/cpu.cpp:85
+#, c-format
+msgid "cpu package %i"
+msgstr "CPU package %i"
+
+#: src/cpu/cpu.cpp:86
+msgid "cpu package"
+msgstr "CPU package"
+
+#: src/cpu/cpu.cpp:89 src/cpu/cpu.cpp:96
+#, fuzzy, c-format
+msgid "package-%i"
+msgstr "CPU package %i"
+
+#: src/cpu/cpu.cpp:90
+msgid "cpu rapl package"
+msgstr ""
+
+#: src/cpu/cpu.cpp:97
+msgid "dram rapl package"
+msgstr ""
+
+#: src/cpu/cpu.cpp:471
+msgid "Processor Idle State Report"
+msgstr ""
+
+#: src/cpu/cpu.cpp:535 src/cpu/cpu.cpp:761
+msgid "Package"
+msgstr ""
+
+#: src/cpu/cpu.cpp:572 src/cpu/cpu.cpp:783
+#, c-format
+msgid "Core %d"
+msgstr ""
+
+#: src/cpu/cpu.cpp:579
+#, c-format
+msgid "GPU %d"
+msgstr ""
+
+#: src/cpu/cpu.cpp:602
+msgid "CPU"
+msgstr ""
+
+#: src/cpu/cpu.cpp:684
+msgid "Processor Frequency Report"
+msgstr ""
+
+#: src/cpu/cpu.cpp:804
+#, c-format
+msgid "CPU %d"
+msgstr ""
+
+#: src/cpu/cpu.cpp:1005
+#, c-format
+msgid "cpu_idle event returned no state?\n"
+msgstr ""
+
+#: src/cpu/cpu.cpp:1020
+#, c-format
+msgid "power or cpu_frequency event returned no state?\n"
+msgstr ""
+
+#: src/cpu/cpu_linux.cpp:79
+msgid "C0 polling"
+msgstr "C0 polling"
+
+#: src/cpu/cpu_linux.cpp:242
+#, c-format
+msgid " CPU(OS) %i"
+msgstr ""
+
+#: src/cpu/cpu_linux.cpp:341 src/cpu/intel_cpus.cpp:733
+#, c-format
+msgid " CPU %i"
+msgstr ""
+
+#: src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(HW)"
+msgstr ""
+
+#: src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(OS)"
+msgstr ""
+
+#: src/cpu/cpu_package.cpp:104 src/cpu/intel_cpus.cpp:498
+#, c-format
+msgid " Package"
+msgstr ""
+
+#: src/cpu/intel_cpus.cpp:152
+#, c-format
+msgid "read_msr cpu%d 0x%llx : "
+msgstr ""
+
+#: src/cpu/intel_cpus.cpp:656
+msgid "C0 active"
+msgstr "C0 active"
+
+#: src/cpu/intel_cpus.cpp:714
+#, c-format
+msgid "Average"
+msgstr ""
+
+#: src/cpu/intel_gpu.cpp:64
+#, c-format
+msgid " GPU "
+msgstr ""
+
+#: src/devices/ahci.cpp:154
+#, c-format
+msgid "SATA link: %s"
+msgstr ""
+
+#: src/devices/ahci.cpp:156
+#, c-format
+msgid "SATA disk: %s"
+msgstr ""
+
+#: src/devices/ahci.cpp:374
+msgid "AHCI ALPM Residency Statistics - Not supported on this macine"
+msgstr ""
+
+#: src/devices/ahci.cpp:389
+msgid "Link"
+msgstr ""
+
+#: src/devices/ahci.cpp:390
+#, fuzzy
+msgid "Active"
+msgstr "C0 active"
+
+#: src/devices/ahci.cpp:391
+msgid "Partial"
+msgstr ""
+
+#: src/devices/ahci.cpp:392
+msgid "Slumber"
+msgstr ""
+
+#: src/devices/ahci.cpp:393
+msgid "Devslp"
+msgstr ""
+
+#: src/devices/ahci.cpp:399
+msgid "AHCI ALPM Residency Statistics"
+msgstr ""
+
+#: src/devices/alsa.cpp:77
+#, c-format
+msgid "Audio codec %s: %s (%s)"
+msgstr ""
+
+#: src/devices/alsa.cpp:79 src/devices/alsa.cpp:81
+#, c-format
+msgid "Audio codec %s: %s"
+msgstr ""
+
+#: src/devices/devfreq.cpp:260
+#, fuzzy
+msgid "Device Freq stats"
+msgstr "Device stats"
+
+#: src/devices/devfreq.cpp:278
+msgid " Devfreq is not enabled"
+msgstr ""
+
+#: src/devices/devfreq.cpp:283
+msgid " No devfreq devices available"
+msgstr ""
+
+#: src/devices/device.cpp:172 src/process/do_process.cpp:831
+#, c-format
+msgid "The battery reports a discharge rate of %sW\n"
+msgstr "The battery reports a discharge rate of %sW\n"
+
+#: src/devices/device.cpp:174 src/process/do_process.cpp:833
+#, c-format
+msgid "The energy consumed was %sJ\n"
+msgstr ""
+
+#: src/devices/device.cpp:180
+#, c-format
+msgid "System baseline power is estimated at %sW\n"
+msgstr "System baseline power is estimated at %sW\n"
+
+#: src/devices/device.cpp:187
+msgid "Power est. Usage Device name\n"
+msgstr "Power est. Usage Device name\n"
+
+#: src/devices/device.cpp:189
+msgid " Usage Device name\n"
+msgstr ""
+
+#: src/devices/device.cpp:256
+#, fuzzy
+msgid "The battery reports a discharge rate of: "
+msgstr "The battery reports a discharge rate of %sW\n"
+
+#: src/devices/device.cpp:261
+msgid "The energy consumed was : "
+msgstr ""
+
+#: src/devices/device.cpp:268
+#, fuzzy
+msgid "The system baseline power is estimated at: "
+msgstr "System baseline power is estimated at %sW\n"
+
+#: src/devices/device.cpp:277 src/process/do_process.cpp:850
+#: src/process/do_process.cpp:852 src/process/do_process.cpp:926
+#: src/process/do_process.cpp:1077
+msgid "Usage"
+msgstr "Usage"
+
+#: src/devices/device.cpp:278
+#, fuzzy
+msgid "Device Name"
+msgstr "Device stats"
+
+#: src/devices/device.cpp:280 src/process/do_process.cpp:935
+#: src/process/do_process.cpp:1082
+msgid "PW Estimate"
+msgstr ""
+
+#: src/devices/device.cpp:317
+msgid "Device Power Report"
+msgstr ""
+
+#: src/devices/network.cpp:177
+#, c-format
+msgid "Network interface: %s (%s)"
+msgstr ""
+
+#: src/devices/rfkill.cpp:65 src/devices/rfkill.cpp:69
+#, c-format
+msgid "Radio device: %s"
+msgstr ""
+
+#: src/devices/runtime_pm.cpp:216
+#, c-format
+msgid "I2C %s (%s): %s"
+msgstr ""
+
+#: src/devices/runtime_pm.cpp:216 src/tuning/tuningi2c.cpp:57
+#: src/tuning/tuningi2c.cpp:59
+msgid "Adapter"
+msgstr ""
+
+#: src/devices/runtime_pm.cpp:216 src/devlist.cpp:331
+#: src/tuning/tuningi2c.cpp:57 src/tuning/tuningi2c.cpp:59
+#, fuzzy
+msgid "Device"
+msgstr "Device stats"
+
+#: src/devices/runtime_pm.cpp:241
+#, c-format
+msgid "PCI Device: %s"
+msgstr ""
+
+#: src/devices/usb.cpp:51 src/devices/usb.cpp:96 src/devices/usb.cpp:98
+#, c-format
+msgid "USB device: %s"
+msgstr ""
+
+#: src/devices/usb.cpp:94
+#, c-format
+msgid "USB device: %s (%s)"
+msgstr ""
+
+#: src/devlist.cpp:330
+msgid "Process"
+msgstr ""
+
+#: src/devlist.cpp:347
+msgid "Process Device Activity"
+msgstr ""
+
+#: src/display.cpp:70
+msgid "Overview"
+msgstr "Overview"
+
+#: src/display.cpp:71
+msgid "Idle stats"
+msgstr "Idle stats"
+
+#: src/display.cpp:72
+msgid "Frequency stats"
+msgstr "Frequency stats"
+
+#: src/display.cpp:73
+msgid "Device stats"
+msgstr "Device stats"
+
+#: src/display.cpp:131
+msgid "Exit"
+msgstr ""
+
+#: src/display.cpp:132
+msgid "Navigate"
+msgstr ""
+
+#: src/lib.cpp:288
+#, c-format
+msgid "%7sW"
+msgstr "%7sW"
+
+#: src/lib.cpp:291
+#, c-format
+msgid " 0 mW"
+msgstr " 0 mW"
+
+#: src/lib.cpp:410
+msgid "PS/2 Touchpad / Keyboard / Mouse"
+msgstr "PS/2 Touchpad / Keyboard / Mouse"
+
+#: src/lib.cpp:411
+msgid "SATA controller"
+msgstr "SATA controller"
+
+#: src/lib.cpp:412
+msgid "Intel built in USB hub"
+msgstr "Intel built in USB hub"
+
+#: src/lib.cpp:467
+#, c-format
+msgid "glob returned GLOB_NOSPACE\n"
+msgstr ""
+
+#: src/lib.cpp:471
+#, c-format
+msgid "glob returned GLOB_ABORTED\n"
+msgstr ""
+
+#: src/lib.cpp:475
+#, c-format
+msgid "glob returned GLOB_NOMATCH\n"
+msgstr ""
+
+#: src/lib.cpp:513 src/lib.cpp:549
+#, c-format
+msgid ""
+"Model-specific registers (MSR)\t\t\t not found (try enabling "
+"CONFIG_X86_MSR).\n"
+msgstr ""
+
+#: src/main.cpp:104
+#, c-format
+msgid "PowerTOP version "
+msgstr ""
+
+#: src/main.cpp:110
+msgid "Set refresh time out"
+msgstr ""
+
+#: src/main.cpp:123
+msgid "Usage: powertop [OPTIONS]"
+msgstr ""
+
+#: src/main.cpp:124
+msgid "sets all tunable options to their GOOD setting"
+msgstr ""
+
+#: src/main.cpp:125
+msgid "runs powertop in calibration mode"
+msgstr ""
+
+#: src/main.cpp:126 src/main.cpp:129
+msgid "[=filename]"
+msgstr ""
+
+#: src/main.cpp:126
+msgid "generate a csv report"
+msgstr ""
+
+#: src/main.cpp:127
+msgid "run in \"debug\" mode"
+msgstr ""
+
+#: src/main.cpp:128
+msgid "[=devnode]"
+msgstr ""
+
+#: src/main.cpp:128
+msgid "uses an Extech Power Analyzer for measurements"
+msgstr ""
+
+#: src/main.cpp:129
+msgid "generate a html report"
+msgstr ""
+
+#: src/main.cpp:130
+msgid "[=iterations] number of times to run each test"
+msgstr ""
+
+#: src/main.cpp:131
+msgid "suppress stderr output"
+msgstr ""
+
+#: src/main.cpp:132 src/main.cpp:133
+msgid "[=seconds]"
+msgstr ""
+
+#: src/main.cpp:132
+msgid "interval for power consumption measurement"
+msgstr ""
+
+#: src/main.cpp:133
+msgid "generate a report for 'x' seconds"
+msgstr ""
+
+#: src/main.cpp:134
+msgid "[=workload]"
+msgstr ""
+
+#: src/main.cpp:134
+msgid "file to execute for workload"
+msgstr ""
+
+#: src/main.cpp:135
+msgid "print version information"
+msgstr ""
+
+#: src/main.cpp:136
+msgid "print this help menu"
+msgstr ""
+
+#: src/main.cpp:138
+msgid "For more help please refer to the 'man 8 powertop'"
+msgstr ""
+
+#: src/main.cpp:233
+#, c-format
+msgid "Unknown issue running workload!\n"
+msgstr ""
+
+#: src/main.cpp:290
+msgid "PowerTOP is out of memory. PowerTOP is Aborting"
+msgstr ""
+
+#: src/main.cpp:298
+#, c-format
+msgid "Preparing to take measurements\n"
+msgstr ""
+
+#: src/main.cpp:303
+#, c-format
+msgid "Taking %d measurement(s) for a duration of %d second(s) each.\n"
+msgstr ""
+
+#: src/main.cpp:305
+#, c-format
+msgid "Measuring workload %s.\n"
+msgstr ""
+
+#: src/main.cpp:330
+#, c-format
+msgid "PowerTOP "
+msgstr ""
+
+#: src/main.cpp:331 src/main.cpp:381
+#, c-format
+msgid "exiting...\n"
+msgstr ""
+
+#: src/main.cpp:365
+#, c-format
+msgid "modprobe cpufreq_stats failed\n"
+msgstr ""
+
+#: src/main.cpp:368
+#, c-format
+msgid "modprobe msr failed\n"
+msgstr ""
+
+#: src/main.cpp:380 src/main.cpp:384
+#, c-format
+msgid "Failed to mount debugfs!\n"
+msgstr ""
+
+#: src/main.cpp:385
+#, c-format
+msgid "Should still be able to auto tune...\n"
+msgstr ""
+
+#: src/main.cpp:467
+#, c-format
+msgid "Invalid CSV filename\n"
+msgstr ""
+
+#: src/main.cpp:483
+#, c-format
+msgid "Invalid HTML filename\n"
+msgstr ""
+
+#: src/main.cpp:492
+#, c-format
+msgid "Quiet mode failed!\n"
+msgstr ""
+
+#: src/main.cpp:560
+msgid "Leaving PowerTOP"
+msgstr ""
+
+#: src/parameters/persistent.cpp:46 src/parameters/persistent.cpp:155
+msgid "Cannot save to file"
+msgstr ""
+
+#: src/parameters/persistent.cpp:89 src/parameters/persistent.cpp:180
+msgid "Cannot load from file"
+msgstr ""
+
+#: src/parameters/persistent.cpp:138
+#, c-format
+msgid "Loaded %i prior measurements\n"
+msgstr "Loaded %i prior measurements\n"
+
+#: src/parameters/persistent.cpp:181
+msgid ""
+"File will be loaded after taking minimum number of measurement(s) with "
+"battery only \n"
+msgstr ""
+
+#: src/perf/perf.cpp:115
+#, c-format
+msgid ""
+"Too many open files, please increase the limit of open file descriptors.\n"
+msgstr ""
+
+#: src/perf/perf.cpp:117
+#, c-format
+msgid "PowerTOP %s needs the kernel to support the 'perf' subsystem\n"
+msgstr "PowerTOP %s needs the kernel to support the 'perf' subsystem\n"
+
+#: src/perf/perf.cpp:118
+#, c-format
+msgid "as well as support for trace points in the kernel:\n"
+msgstr "as well as support for trace points in the kernel:\n"
+
+#: src/process/do_process.cpp:819
+#, c-format
+msgid ""
+"Estimated power: %5.1f Measured power: %5.1f Sum: %5.1f\n"
+"\n"
+msgstr ""
+"Estimated power: %5.1f Measured power: %5.1f Sum: %5.1f\n"
+"\n"
+
+#: src/process/do_process.cpp:838
+#, c-format
+msgid "The estimated remaining time is %i hours, %i minutes\n"
+msgstr ""
+
+#: src/process/do_process.cpp:846
+msgid "Summary"
+msgstr ""
+
+#: src/process/do_process.cpp:846
+msgid "wakeups/second"
+msgstr ""
+
+#: src/process/do_process.cpp:846
+msgid "GPU ops/seconds"
+msgstr ""
+
+#: src/process/do_process.cpp:846
+msgid "VFS ops/sec and"
+msgstr ""
+
+#: src/process/do_process.cpp:846
+msgid "CPU use"
+msgstr ""
+
+#: src/process/do_process.cpp:850
+msgid "Power est."
+msgstr ""
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:1078
+msgid "Events/s"
+msgstr ""
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:931 src/process/do_process.cpp:1079
+msgid "Category"
+msgstr ""
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:932 src/process/do_process.cpp:1080
+#: src/tuning/tuning.cpp:242 src/tuning/tuning.cpp:270
+#: src/tuning/tuning.cpp:295 src/wakeup/waketab.cpp:155
+msgid "Description"
+msgstr ""
+
+#: src/process/do_process.cpp:927
+msgid "Wakeups/s"
+msgstr ""
+
+#: src/process/do_process.cpp:928
+msgid "GPU ops/s"
+msgstr ""
+
+#: src/process/do_process.cpp:929
+msgid "Disk IO/s"
+msgstr ""
+
+#: src/process/do_process.cpp:930
+msgid "GFX Wakeups/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1017
+msgid "Overview of Software Power Consumers"
+msgstr ""
+
+#: src/process/do_process.cpp:1057
+msgid "Target:"
+msgstr ""
+
+#: src/process/do_process.cpp:1058
+msgid "1 units/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1059
+msgid "System: "
+msgstr ""
+
+#: src/process/do_process.cpp:1061
+msgid " wakeup/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1062
+msgid "CPU: "
+msgstr ""
+
+#: src/process/do_process.cpp:1064
+#, fuzzy, c-format
+msgid "% usage"
+msgstr "Usage"
+
+#: src/process/do_process.cpp:1065
+msgid "GPU:"
+msgstr ""
+
+#: src/process/do_process.cpp:1067 src/process/do_process.cpp:1073
+msgid " ops/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1068
+msgid "GFX:"
+msgstr ""
+
+#: src/process/do_process.cpp:1070
+msgid " wakeups/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1071
+msgid "VFS:"
+msgstr ""
+
+#: src/process/do_process.cpp:1139
+msgid "Top 10 Power Consumers"
+msgstr ""
+
+#: src/report/report.cpp:122
+msgid "PowerTOP Version"
+msgstr ""
+
+#: src/report/report.cpp:131
+msgid "Kernel Version"
+msgstr ""
+
+#: src/report/report.cpp:135
+msgid "System Name"
+msgstr ""
+
+#: src/report/report.cpp:142
+msgid "CPU Information"
+msgstr ""
+
+#: src/report/report.cpp:154
+msgid "OS Information"
+msgstr ""
+
+#: src/report/report.cpp:161
+msgid "System Information"
+msgstr ""
+
+#: src/report/report.cpp:195
+#, c-format
+msgid "Cannot open output file %s (%s)\n"
+msgstr ""
+
+#: src/report/report.cpp:211
+#, c-format
+msgid "PowerTOP outputting using base filename %s\n"
+msgstr ""
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:49
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45
+msgid "Good"
+msgstr ""
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:50
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45
+msgid "Bad"
+msgstr ""
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:51
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45 src/wakeup/wakeup.cpp:50
+msgid "Unknown"
+msgstr ""
+
+#: src/tuning/bluetooth.cpp:48
+#, c-format
+msgid "Bluetooth device interface status"
+msgstr ""
+
+#: src/tuning/ethernet.cpp:54 src/wakeup/wakeup_ethernet.cpp:51
+#, c-format
+msgid "Wake-on-lan status for device %s"
+msgstr ""
+
+#: src/tuning/runtime.cpp:48
+#, c-format
+msgid "Runtime PM for %s device %s"
+msgstr ""
+
+#: src/tuning/runtime.cpp:50
+#, c-format
+msgid "%s device %s has no runtime power management"
+msgstr ""
+
+#: src/tuning/runtime.cpp:74
+#, c-format
+msgid "PCI Device %s has no runtime power management"
+msgstr ""
+
+#: src/tuning/runtime.cpp:76
+#, c-format
+msgid "Runtime PM for PCI Device %s"
+msgstr ""
+
+#: src/tuning/runtime.cpp:80
+#, c-format
+msgid "Runtime PM for port %s of PCI device: %s"
+msgstr ""
+
+#: src/tuning/runtime.cpp:83
+#, c-format
+msgid "Runtime PM for disk %s"
+msgstr ""
+
+#: src/tuning/tuning.cpp:62
+msgid "Enable Audio codec power management"
+msgstr ""
+
+#: src/tuning/tuning.cpp:63
+msgid "NMI watchdog should be turned off"
+msgstr ""
+
+#: src/tuning/tuning.cpp:64
+msgid "Power Aware CPU scheduler"
+msgstr ""
+
+#: src/tuning/tuning.cpp:65
+msgid "VM writeback timeout"
+msgstr ""
+
+#: src/tuning/tuning.cpp:81
+msgid "Tunables"
+msgstr ""
+
+#: src/tuning/tuning.cpp:81
+msgid " <ESC> Exit | <Enter> Toggle tunable | <r> Window refresh"
+msgstr ""
+
+#: src/tuning/tuning.cpp:243 src/wakeup/waketab.cpp:156
+msgid "Script"
+msgstr ""
+
+#: src/tuning/tuning.cpp:257
+msgid "Software Settings in Need of Tuning"
+msgstr ""
+
+#: src/tuning/tuning.cpp:276
+msgid "Untunable Software Issues"
+msgstr ""
+
+#: src/tuning/tuning.cpp:307
+msgid "Optimal Tuned Software Settings"
+msgstr ""
+
+#: src/tuning/tuningi2c.cpp:57
+#, c-format
+msgid "Runtime PM for I2C %s %s (%s)"
+msgstr ""
+
+#: src/tuning/tuningi2c.cpp:59
+#, c-format
+msgid "I2C %s %s has no runtime power management"
+msgstr ""
+
+#: src/tuning/tuningsysfs.cpp:123
+#, c-format
+msgid "Enable SATA link power management for %s"
+msgstr ""
+
+#: src/tuning/tuningusb.cpp:54
+#, c-format
+msgid "Autosuspend for unknown USB device %s (%s:%s)"
+msgstr ""
+
+#: src/tuning/tuningusb.cpp:71 src/tuning/tuningusb.cpp:73
+#: src/tuning/tuningusb.cpp:75
+#, c-format
+msgid "Autosuspend for USB device %s [%s]"
+msgstr ""
+
+#: src/tuning/wifi.cpp:48
+#, c-format
+msgid "Wireless Power Saving for interface %s"
+msgstr ""
+
+#: src/wakeup/waketab.cpp:42
+msgid "WakeUp"
+msgstr ""
+
+#: src/wakeup/waketab.cpp:42
+msgid " <ESC> Exit | <Enter> Toggle wakeup | <r> Window refresh"
+msgstr ""
+
+#: src/wakeup/waketab.cpp:170
+msgid "Wake status of the devices"
+msgstr ""
+
+#: src/wakeup/wakeup.cpp:48 src/wakeup/wakeup_ethernet.cpp:47
+#: src/wakeup/wakeup_usb.cpp:47
+msgid "Enabled"
+msgstr ""
+
+#: src/wakeup/wakeup.cpp:49 src/wakeup/wakeup_ethernet.cpp:47
+#: src/wakeup/wakeup_usb.cpp:47
+msgid "Disabled"
+msgstr ""
+
+#: src/wakeup/wakeup_usb.cpp:51
+#, c-format
+msgid "Wake status for USB device %s"
+msgstr ""
+
+#~ msgid "Actual"
+#~ msgstr "Actual"
+
+#, fuzzy
+#~ msgid "I2C Device: %s"
+#~ msgstr "Device stats"
diff --git a/po/en_US.po b/po/en_US.po
new file mode 100644
index 0000000..d84a26a
--- /dev/null
+++ b/po/en_US.po
@@ -0,0 +1,972 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Intel Corporation
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Dimitris Glezos <glezos@indifex.com>, 2011
+msgid ""
+msgstr ""
+"Project-Id-Version: PowerTOP\n"
+"Report-Msgid-Bugs-To: \"powertop@lists.01.org\"\n"
+"POT-Creation-Date: 2022-09-29 04:45-0700\n"
+"PO-Revision-Date: 2013-11-05 08:40+0000\n"
+"Last-Translator: Margie Foster <margie@linux.intel.com>\n"
+"Language-Team: English (United States) (http://www.transifex.com/projects/p/"
+"PowerTOP/language/en_US/)\n"
+"Language: en_US\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/calibrate/calibrate.cpp:238
+#, c-format
+msgid "Cannot create temp file\n"
+msgstr "Cannot create temp file\n"
+
+#: src/calibrate/calibrate.cpp:258
+#, c-format
+msgid "Calibrating: CPU usage on %i threads\n"
+msgstr "Calibrating: CPU usage on %i threads\n"
+
+#: src/calibrate/calibrate.cpp:273
+#, c-format
+msgid "Calibrating: CPU wakeup power consumption\n"
+msgstr "Calibrating: CPU wakeup power consumption\n"
+
+#: src/calibrate/calibrate.cpp:290
+#, c-format
+msgid "Calibrating USB devices\n"
+msgstr "Calibrating USB devices\n"
+
+#: src/calibrate/calibrate.cpp:292 src/calibrate/calibrate.cpp:309
+#: src/calibrate/calibrate.cpp:317 src/calibrate/calibrate.cpp:334
+#, c-format
+msgid ".... device %s \n"
+msgstr ".... device %s \n"
+
+#: src/calibrate/calibrate.cpp:307
+#, c-format
+msgid "Calibrating radio devices\n"
+msgstr "Calibrating radio devices\n"
+
+#: src/calibrate/calibrate.cpp:331
+#, c-format
+msgid "Calibrating backlight\n"
+msgstr "Calibrating backlight\n"
+
+#: src/calibrate/calibrate.cpp:355 src/calibrate/calibrate.cpp:365
+#, c-format
+msgid "Calibrating idle\n"
+msgstr "Calibrating idle\n"
+
+#: src/calibrate/calibrate.cpp:378
+#, c-format
+msgid "Calibrating: disk usage \n"
+msgstr "Calibrating: disk usage \n"
+
+#: src/calibrate/calibrate.cpp:403
+msgid "Starting PowerTOP power estimate calibration \n"
+msgstr "Starting PowerTOP power estimate calibration \n"
+
+#: src/calibrate/calibrate.cpp:426
+msgid "Finishing PowerTOP power estimate calibration \n"
+msgstr "Finishing PowerTOP power estimate calibration \n"
+
+#: src/calibrate/calibrate.cpp:430
+#, c-format
+msgid "Parameters after calibration:\n"
+msgstr "Parameters after calibration:\n"
+
+#: src/cpu/abstract_cpu.cpp:74
+msgid "Idle"
+msgstr ""
+
+#: src/cpu/abstract_cpu.cpp:76
+msgid "Turbo Mode"
+msgstr ""
+
+#: src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(HW)"
+msgstr ""
+
+#: src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(OS)"
+msgstr ""
+
+#: src/cpu/cpu_core.cpp:91 src/cpu/intel_cpus.cpp:367
+#, c-format
+msgid " Core"
+msgstr ""
+
+#: src/cpu/cpu.cpp:85
+#, c-format
+msgid "cpu package %i"
+msgstr "cpu package %i"
+
+#: src/cpu/cpu.cpp:86
+msgid "cpu package"
+msgstr "cpu package"
+
+#: src/cpu/cpu.cpp:89 src/cpu/cpu.cpp:96
+#, fuzzy, c-format
+msgid "package-%i"
+msgstr "cpu package %i"
+
+#: src/cpu/cpu.cpp:90
+msgid "cpu rapl package"
+msgstr ""
+
+#: src/cpu/cpu.cpp:97
+msgid "dram rapl package"
+msgstr ""
+
+#: src/cpu/cpu.cpp:471
+msgid "Processor Idle State Report"
+msgstr ""
+
+#: src/cpu/cpu.cpp:535 src/cpu/cpu.cpp:761
+msgid "Package"
+msgstr ""
+
+#: src/cpu/cpu.cpp:572 src/cpu/cpu.cpp:783
+#, c-format
+msgid "Core %d"
+msgstr ""
+
+#: src/cpu/cpu.cpp:579
+#, c-format
+msgid "GPU %d"
+msgstr ""
+
+#: src/cpu/cpu.cpp:602
+msgid "CPU"
+msgstr ""
+
+#: src/cpu/cpu.cpp:684
+msgid "Processor Frequency Report"
+msgstr ""
+
+#: src/cpu/cpu.cpp:804
+#, c-format
+msgid "CPU %d"
+msgstr ""
+
+#: src/cpu/cpu.cpp:1005
+#, c-format
+msgid "cpu_idle event returned no state?\n"
+msgstr ""
+
+#: src/cpu/cpu.cpp:1020
+#, c-format
+msgid "power or cpu_frequency event returned no state?\n"
+msgstr ""
+
+#: src/cpu/cpu_linux.cpp:79
+msgid "C0 polling"
+msgstr "C0 polling"
+
+#: src/cpu/cpu_linux.cpp:242
+#, c-format
+msgid " CPU(OS) %i"
+msgstr ""
+
+#: src/cpu/cpu_linux.cpp:341 src/cpu/intel_cpus.cpp:733
+#, c-format
+msgid " CPU %i"
+msgstr ""
+
+#: src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(HW)"
+msgstr ""
+
+#: src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(OS)"
+msgstr ""
+
+#: src/cpu/cpu_package.cpp:104 src/cpu/intel_cpus.cpp:498
+#, c-format
+msgid " Package"
+msgstr ""
+
+#: src/cpu/intel_cpus.cpp:152
+#, c-format
+msgid "read_msr cpu%d 0x%llx : "
+msgstr ""
+
+#: src/cpu/intel_cpus.cpp:656
+msgid "C0 active"
+msgstr "C0 active"
+
+#: src/cpu/intel_cpus.cpp:714
+#, c-format
+msgid "Average"
+msgstr ""
+
+#: src/cpu/intel_gpu.cpp:64
+#, c-format
+msgid " GPU "
+msgstr ""
+
+#: src/devices/ahci.cpp:154
+#, c-format
+msgid "SATA link: %s"
+msgstr "SATA link: %s"
+
+#: src/devices/ahci.cpp:156
+#, c-format
+msgid "SATA disk: %s"
+msgstr "SATA disk: %s"
+
+#: src/devices/ahci.cpp:374
+msgid "AHCI ALPM Residency Statistics - Not supported on this macine"
+msgstr ""
+
+#: src/devices/ahci.cpp:389
+msgid "Link"
+msgstr ""
+
+#: src/devices/ahci.cpp:390
+#, fuzzy
+msgid "Active"
+msgstr "C0 active"
+
+#: src/devices/ahci.cpp:391
+msgid "Partial"
+msgstr ""
+
+#: src/devices/ahci.cpp:392
+msgid "Slumber"
+msgstr ""
+
+#: src/devices/ahci.cpp:393
+msgid "Devslp"
+msgstr ""
+
+#: src/devices/ahci.cpp:399
+msgid "AHCI ALPM Residency Statistics"
+msgstr ""
+
+#: src/devices/alsa.cpp:77
+#, c-format
+msgid "Audio codec %s: %s (%s)"
+msgstr "Audio codec %s: %s (%s)"
+
+#: src/devices/alsa.cpp:79 src/devices/alsa.cpp:81
+#, c-format
+msgid "Audio codec %s: %s"
+msgstr "Audio codec %s: %s"
+
+#: src/devices/devfreq.cpp:260
+#, fuzzy
+msgid "Device Freq stats"
+msgstr "Device stats"
+
+#: src/devices/devfreq.cpp:278
+msgid " Devfreq is not enabled"
+msgstr ""
+
+#: src/devices/devfreq.cpp:283
+msgid " No devfreq devices available"
+msgstr ""
+
+#: src/devices/device.cpp:172 src/process/do_process.cpp:831
+#, c-format
+msgid "The battery reports a discharge rate of %sW\n"
+msgstr "The battery reports a discharge rate of %sW\n"
+
+#: src/devices/device.cpp:174 src/process/do_process.cpp:833
+#, c-format
+msgid "The energy consumed was %sJ\n"
+msgstr ""
+
+#: src/devices/device.cpp:180
+#, c-format
+msgid "System baseline power is estimated at %sW\n"
+msgstr "System baseline power is estimated at %sW\n"
+
+#: src/devices/device.cpp:187
+msgid "Power est. Usage Device name\n"
+msgstr "Power est. Usage Device name\n"
+
+#: src/devices/device.cpp:189
+msgid " Usage Device name\n"
+msgstr " Usage Device name\n"
+
+#: src/devices/device.cpp:256
+#, fuzzy
+msgid "The battery reports a discharge rate of: "
+msgstr "The battery reports a discharge rate of %sW\n"
+
+#: src/devices/device.cpp:261
+msgid "The energy consumed was : "
+msgstr ""
+
+#: src/devices/device.cpp:268
+#, fuzzy
+msgid "The system baseline power is estimated at: "
+msgstr "System baseline power is estimated at %sW\n"
+
+#: src/devices/device.cpp:277 src/process/do_process.cpp:850
+#: src/process/do_process.cpp:852 src/process/do_process.cpp:926
+#: src/process/do_process.cpp:1077
+msgid "Usage"
+msgstr ""
+
+#: src/devices/device.cpp:278
+#, fuzzy
+msgid "Device Name"
+msgstr "Device stats"
+
+#: src/devices/device.cpp:280 src/process/do_process.cpp:935
+#: src/process/do_process.cpp:1082
+msgid "PW Estimate"
+msgstr ""
+
+#: src/devices/device.cpp:317
+msgid "Device Power Report"
+msgstr ""
+
+#: src/devices/network.cpp:177
+#, c-format
+msgid "Network interface: %s (%s)"
+msgstr "Network interface: %s (%s)"
+
+#: src/devices/rfkill.cpp:65 src/devices/rfkill.cpp:69
+#, c-format
+msgid "Radio device: %s"
+msgstr "Radio device: %s"
+
+#: src/devices/runtime_pm.cpp:216
+#, c-format
+msgid "I2C %s (%s): %s"
+msgstr ""
+
+#: src/devices/runtime_pm.cpp:216 src/tuning/tuningi2c.cpp:57
+#: src/tuning/tuningi2c.cpp:59
+msgid "Adapter"
+msgstr ""
+
+#: src/devices/runtime_pm.cpp:216 src/devlist.cpp:331
+#: src/tuning/tuningi2c.cpp:57 src/tuning/tuningi2c.cpp:59
+#, fuzzy
+msgid "Device"
+msgstr "Device stats"
+
+#: src/devices/runtime_pm.cpp:241
+#, c-format
+msgid "PCI Device: %s"
+msgstr "PCI Device: %s"
+
+#: src/devices/usb.cpp:51 src/devices/usb.cpp:96 src/devices/usb.cpp:98
+#, c-format
+msgid "USB device: %s"
+msgstr "USB device: %s"
+
+#: src/devices/usb.cpp:94
+#, c-format
+msgid "USB device: %s (%s)"
+msgstr "USB device: %s (%s)"
+
+#: src/devlist.cpp:330
+msgid "Process"
+msgstr ""
+
+#: src/devlist.cpp:347
+msgid "Process Device Activity"
+msgstr ""
+
+#: src/display.cpp:70
+msgid "Overview"
+msgstr "Overview"
+
+#: src/display.cpp:71
+msgid "Idle stats"
+msgstr "Idle stats"
+
+#: src/display.cpp:72
+msgid "Frequency stats"
+msgstr "Frequency stats"
+
+#: src/display.cpp:73
+msgid "Device stats"
+msgstr "Device stats"
+
+#: src/display.cpp:131
+msgid "Exit"
+msgstr ""
+
+#: src/display.cpp:132
+msgid "Navigate"
+msgstr ""
+
+#: src/lib.cpp:288
+#, c-format
+msgid "%7sW"
+msgstr "%7sW"
+
+#: src/lib.cpp:291
+#, c-format
+msgid " 0 mW"
+msgstr " 0 mW"
+
+#: src/lib.cpp:410
+msgid "PS/2 Touchpad / Keyboard / Mouse"
+msgstr "PS/2 Touchpad / Keyboard / Mouse"
+
+#: src/lib.cpp:411
+msgid "SATA controller"
+msgstr "SATA controller"
+
+#: src/lib.cpp:412
+msgid "Intel built in USB hub"
+msgstr "Intel built in USB hub"
+
+#: src/lib.cpp:467
+#, c-format
+msgid "glob returned GLOB_NOSPACE\n"
+msgstr ""
+
+#: src/lib.cpp:471
+#, c-format
+msgid "glob returned GLOB_ABORTED\n"
+msgstr ""
+
+#: src/lib.cpp:475
+#, c-format
+msgid "glob returned GLOB_NOMATCH\n"
+msgstr ""
+
+#: src/lib.cpp:513 src/lib.cpp:549
+#, c-format
+msgid ""
+"Model-specific registers (MSR)\t\t\t not found (try enabling "
+"CONFIG_X86_MSR).\n"
+msgstr ""
+
+#: src/main.cpp:104
+#, fuzzy, c-format
+msgid "PowerTOP version "
+msgstr "PowerTOP "
+
+#: src/main.cpp:110
+msgid "Set refresh time out"
+msgstr ""
+
+#: src/main.cpp:123
+msgid "Usage: powertop [OPTIONS]"
+msgstr ""
+
+#: src/main.cpp:124
+msgid "sets all tunable options to their GOOD setting"
+msgstr ""
+
+#: src/main.cpp:125
+msgid "runs powertop in calibration mode"
+msgstr ""
+
+#: src/main.cpp:126 src/main.cpp:129
+msgid "[=filename]"
+msgstr ""
+
+#: src/main.cpp:126
+msgid "generate a csv report"
+msgstr ""
+
+#: src/main.cpp:127
+msgid "run in \"debug\" mode"
+msgstr ""
+
+#: src/main.cpp:128
+msgid "[=devnode]"
+msgstr ""
+
+#: src/main.cpp:128
+msgid "uses an Extech Power Analyzer for measurements"
+msgstr ""
+
+#: src/main.cpp:129
+msgid "generate a html report"
+msgstr ""
+
+#: src/main.cpp:130
+msgid "[=iterations] number of times to run each test"
+msgstr ""
+
+#: src/main.cpp:131
+msgid "suppress stderr output"
+msgstr ""
+
+#: src/main.cpp:132 src/main.cpp:133
+msgid "[=seconds]"
+msgstr ""
+
+#: src/main.cpp:132
+msgid "interval for power consumption measurement"
+msgstr ""
+
+#: src/main.cpp:133
+msgid "generate a report for 'x' seconds"
+msgstr ""
+
+#: src/main.cpp:134
+msgid "[=workload]"
+msgstr ""
+
+#: src/main.cpp:134
+msgid "file to execute for workload"
+msgstr ""
+
+#: src/main.cpp:135
+msgid "print version information"
+msgstr ""
+
+#: src/main.cpp:136
+msgid "print this help menu"
+msgstr ""
+
+#: src/main.cpp:138
+msgid "For more help please refer to the 'man 8 powertop'"
+msgstr ""
+
+#: src/main.cpp:233
+#, c-format
+msgid "Unknown issue running workload!\n"
+msgstr ""
+
+#: src/main.cpp:290
+msgid "PowerTOP is out of memory. PowerTOP is Aborting"
+msgstr ""
+
+#: src/main.cpp:298
+#, c-format
+msgid "Preparing to take measurements\n"
+msgstr ""
+
+#: src/main.cpp:303
+#, c-format
+msgid "Taking %d measurement(s) for a duration of %d second(s) each.\n"
+msgstr ""
+
+#: src/main.cpp:305
+#, c-format
+msgid "Measuring workload %s.\n"
+msgstr ""
+
+#: src/main.cpp:330
+#, c-format
+msgid "PowerTOP "
+msgstr "PowerTOP "
+
+#: src/main.cpp:331 src/main.cpp:381
+#, c-format
+msgid "exiting...\n"
+msgstr "exiting...\n"
+
+#: src/main.cpp:365
+#, c-format
+msgid "modprobe cpufreq_stats failed\n"
+msgstr ""
+
+#: src/main.cpp:368
+#, c-format
+msgid "modprobe msr failed\n"
+msgstr ""
+
+#: src/main.cpp:380 src/main.cpp:384
+#, c-format
+msgid "Failed to mount debugfs!\n"
+msgstr ""
+
+#: src/main.cpp:385
+#, c-format
+msgid "Should still be able to auto tune...\n"
+msgstr ""
+
+#: src/main.cpp:467
+#, c-format
+msgid "Invalid CSV filename\n"
+msgstr ""
+
+#: src/main.cpp:483
+#, c-format
+msgid "Invalid HTML filename\n"
+msgstr ""
+
+#: src/main.cpp:492
+#, c-format
+msgid "Quiet mode failed!\n"
+msgstr ""
+
+#: src/main.cpp:560
+msgid "Leaving PowerTOP"
+msgstr ""
+
+#: src/parameters/persistent.cpp:46 src/parameters/persistent.cpp:155
+msgid "Cannot save to file"
+msgstr ""
+
+#: src/parameters/persistent.cpp:89 src/parameters/persistent.cpp:180
+msgid "Cannot load from file"
+msgstr ""
+
+#: src/parameters/persistent.cpp:138
+#, c-format
+msgid "Loaded %i prior measurements\n"
+msgstr "Loaded %i prior measurements\n"
+
+#: src/parameters/persistent.cpp:181
+msgid ""
+"File will be loaded after taking minimum number of measurement(s) with "
+"battery only \n"
+msgstr ""
+
+#: src/perf/perf.cpp:115
+#, c-format
+msgid ""
+"Too many open files, please increase the limit of open file descriptors.\n"
+msgstr ""
+
+#: src/perf/perf.cpp:117
+#, c-format
+msgid "PowerTOP %s needs the kernel to support the 'perf' subsystem\n"
+msgstr "PowerTOP %s needs the kernel to support the 'perf' subsystem\n"
+
+#: src/perf/perf.cpp:118
+#, c-format
+msgid "as well as support for trace points in the kernel:\n"
+msgstr "as well as support for trace points in the kernel:\n"
+
+#: src/process/do_process.cpp:819
+#, c-format
+msgid ""
+"Estimated power: %5.1f Measured power: %5.1f Sum: %5.1f\n"
+"\n"
+msgstr ""
+"Estimated power: %5.1f Measured power: %5.1f Sum: %5.1f\n"
+"\n"
+
+#: src/process/do_process.cpp:838
+#, c-format
+msgid "The estimated remaining time is %i hours, %i minutes\n"
+msgstr ""
+
+#: src/process/do_process.cpp:846
+msgid "Summary"
+msgstr ""
+
+#: src/process/do_process.cpp:846
+msgid "wakeups/second"
+msgstr ""
+
+#: src/process/do_process.cpp:846
+msgid "GPU ops/seconds"
+msgstr ""
+
+#: src/process/do_process.cpp:846
+msgid "VFS ops/sec and"
+msgstr ""
+
+#: src/process/do_process.cpp:846
+msgid "CPU use"
+msgstr ""
+
+#: src/process/do_process.cpp:850
+msgid "Power est."
+msgstr ""
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:1078
+msgid "Events/s"
+msgstr ""
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:931 src/process/do_process.cpp:1079
+msgid "Category"
+msgstr ""
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:932 src/process/do_process.cpp:1080
+#: src/tuning/tuning.cpp:242 src/tuning/tuning.cpp:270
+#: src/tuning/tuning.cpp:295 src/wakeup/waketab.cpp:155
+msgid "Description"
+msgstr ""
+
+#: src/process/do_process.cpp:927
+msgid "Wakeups/s"
+msgstr ""
+
+#: src/process/do_process.cpp:928
+msgid "GPU ops/s"
+msgstr ""
+
+#: src/process/do_process.cpp:929
+msgid "Disk IO/s"
+msgstr ""
+
+#: src/process/do_process.cpp:930
+msgid "GFX Wakeups/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1017
+msgid "Overview of Software Power Consumers"
+msgstr ""
+
+#: src/process/do_process.cpp:1057
+msgid "Target:"
+msgstr ""
+
+#: src/process/do_process.cpp:1058
+msgid "1 units/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1059
+msgid "System: "
+msgstr ""
+
+#: src/process/do_process.cpp:1061
+msgid " wakeup/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1062
+msgid "CPU: "
+msgstr ""
+
+#: src/process/do_process.cpp:1064
+#, c-format
+msgid "% usage"
+msgstr ""
+
+#: src/process/do_process.cpp:1065
+msgid "GPU:"
+msgstr ""
+
+#: src/process/do_process.cpp:1067 src/process/do_process.cpp:1073
+msgid " ops/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1068
+msgid "GFX:"
+msgstr ""
+
+#: src/process/do_process.cpp:1070
+msgid " wakeups/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1071
+msgid "VFS:"
+msgstr ""
+
+#: src/process/do_process.cpp:1139
+msgid "Top 10 Power Consumers"
+msgstr ""
+
+#: src/report/report.cpp:122
+#, fuzzy
+msgid "PowerTOP Version"
+msgstr "PowerTOP "
+
+#: src/report/report.cpp:131
+msgid "Kernel Version"
+msgstr ""
+
+#: src/report/report.cpp:135
+msgid "System Name"
+msgstr ""
+
+#: src/report/report.cpp:142
+msgid "CPU Information"
+msgstr ""
+
+#: src/report/report.cpp:154
+msgid "OS Information"
+msgstr ""
+
+#: src/report/report.cpp:161
+msgid "System Information"
+msgstr ""
+
+#: src/report/report.cpp:195
+#, fuzzy, c-format
+msgid "Cannot open output file %s (%s)\n"
+msgstr "Cannot create temp file\n"
+
+#: src/report/report.cpp:211
+#, c-format
+msgid "PowerTOP outputting using base filename %s\n"
+msgstr ""
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:49
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45
+msgid "Good"
+msgstr "Good"
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:50
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45
+msgid "Bad"
+msgstr "Bad"
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:51
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45 src/wakeup/wakeup.cpp:50
+msgid "Unknown"
+msgstr "Unknown"
+
+#: src/tuning/bluetooth.cpp:48
+#, c-format
+msgid "Bluetooth device interface status"
+msgstr "Bluetooth device interface status"
+
+#: src/tuning/ethernet.cpp:54 src/wakeup/wakeup_ethernet.cpp:51
+#, c-format
+msgid "Wake-on-lan status for device %s"
+msgstr "Wake-on-lan status for device %s"
+
+#: src/tuning/runtime.cpp:48
+#, c-format
+msgid "Runtime PM for %s device %s"
+msgstr "Runtime PM for %s device %s"
+
+#: src/tuning/runtime.cpp:50
+#, c-format
+msgid "%s device %s has no runtime power management"
+msgstr "%s device %s has no runtime power management"
+
+#: src/tuning/runtime.cpp:74
+#, c-format
+msgid "PCI Device %s has no runtime power management"
+msgstr "PCI Device %s has no runtime power management"
+
+#: src/tuning/runtime.cpp:76
+#, c-format
+msgid "Runtime PM for PCI Device %s"
+msgstr "Runtime PM for PCI Device %s"
+
+#: src/tuning/runtime.cpp:80
+#, fuzzy, c-format
+msgid "Runtime PM for port %s of PCI device: %s"
+msgstr "Runtime PM for %s device %s"
+
+#: src/tuning/runtime.cpp:83
+#, fuzzy, c-format
+msgid "Runtime PM for disk %s"
+msgstr "Runtime PM for %s device %s"
+
+#: src/tuning/tuning.cpp:62
+msgid "Enable Audio codec power management"
+msgstr "Enable Audio codec power management"
+
+#: src/tuning/tuning.cpp:63
+msgid "NMI watchdog should be turned off"
+msgstr "NMI watchdog should be turned off"
+
+#: src/tuning/tuning.cpp:64
+msgid "Power Aware CPU scheduler"
+msgstr "Power Aware CPU scheduler"
+
+#: src/tuning/tuning.cpp:65
+msgid "VM writeback timeout"
+msgstr "VM writeback timeout"
+
+#: src/tuning/tuning.cpp:81
+msgid "Tunables"
+msgstr "Tunables"
+
+#: src/tuning/tuning.cpp:81
+msgid " <ESC> Exit | <Enter> Toggle tunable | <r> Window refresh"
+msgstr ""
+
+#: src/tuning/tuning.cpp:243 src/wakeup/waketab.cpp:156
+msgid "Script"
+msgstr ""
+
+#: src/tuning/tuning.cpp:257
+msgid "Software Settings in Need of Tuning"
+msgstr ""
+
+#: src/tuning/tuning.cpp:276
+msgid "Untunable Software Issues"
+msgstr ""
+
+#: src/tuning/tuning.cpp:307
+msgid "Optimal Tuned Software Settings"
+msgstr ""
+
+#: src/tuning/tuningi2c.cpp:57
+#, fuzzy, c-format
+msgid "Runtime PM for I2C %s %s (%s)"
+msgstr "Runtime PM for %s device %s"
+
+#: src/tuning/tuningi2c.cpp:59
+#, fuzzy, c-format
+msgid "I2C %s %s has no runtime power management"
+msgstr "%s device %s has no runtime power management"
+
+#: src/tuning/tuningsysfs.cpp:123
+#, fuzzy, c-format
+msgid "Enable SATA link power management for %s"
+msgstr "Enable Audio codec power management"
+
+#: src/tuning/tuningusb.cpp:54
+#, c-format
+msgid "Autosuspend for unknown USB device %s (%s:%s)"
+msgstr "Autosuspend for unknown USB device %s (%s:%s)"
+
+#: src/tuning/tuningusb.cpp:71 src/tuning/tuningusb.cpp:73
+#: src/tuning/tuningusb.cpp:75
+#, c-format
+msgid "Autosuspend for USB device %s [%s]"
+msgstr "Autosuspend for USB device %s [%s]"
+
+#: src/tuning/wifi.cpp:48
+#, c-format
+msgid "Wireless Power Saving for interface %s"
+msgstr "Wireless Power Saving for interface %s"
+
+#: src/wakeup/waketab.cpp:42
+msgid "WakeUp"
+msgstr ""
+
+#: src/wakeup/waketab.cpp:42
+msgid " <ESC> Exit | <Enter> Toggle wakeup | <r> Window refresh"
+msgstr ""
+
+#: src/wakeup/waketab.cpp:170
+#, fuzzy
+msgid "Wake status of the devices"
+msgstr "Wake-on-lan status for device %s"
+
+#: src/wakeup/wakeup.cpp:48 src/wakeup/wakeup_ethernet.cpp:47
+#: src/wakeup/wakeup_usb.cpp:47
+#, fuzzy
+msgid "Enabled"
+msgstr "Tunables"
+
+#: src/wakeup/wakeup.cpp:49 src/wakeup/wakeup_ethernet.cpp:47
+#: src/wakeup/wakeup_usb.cpp:47
+msgid "Disabled"
+msgstr ""
+
+#: src/wakeup/wakeup_usb.cpp:51
+#, fuzzy, c-format
+msgid "Wake status for USB device %s"
+msgstr "Wake-on-lan status for device %s"
+
+#~ msgid "Actual"
+#~ msgstr "Actual"
+
+#, fuzzy
+#~ msgid "I2C Device: %s"
+#~ msgstr "PCI Device: %s"
+
+#~ msgid "Using 'ondemand' cpufreq governor"
+#~ msgstr "Using 'ondemand' cpufreq governor"
diff --git a/po/es_CO.po b/po/es_CO.po
new file mode 100644
index 0000000..84eb433
--- /dev/null
+++ b/po/es_CO.po
@@ -0,0 +1,951 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Intel Corporation
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: PowerTOP\n"
+"Report-Msgid-Bugs-To: powertop@lists.01.org\n"
+"POT-Creation-Date: 2019-01-04 13:55-0800\n"
+"PO-Revision-Date: 2013-11-05 08:40+0000\n"
+"Last-Translator: Margie Foster <margie@linux.intel.com>\n"
+"Language-Team: Spanish (Colombia) (http://www.transifex.com/projects/p/"
+"PowerTOP/language/es_CO/)\n"
+"Language: es_CO\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ../src/calibrate/calibrate.cpp:238
+#, c-format
+msgid "Cannot create temp file\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:258
+#, c-format
+msgid "Calibrating: CPU usage on %i threads\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:273
+#, c-format
+msgid "Calibrating: CPU wakeup power consumption\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:290
+#, c-format
+msgid "Calibrating USB devices\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:292 ../src/calibrate/calibrate.cpp:309
+#: ../src/calibrate/calibrate.cpp:317 ../src/calibrate/calibrate.cpp:334
+#, c-format
+msgid ".... device %s \n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:307
+#, c-format
+msgid "Calibrating radio devices\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:331
+#, c-format
+msgid "Calibrating backlight\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:355 ../src/calibrate/calibrate.cpp:365
+#, c-format
+msgid "Calibrating idle\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:378
+#, c-format
+msgid "Calibrating: disk usage \n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:403
+msgid "Starting PowerTOP power estimate calibration \n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:426
+msgid "Finishing PowerTOP power estimate calibration \n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:430
+#, c-format
+msgid "Parameters after calibration:\n"
+msgstr ""
+
+#: ../src/cpu/abstract_cpu.cpp:74
+msgid "Idle"
+msgstr ""
+
+#: ../src/cpu/abstract_cpu.cpp:76
+msgid "Turbo Mode"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(HW)"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(OS)"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:91 ../src/cpu/intel_cpus.cpp:324
+#, c-format
+msgid " Core"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:85
+#, c-format
+msgid "cpu package %i"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:86
+msgid "cpu package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:89 ../src/cpu/cpu.cpp:96
+#, c-format
+msgid "package-%i"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:90
+msgid "cpu rapl package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:97
+msgid "dram rapl package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:471
+msgid "Processor Idle State Report"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:535 ../src/cpu/cpu.cpp:753
+msgid "Package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:566 ../src/cpu/cpu.cpp:775
+#, c-format
+msgid "Core %d"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:573
+#, c-format
+msgid "GPU %d"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:594
+msgid "CPU"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:676
+msgid "Processor Frequency Report"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:796
+#, c-format
+msgid "CPU %d"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:997
+#, c-format
+msgid "cpu_idle event returned no state?\n"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:1012
+#, c-format
+msgid "power or cpu_frequency event returned no state?\n"
+msgstr ""
+
+#: ../src/cpu/cpu_linux.cpp:79
+msgid "C0 polling"
+msgstr ""
+
+#: ../src/cpu/cpu_linux.cpp:242
+#, c-format
+msgid " CPU(OS) %i"
+msgstr ""
+
+#: ../src/cpu/cpu_linux.cpp:341 ../src/cpu/intel_cpus.cpp:651
+#, c-format
+msgid " CPU %i"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(HW)"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(OS)"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:104 ../src/cpu/intel_cpus.cpp:412
+#, c-format
+msgid " Package"
+msgstr ""
+
+#: ../src/cpu/intel_cpus.cpp:129
+#, c-format
+msgid "read_msr cpu%d 0x%llx : "
+msgstr ""
+
+#: ../src/cpu/intel_cpus.cpp:574
+msgid "C0 active"
+msgstr ""
+
+#: ../src/cpu/intel_cpus.cpp:632
+#, c-format
+msgid "Average"
+msgstr ""
+
+#: ../src/cpu/intel_gpu.cpp:64
+#, c-format
+msgid " GPU "
+msgstr ""
+
+#: ../src/devices/ahci.cpp:154
+#, c-format
+msgid "SATA link: %s"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:156
+#, c-format
+msgid "SATA disk: %s"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:374
+msgid "AHCI ALPM Residency Statistics - Not supported on this macine"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:389
+msgid "Link"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:390
+msgid "Active"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:391
+msgid "Partial"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:392
+msgid "Slumber"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:393
+msgid "Devslp"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:399
+msgid "AHCI ALPM Residency Statistics"
+msgstr ""
+
+#: ../src/devices/alsa.cpp:77
+#, c-format
+msgid "Audio codec %s: %s (%s)"
+msgstr ""
+
+#: ../src/devices/alsa.cpp:79 ../src/devices/alsa.cpp:81
+#, c-format
+msgid "Audio codec %s: %s"
+msgstr ""
+
+#: ../src/devices/devfreq.cpp:261
+msgid "Device Freq stats"
+msgstr ""
+
+#: ../src/devices/devfreq.cpp:279
+msgid " Devfreq is not enabled"
+msgstr ""
+
+#: ../src/devices/devfreq.cpp:284
+msgid " No devfreq devices available"
+msgstr ""
+
+#: ../src/devices/device.cpp:172 ../src/process/do_process.cpp:831
+#, c-format
+msgid "The battery reports a discharge rate of %sW\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:174 ../src/process/do_process.cpp:833
+#, c-format
+msgid "The power consumed was %sJ\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:180
+#, c-format
+msgid "System baseline power is estimated at %sW\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:187
+msgid "Power est. Usage Device name\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:189
+msgid " Usage Device name\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:256
+msgid "The battery reports a discharge rate of: "
+msgstr ""
+
+#: ../src/devices/device.cpp:261
+msgid "The power consumed was : "
+msgstr ""
+
+#: ../src/devices/device.cpp:268
+msgid "The system baseline power is estimated at: "
+msgstr ""
+
+#: ../src/devices/device.cpp:277 ../src/process/do_process.cpp:850
+#: ../src/process/do_process.cpp:852 ../src/process/do_process.cpp:926
+#: ../src/process/do_process.cpp:1077
+msgid "Usage"
+msgstr ""
+
+#: ../src/devices/device.cpp:278
+msgid "Device Name"
+msgstr ""
+
+#: ../src/devices/device.cpp:280 ../src/process/do_process.cpp:935
+#: ../src/process/do_process.cpp:1082
+msgid "PW Estimate"
+msgstr ""
+
+#. Report Output
+#: ../src/devices/device.cpp:317
+msgid "Device Power Report"
+msgstr ""
+
+#: ../src/devices/network.cpp:177
+#, c-format
+msgid "Network interface: %s (%s)"
+msgstr ""
+
+#: ../src/devices/rfkill.cpp:65 ../src/devices/rfkill.cpp:69
+#, c-format
+msgid "Radio device: %s"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216
+#, c-format
+msgid "I2C %s (%s): %s"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216 ../src/tuning/tuningi2c.cpp:57
+#: ../src/tuning/tuningi2c.cpp:59
+msgid "Adapter"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216 ../src/devlist.cpp:331
+#: ../src/tuning/tuningi2c.cpp:57 ../src/tuning/tuningi2c.cpp:59
+msgid "Device"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:241
+#, c-format
+msgid "PCI Device: %s"
+msgstr ""
+
+#: ../src/devices/usb.cpp:51 ../src/devices/usb.cpp:96
+#: ../src/devices/usb.cpp:98
+#, c-format
+msgid "USB device: %s"
+msgstr ""
+
+#: ../src/devices/usb.cpp:94
+#, c-format
+msgid "USB device: %s (%s)"
+msgstr ""
+
+#: ../src/devlist.cpp:330
+msgid "Process"
+msgstr ""
+
+#. Report Output
+#. No div attribute here inherits from device power report
+#: ../src/devlist.cpp:347
+msgid "Process Device Activity"
+msgstr ""
+
+#: ../src/display.cpp:70
+msgid "Overview"
+msgstr ""
+
+#: ../src/display.cpp:71
+msgid "Idle stats"
+msgstr ""
+
+#: ../src/display.cpp:72
+msgid "Frequency stats"
+msgstr ""
+
+#: ../src/display.cpp:73
+msgid "Device stats"
+msgstr ""
+
+#: ../src/display.cpp:131
+msgid "Exit"
+msgstr ""
+
+#: ../src/display.cpp:132
+msgid "Navigate"
+msgstr ""
+
+#: ../src/lib.cpp:288
+#, c-format
+msgid "%7sW"
+msgstr ""
+
+#: ../src/lib.cpp:291
+#, c-format
+msgid " 0 mW"
+msgstr ""
+
+#: ../src/lib.cpp:410
+msgid "PS/2 Touchpad / Keyboard / Mouse"
+msgstr ""
+
+#: ../src/lib.cpp:411
+msgid "SATA controller"
+msgstr ""
+
+#: ../src/lib.cpp:412
+msgid "Intel built in USB hub"
+msgstr ""
+
+#: ../src/lib.cpp:467
+#, c-format
+msgid "glob returned GLOB_NOSPACE\n"
+msgstr ""
+
+#: ../src/lib.cpp:471
+#, c-format
+msgid "glob returned GLOB_ABORTED\n"
+msgstr ""
+
+#: ../src/lib.cpp:475
+#, c-format
+msgid "glob returned GLOB_NOMATCH\n"
+msgstr ""
+
+#: ../src/lib.cpp:513 ../src/lib.cpp:549
+#, c-format
+msgid ""
+"Model-specific registers (MSR)\t\t\t not found (try enabling "
+"CONFIG_X86_MSR).\n"
+msgstr ""
+
+#: ../src/main.cpp:103
+#, c-format
+msgid "PowerTOP version "
+msgstr ""
+
+#: ../src/main.cpp:109
+msgid "Set refresh time out"
+msgstr ""
+
+#: ../src/main.cpp:122
+msgid "Usage: powertop [OPTIONS]"
+msgstr ""
+
+#: ../src/main.cpp:123
+msgid "sets all tunable options to their GOOD setting"
+msgstr ""
+
+#: ../src/main.cpp:124
+msgid "runs powertop in calibration mode"
+msgstr ""
+
+#: ../src/main.cpp:125 ../src/main.cpp:128
+msgid "[=filename]"
+msgstr ""
+
+#: ../src/main.cpp:125
+msgid "generate a csv report"
+msgstr ""
+
+#: ../src/main.cpp:126
+msgid "run in \"debug\" mode"
+msgstr ""
+
+#: ../src/main.cpp:127
+msgid "[=devnode]"
+msgstr ""
+
+#: ../src/main.cpp:127
+msgid "uses an Extech Power Analyzer for measurements"
+msgstr ""
+
+#: ../src/main.cpp:128
+msgid "generate a html report"
+msgstr ""
+
+#: ../src/main.cpp:129
+msgid "[=iterations] number of times to run each test"
+msgstr ""
+
+#: ../src/main.cpp:130
+msgid "suppress stderr output"
+msgstr ""
+
+#: ../src/main.cpp:131 ../src/main.cpp:132
+msgid "[=seconds]"
+msgstr ""
+
+#: ../src/main.cpp:131
+msgid "interval for power consumption measurement"
+msgstr ""
+
+#: ../src/main.cpp:132
+msgid "generate a report for 'x' seconds"
+msgstr ""
+
+#: ../src/main.cpp:133
+msgid "[=workload]"
+msgstr ""
+
+#: ../src/main.cpp:133
+msgid "file to execute for workload"
+msgstr ""
+
+#: ../src/main.cpp:134
+msgid "print version information"
+msgstr ""
+
+#: ../src/main.cpp:135
+msgid "print this help menu"
+msgstr ""
+
+#: ../src/main.cpp:137
+msgid "For more help please refer to the 'man 8 powertop'"
+msgstr ""
+
+#: ../src/main.cpp:232
+#, c-format
+msgid "Unknown issue running workload!\n"
+msgstr ""
+
+#: ../src/main.cpp:289
+msgid "PowerTOP is out of memory. PowerTOP is Aborting"
+msgstr ""
+
+#. one to warm up everything
+#: ../src/main.cpp:297
+#, c-format
+msgid "Preparing to take measurements\n"
+msgstr ""
+
+#: ../src/main.cpp:302
+#, c-format
+msgid "Taking %d measurement(s) for a duration of %d second(s) each.\n"
+msgstr ""
+
+#: ../src/main.cpp:304
+#, c-format
+msgid "Measuring workload %s.\n"
+msgstr ""
+
+#: ../src/main.cpp:329
+#, c-format
+msgid "PowerTOP "
+msgstr ""
+
+#: ../src/main.cpp:330 ../src/main.cpp:380
+#, c-format
+msgid "exiting...\n"
+msgstr ""
+
+#: ../src/main.cpp:364
+#, c-format
+msgid "modprobe cpufreq_stats failed"
+msgstr ""
+
+#: ../src/main.cpp:367
+#, c-format
+msgid "modprobe msr failed"
+msgstr ""
+
+#: ../src/main.cpp:379 ../src/main.cpp:383
+#, c-format
+msgid "Failed to mount debugfs!\n"
+msgstr ""
+
+#: ../src/main.cpp:384
+#, c-format
+msgid "Should still be able to auto tune...\n"
+msgstr ""
+
+#: ../src/main.cpp:466
+#, c-format
+msgid "Invalid CSV filename\n"
+msgstr ""
+
+#: ../src/main.cpp:482
+#, c-format
+msgid "Invalid HTML filename\n"
+msgstr ""
+
+#: ../src/main.cpp:491
+#, c-format
+msgid "Quiet mode failed!\n"
+msgstr ""
+
+#: ../src/main.cpp:559
+msgid "Leaving PowerTOP"
+msgstr ""
+
+#: ../src/parameters/persistent.cpp:46 ../src/parameters/persistent.cpp:155
+msgid "Cannot save to file"
+msgstr ""
+
+#: ../src/parameters/persistent.cpp:89 ../src/parameters/persistent.cpp:180
+msgid "Cannot load from file"
+msgstr ""
+
+#. '%i" is for count, do not translate
+#: ../src/parameters/persistent.cpp:138
+#, c-format
+msgid "Loaded %i prior measurements\n"
+msgstr ""
+
+#: ../src/parameters/persistent.cpp:181
+msgid ""
+"File will be loaded after taking minimum number of measurement(s) with "
+"battery only \n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:115
+#, c-format
+msgid ""
+"Too many open files, please increase the limit of open file descriptors.\n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:117
+#, c-format
+msgid "PowerTOP %s needs the kernel to support the 'perf' subsystem\n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:118
+#, c-format
+msgid "as well as support for trace points in the kernel:\n"
+msgstr ""
+
+#: ../src/process/do_process.cpp:819
+#, c-format
+msgid ""
+"Estimated power: %5.1f Measured power: %5.1f Sum: %5.1f\n"
+"\n"
+msgstr ""
+
+#: ../src/process/do_process.cpp:838
+#, c-format
+msgid "The estimated remaining time is %i hours, %i minutes\n"
+msgstr ""
+
+#: ../src/process/do_process.cpp:846
+msgid "Summary"
+msgstr ""
+
+#: ../src/process/do_process.cpp:846
+msgid "wakeups/second"
+msgstr ""
+
+#: ../src/process/do_process.cpp:846
+msgid "GPU ops/seconds"
+msgstr ""
+
+#: ../src/process/do_process.cpp:846
+msgid "VFS ops/sec and"
+msgstr ""
+
+#: ../src/process/do_process.cpp:846
+msgid "CPU use"
+msgstr ""
+
+#: ../src/process/do_process.cpp:850
+msgid "Power est."
+msgstr ""
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:1078
+msgid "Events/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:931 ../src/process/do_process.cpp:1079
+msgid "Category"
+msgstr ""
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:932 ../src/process/do_process.cpp:1080
+#: ../src/tuning/tuning.cpp:242 ../src/tuning/tuning.cpp:270
+#: ../src/tuning/tuning.cpp:288 ../src/wakeup/waketab.cpp:155
+msgid "Description"
+msgstr ""
+
+#: ../src/process/do_process.cpp:927
+msgid "Wakeups/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:928
+msgid "GPU ops/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:929
+msgid "Disk IO/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:930
+msgid "GFX Wakeups/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1017
+msgid "Overview of Software Power Consumers"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1057
+msgid "Target:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1058
+msgid "1 units/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1059
+msgid "System: "
+msgstr ""
+
+#: ../src/process/do_process.cpp:1061
+msgid " wakeup/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1062
+msgid "CPU: "
+msgstr ""
+
+#: ../src/process/do_process.cpp:1064
+#, c-format
+msgid "% usage"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1065
+msgid "GPU:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1067 ../src/process/do_process.cpp:1073
+msgid " ops/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1068
+msgid "GFX:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1070
+msgid " wakeups/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1071
+msgid "VFS:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1139
+msgid "Top 10 Power Consumers"
+msgstr ""
+
+#: ../src/report/report.cpp:122
+msgid "PowerTOP Version"
+msgstr ""
+
+#: ../src/report/report.cpp:131
+msgid "Kernel Version"
+msgstr ""
+
+#: ../src/report/report.cpp:135
+msgid "System Name"
+msgstr ""
+
+#: ../src/report/report.cpp:142
+msgid "CPU Information"
+msgstr ""
+
+#: ../src/report/report.cpp:154
+msgid "OS Information"
+msgstr ""
+
+#: ../src/report/report.cpp:161
+msgid "System Information"
+msgstr ""
+
+#: ../src/report/report.cpp:195
+#, c-format
+msgid "Cannot open output file %s (%s)\n"
+msgstr ""
+
+#: ../src/report/report.cpp:211
+#, c-format
+msgid "PowerTOP outputing using base filename %s\n"
+msgstr ""
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:49
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+msgid "Good"
+msgstr ""
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:50
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+msgid "Bad"
+msgstr ""
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:51
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+#: ../src/wakeup/wakeup.cpp:50
+msgid "Unknown"
+msgstr ""
+
+#: ../src/tuning/bluetooth.cpp:48
+#, c-format
+msgid "Bluetooth device interface status"
+msgstr ""
+
+#: ../src/tuning/ethernet.cpp:54 ../src/wakeup/wakeup_ethernet.cpp:51
+#, c-format
+msgid "Wake-on-lan status for device %s"
+msgstr ""
+
+#: ../src/tuning/runtime.cpp:48
+#, c-format
+msgid "Runtime PM for %s device %s"
+msgstr ""
+
+#: ../src/tuning/runtime.cpp:50
+#, c-format
+msgid "%s device %s has no runtime power management"
+msgstr ""
+
+#: ../src/tuning/runtime.cpp:74
+#, c-format
+msgid "PCI Device %s has no runtime power management"
+msgstr ""
+
+#: ../src/tuning/runtime.cpp:76
+#, c-format
+msgid "Runtime PM for PCI Device %s"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:62
+msgid "Enable Audio codec power management"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:63
+msgid "NMI watchdog should be turned off"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:64
+msgid "Power Aware CPU scheduler"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:65
+msgid "VM writeback timeout"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:81
+msgid "Tunables"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:81
+msgid " <ESC> Exit | <Enter> Toggle tunable | <r> Window refresh"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:243 ../src/wakeup/waketab.cpp:156
+msgid "Script"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:257
+msgid "Software Settings in Need of Tuning"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:276
+msgid "Untunable Software Issues"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:300
+msgid "Optimal Tuned Software Settings"
+msgstr ""
+
+#: ../src/tuning/tuningi2c.cpp:57
+#, c-format
+msgid "Runtime PM for I2C %s %s (%s)"
+msgstr ""
+
+#: ../src/tuning/tuningi2c.cpp:59
+#, c-format
+msgid "I2C %s %s has no runtime power management"
+msgstr ""
+
+#: ../src/tuning/tuningsysfs.cpp:123
+#, c-format
+msgid "Enable SATA link power management for %s"
+msgstr ""
+
+#: ../src/tuning/tuningusb.cpp:54
+#, c-format
+msgid "Autosuspend for unknown USB device %s (%s:%s)"
+msgstr ""
+
+#: ../src/tuning/tuningusb.cpp:71 ../src/tuning/tuningusb.cpp:73
+#: ../src/tuning/tuningusb.cpp:75
+#, c-format
+msgid "Autosuspend for USB device %s [%s]"
+msgstr ""
+
+#: ../src/tuning/wifi.cpp:48
+#, c-format
+msgid "Wireless Power Saving for interface %s"
+msgstr ""
+
+#: ../src/wakeup/waketab.cpp:42
+msgid "WakeUp"
+msgstr ""
+
+#: ../src/wakeup/waketab.cpp:42
+msgid " <ESC> Exit | <Enter> Toggle wakeup | <r> Window refresh"
+msgstr ""
+
+#. Report Output
+#: ../src/wakeup/waketab.cpp:170
+msgid "Wake status of the devices"
+msgstr ""
+
+#: ../src/wakeup/wakeup.cpp:48 ../src/wakeup/wakeup_ethernet.cpp:47
+#: ../src/wakeup/wakeup_usb.cpp:47
+msgid "Enable"
+msgstr ""
+
+#: ../src/wakeup/wakeup.cpp:49 ../src/wakeup/wakeup_ethernet.cpp:47
+#: ../src/wakeup/wakeup_usb.cpp:47
+msgid "Disable"
+msgstr ""
+
+#: ../src/wakeup/wakeup_usb.cpp:51
+#, c-format
+msgid "Wake status for USB device %s"
+msgstr ""
diff --git a/po/es_ES.po b/po/es_ES.po
new file mode 100644
index 0000000..8693c9a
--- /dev/null
+++ b/po/es_ES.po
@@ -0,0 +1,980 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Intel Corporation
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Andres <andreshko9@hotmail.com>, 2011
+# Patrick McCarty <patrick.mccarty@linux.intel.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: PowerTOP\n"
+"Report-Msgid-Bugs-To: \"powertop@lists.01.org\"\n"
+"POT-Creation-Date: 2022-09-29 04:45-0700\n"
+"PO-Revision-Date: 2013-11-05 08:40+0000\n"
+"Last-Translator: Margie Foster <margie@linux.intel.com>\n"
+"Language-Team: Spanish (Spain) (http://www.transifex.com/projects/p/PowerTOP/"
+"language/es_ES/)\n"
+"Language: es_ES\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/calibrate/calibrate.cpp:238
+#, c-format
+msgid "Cannot create temp file\n"
+msgstr "No puede crear archivo temp\n"
+
+#: src/calibrate/calibrate.cpp:258
+#, c-format
+msgid "Calibrating: CPU usage on %i threads\n"
+msgstr "Calibrando: uso de CPU en %i discusiones\n"
+
+#: src/calibrate/calibrate.cpp:273
+#, c-format
+msgid "Calibrating: CPU wakeup power consumption\n"
+msgstr "Calibrando: consumo de energía del despertado de la CPU\n"
+
+#: src/calibrate/calibrate.cpp:290
+#, c-format
+msgid "Calibrating USB devices\n"
+msgstr "Calibrando dispositivos USB\n"
+
+#: src/calibrate/calibrate.cpp:292 src/calibrate/calibrate.cpp:309
+#: src/calibrate/calibrate.cpp:317 src/calibrate/calibrate.cpp:334
+#, c-format
+msgid ".... device %s \n"
+msgstr ".... dispositivo %s \n"
+
+#: src/calibrate/calibrate.cpp:307
+#, c-format
+msgid "Calibrating radio devices\n"
+msgstr "Calibrando dispositivos de radio\n"
+
+#: src/calibrate/calibrate.cpp:331
+#, c-format
+msgid "Calibrating backlight\n"
+msgstr "Calibrando luz trasera\n"
+
+#: src/calibrate/calibrate.cpp:355 src/calibrate/calibrate.cpp:365
+#, c-format
+msgid "Calibrating idle\n"
+msgstr "Calibrando parado\n"
+
+#: src/calibrate/calibrate.cpp:378
+#, c-format
+msgid "Calibrating: disk usage \n"
+msgstr "Calibrando: uso de disco \n"
+
+#: src/calibrate/calibrate.cpp:403
+msgid "Starting PowerTOP power estimate calibration \n"
+msgstr "Iniciando calibración de estimado de energía PowerTOP \n"
+
+#: src/calibrate/calibrate.cpp:426
+msgid "Finishing PowerTOP power estimate calibration \n"
+msgstr "Finalizando calibración de estimación de energía de PowerTOP \n"
+
+#: src/calibrate/calibrate.cpp:430
+#, c-format
+msgid "Parameters after calibration:\n"
+msgstr "Parámetros tras calibración:\n"
+
+#: src/cpu/abstract_cpu.cpp:74
+msgid "Idle"
+msgstr ""
+
+#: src/cpu/abstract_cpu.cpp:76
+msgid "Turbo Mode"
+msgstr ""
+
+#: src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(HW)"
+msgstr ""
+
+#: src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(OS)"
+msgstr ""
+
+#: src/cpu/cpu_core.cpp:91 src/cpu/intel_cpus.cpp:367
+#, c-format
+msgid " Core"
+msgstr ""
+
+#: src/cpu/cpu.cpp:85
+#, c-format
+msgid "cpu package %i"
+msgstr "package cpu %i"
+
+#: src/cpu/cpu.cpp:86
+msgid "cpu package"
+msgstr "paquete cpu"
+
+#: src/cpu/cpu.cpp:89 src/cpu/cpu.cpp:96
+#, fuzzy, c-format
+msgid "package-%i"
+msgstr "package cpu %i"
+
+#: src/cpu/cpu.cpp:90
+msgid "cpu rapl package"
+msgstr ""
+
+#: src/cpu/cpu.cpp:97
+msgid "dram rapl package"
+msgstr ""
+
+#: src/cpu/cpu.cpp:471
+msgid "Processor Idle State Report"
+msgstr ""
+
+#: src/cpu/cpu.cpp:535 src/cpu/cpu.cpp:761
+msgid "Package"
+msgstr ""
+
+#: src/cpu/cpu.cpp:572 src/cpu/cpu.cpp:783
+#, c-format
+msgid "Core %d"
+msgstr ""
+
+#: src/cpu/cpu.cpp:579
+#, fuzzy, c-format
+msgid "GPU %d"
+msgstr " CPU %i"
+
+#: src/cpu/cpu.cpp:602
+#, fuzzy
+msgid "CPU"
+msgstr " CPU %i"
+
+#: src/cpu/cpu.cpp:684
+msgid "Processor Frequency Report"
+msgstr ""
+
+#: src/cpu/cpu.cpp:804
+#, fuzzy, c-format
+msgid "CPU %d"
+msgstr " CPU %i"
+
+#: src/cpu/cpu.cpp:1005
+#, c-format
+msgid "cpu_idle event returned no state?\n"
+msgstr ""
+
+#: src/cpu/cpu.cpp:1020
+#, c-format
+msgid "power or cpu_frequency event returned no state?\n"
+msgstr ""
+
+#: src/cpu/cpu_linux.cpp:79
+msgid "C0 polling"
+msgstr "C0 sondeando"
+
+#: src/cpu/cpu_linux.cpp:242
+#, c-format
+msgid " CPU(OS) %i"
+msgstr ""
+
+#: src/cpu/cpu_linux.cpp:341 src/cpu/intel_cpus.cpp:733
+#, c-format
+msgid " CPU %i"
+msgstr ""
+
+#: src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(HW)"
+msgstr ""
+
+#: src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(OS)"
+msgstr ""
+
+#: src/cpu/cpu_package.cpp:104 src/cpu/intel_cpus.cpp:498
+#, c-format
+msgid " Package"
+msgstr ""
+
+#: src/cpu/intel_cpus.cpp:152
+#, c-format
+msgid "read_msr cpu%d 0x%llx : "
+msgstr ""
+
+#: src/cpu/intel_cpus.cpp:656
+msgid "C0 active"
+msgstr "C0 activo"
+
+#: src/cpu/intel_cpus.cpp:714
+#, c-format
+msgid "Average"
+msgstr ""
+
+#: src/cpu/intel_gpu.cpp:64
+#, fuzzy, c-format
+msgid " GPU "
+msgstr " CPU %i"
+
+#: src/devices/ahci.cpp:154
+#, c-format
+msgid "SATA link: %s"
+msgstr "Enlace SATA: %s"
+
+#: src/devices/ahci.cpp:156
+#, c-format
+msgid "SATA disk: %s"
+msgstr "Disco SATA: %s"
+
+#: src/devices/ahci.cpp:374
+msgid "AHCI ALPM Residency Statistics - Not supported on this macine"
+msgstr ""
+
+#: src/devices/ahci.cpp:389
+msgid "Link"
+msgstr ""
+
+#: src/devices/ahci.cpp:390
+#, fuzzy
+msgid "Active"
+msgstr "C0 activo"
+
+#: src/devices/ahci.cpp:391
+msgid "Partial"
+msgstr ""
+
+#: src/devices/ahci.cpp:392
+msgid "Slumber"
+msgstr ""
+
+#: src/devices/ahci.cpp:393
+msgid "Devslp"
+msgstr ""
+
+#: src/devices/ahci.cpp:399
+msgid "AHCI ALPM Residency Statistics"
+msgstr ""
+
+#: src/devices/alsa.cpp:77
+#, c-format
+msgid "Audio codec %s: %s (%s)"
+msgstr "Codec de audio %s: %s (%s)"
+
+#: src/devices/alsa.cpp:79 src/devices/alsa.cpp:81
+#, c-format
+msgid "Audio codec %s: %s"
+msgstr "Codec de audio %s: %s"
+
+#: src/devices/devfreq.cpp:260
+#, fuzzy
+msgid "Device Freq stats"
+msgstr "Estadísticas del dispositivo"
+
+#: src/devices/devfreq.cpp:278
+msgid " Devfreq is not enabled"
+msgstr ""
+
+#: src/devices/devfreq.cpp:283
+msgid " No devfreq devices available"
+msgstr ""
+
+#: src/devices/device.cpp:172 src/process/do_process.cpp:831
+#, c-format
+msgid "The battery reports a discharge rate of %sW\n"
+msgstr "La batería reporta una tasa de descarga de %sW\n"
+
+#: src/devices/device.cpp:174 src/process/do_process.cpp:833
+#, c-format
+msgid "The energy consumed was %sJ\n"
+msgstr ""
+
+#: src/devices/device.cpp:180
+#, c-format
+msgid "System baseline power is estimated at %sW\n"
+msgstr "Linea base de energía del sistema es estimada en %sW\n"
+
+#: src/devices/device.cpp:187
+msgid "Power est. Usage Device name\n"
+msgstr "Power est. Usage Device name\n"
+
+#: src/devices/device.cpp:189
+msgid " Usage Device name\n"
+msgstr " Uso Nombre del dispositivo\n"
+
+#: src/devices/device.cpp:256
+#, fuzzy
+msgid "The battery reports a discharge rate of: "
+msgstr "La batería reporta una tasa de descarga de %sW\n"
+
+#: src/devices/device.cpp:261
+msgid "The energy consumed was : "
+msgstr ""
+
+#: src/devices/device.cpp:268
+#, fuzzy
+msgid "The system baseline power is estimated at: "
+msgstr "Linea base de energía del sistema es estimada en %sW\n"
+
+#: src/devices/device.cpp:277 src/process/do_process.cpp:850
+#: src/process/do_process.cpp:852 src/process/do_process.cpp:926
+#: src/process/do_process.cpp:1077
+msgid "Usage"
+msgstr ""
+
+#: src/devices/device.cpp:278
+#, fuzzy
+msgid "Device Name"
+msgstr "Estadísticas del dispositivo"
+
+#: src/devices/device.cpp:280 src/process/do_process.cpp:935
+#: src/process/do_process.cpp:1082
+msgid "PW Estimate"
+msgstr ""
+
+#: src/devices/device.cpp:317
+msgid "Device Power Report"
+msgstr ""
+
+#: src/devices/network.cpp:177
+#, c-format
+msgid "Network interface: %s (%s)"
+msgstr "Interfaz de red: %s (%s)"
+
+#: src/devices/rfkill.cpp:65 src/devices/rfkill.cpp:69
+#, c-format
+msgid "Radio device: %s"
+msgstr "Dispositivo de radio: %s"
+
+#: src/devices/runtime_pm.cpp:216
+#, c-format
+msgid "I2C %s (%s): %s"
+msgstr ""
+
+#: src/devices/runtime_pm.cpp:216 src/tuning/tuningi2c.cpp:57
+#: src/tuning/tuningi2c.cpp:59
+msgid "Adapter"
+msgstr ""
+
+#: src/devices/runtime_pm.cpp:216 src/devlist.cpp:331
+#: src/tuning/tuningi2c.cpp:57 src/tuning/tuningi2c.cpp:59
+#, fuzzy
+msgid "Device"
+msgstr "Estadísticas del dispositivo"
+
+#: src/devices/runtime_pm.cpp:241
+#, c-format
+msgid "PCI Device: %s"
+msgstr "Dispositivo PCI: %s"
+
+#: src/devices/usb.cpp:51 src/devices/usb.cpp:96 src/devices/usb.cpp:98
+#, c-format
+msgid "USB device: %s"
+msgstr "Dispositivo USB: %s"
+
+#: src/devices/usb.cpp:94
+#, c-format
+msgid "USB device: %s (%s)"
+msgstr "Dispositivo USB: %s (%s)"
+
+#: src/devlist.cpp:330
+msgid "Process"
+msgstr ""
+
+#: src/devlist.cpp:347
+msgid "Process Device Activity"
+msgstr ""
+
+#: src/display.cpp:70
+msgid "Overview"
+msgstr "Información general"
+
+#: src/display.cpp:71
+msgid "Idle stats"
+msgstr "Estadísticas de parado"
+
+#: src/display.cpp:72
+msgid "Frequency stats"
+msgstr "Estadísticas de frecuencia"
+
+#: src/display.cpp:73
+msgid "Device stats"
+msgstr "Estadísticas del dispositivo"
+
+#: src/display.cpp:131
+msgid "Exit"
+msgstr "Salida"
+
+#: src/display.cpp:132
+msgid "Navigate"
+msgstr ""
+
+#: src/lib.cpp:288
+#, c-format
+msgid "%7sW"
+msgstr "%7sW"
+
+#: src/lib.cpp:291
+#, c-format
+msgid " 0 mW"
+msgstr " 0 mW"
+
+#: src/lib.cpp:410
+msgid "PS/2 Touchpad / Keyboard / Mouse"
+msgstr "PS/2 Touchpad / Teclado / Ratón"
+
+#: src/lib.cpp:411
+msgid "SATA controller"
+msgstr "Controlador SATA"
+
+#: src/lib.cpp:412
+msgid "Intel built in USB hub"
+msgstr "Intel construido en concentrador USB"
+
+#: src/lib.cpp:467
+#, c-format
+msgid "glob returned GLOB_NOSPACE\n"
+msgstr ""
+
+#: src/lib.cpp:471
+#, c-format
+msgid "glob returned GLOB_ABORTED\n"
+msgstr ""
+
+#: src/lib.cpp:475
+#, c-format
+msgid "glob returned GLOB_NOMATCH\n"
+msgstr ""
+
+#: src/lib.cpp:513 src/lib.cpp:549
+#, c-format
+msgid ""
+"Model-specific registers (MSR)\t\t\t not found (try enabling "
+"CONFIG_X86_MSR).\n"
+msgstr ""
+
+#: src/main.cpp:104
+#, fuzzy, c-format
+msgid "PowerTOP version "
+msgstr "PowerTOP "
+
+#: src/main.cpp:110
+msgid "Set refresh time out"
+msgstr "Actualización Set time out"
+
+#: src/main.cpp:123
+msgid "Usage: powertop [OPTIONS]"
+msgstr ""
+
+#: src/main.cpp:124
+msgid "sets all tunable options to their GOOD setting"
+msgstr ""
+
+#: src/main.cpp:125
+msgid "runs powertop in calibration mode"
+msgstr ""
+
+#: src/main.cpp:126 src/main.cpp:129
+msgid "[=filename]"
+msgstr ""
+
+#: src/main.cpp:126
+msgid "generate a csv report"
+msgstr ""
+
+#: src/main.cpp:127
+msgid "run in \"debug\" mode"
+msgstr ""
+
+#: src/main.cpp:128
+msgid "[=devnode]"
+msgstr ""
+
+#: src/main.cpp:128
+msgid "uses an Extech Power Analyzer for measurements"
+msgstr ""
+
+#: src/main.cpp:129
+msgid "generate a html report"
+msgstr ""
+
+#: src/main.cpp:130
+msgid "[=iterations] number of times to run each test"
+msgstr ""
+
+#: src/main.cpp:131
+msgid "suppress stderr output"
+msgstr ""
+
+#: src/main.cpp:132 src/main.cpp:133
+msgid "[=seconds]"
+msgstr ""
+
+#: src/main.cpp:132
+msgid "interval for power consumption measurement"
+msgstr ""
+
+#: src/main.cpp:133
+msgid "generate a report for 'x' seconds"
+msgstr ""
+
+#: src/main.cpp:134
+msgid "[=workload]"
+msgstr ""
+
+#: src/main.cpp:134
+msgid "file to execute for workload"
+msgstr ""
+
+#: src/main.cpp:135
+msgid "print version information"
+msgstr ""
+
+#: src/main.cpp:136
+msgid "print this help menu"
+msgstr ""
+
+#: src/main.cpp:138
+msgid "For more help please refer to the 'man 8 powertop'"
+msgstr ""
+
+#: src/main.cpp:233
+#, c-format
+msgid "Unknown issue running workload!\n"
+msgstr ""
+
+#: src/main.cpp:290
+msgid "PowerTOP is out of memory. PowerTOP is Aborting"
+msgstr ""
+
+#: src/main.cpp:298
+#, c-format
+msgid "Preparing to take measurements\n"
+msgstr ""
+
+#: src/main.cpp:303
+#, c-format
+msgid "Taking %d measurement(s) for a duration of %d second(s) each.\n"
+msgstr ""
+
+#: src/main.cpp:305
+#, c-format
+msgid "Measuring workload %s.\n"
+msgstr ""
+
+#: src/main.cpp:330
+#, c-format
+msgid "PowerTOP "
+msgstr "PowerTOP "
+
+#: src/main.cpp:331 src/main.cpp:381
+#, c-format
+msgid "exiting...\n"
+msgstr "saliendo...\n"
+
+#: src/main.cpp:365
+#, c-format
+msgid "modprobe cpufreq_stats failed\n"
+msgstr ""
+
+#: src/main.cpp:368
+#, c-format
+msgid "modprobe msr failed\n"
+msgstr ""
+
+#: src/main.cpp:380 src/main.cpp:384
+#, c-format
+msgid "Failed to mount debugfs!\n"
+msgstr ""
+
+#: src/main.cpp:385
+#, c-format
+msgid "Should still be able to auto tune...\n"
+msgstr ""
+
+#: src/main.cpp:467
+#, c-format
+msgid "Invalid CSV filename\n"
+msgstr ""
+
+#: src/main.cpp:483
+#, c-format
+msgid "Invalid HTML filename\n"
+msgstr ""
+
+#: src/main.cpp:492
+#, c-format
+msgid "Quiet mode failed!\n"
+msgstr ""
+
+#: src/main.cpp:560
+msgid "Leaving PowerTOP"
+msgstr ""
+
+#: src/parameters/persistent.cpp:46 src/parameters/persistent.cpp:155
+msgid "Cannot save to file"
+msgstr ""
+
+#: src/parameters/persistent.cpp:89 src/parameters/persistent.cpp:180
+msgid "Cannot load from file"
+msgstr ""
+
+#: src/parameters/persistent.cpp:138
+#, c-format
+msgid "Loaded %i prior measurements\n"
+msgstr "Cargado %i medidas previas\n"
+
+#: src/parameters/persistent.cpp:181
+msgid ""
+"File will be loaded after taking minimum number of measurement(s) with "
+"battery only \n"
+msgstr ""
+
+#: src/perf/perf.cpp:115
+#, c-format
+msgid ""
+"Too many open files, please increase the limit of open file descriptors.\n"
+msgstr ""
+
+#: src/perf/perf.cpp:117
+#, c-format
+msgid "PowerTOP %s needs the kernel to support the 'perf' subsystem\n"
+msgstr "PowerTOP %s necesita que el kernel soporte el subsistema 'perf'\n"
+
+#: src/perf/perf.cpp:118
+#, c-format
+msgid "as well as support for trace points in the kernel:\n"
+msgstr "así como soporte para puntos de seguimiento en el kernel:\n"
+
+#: src/process/do_process.cpp:819
+#, c-format
+msgid ""
+"Estimated power: %5.1f Measured power: %5.1f Sum: %5.1f\n"
+"\n"
+msgstr ""
+"Energía estimada: %5.1f Energía medida: %5.1f Sum: %5.1f\n"
+"\n"
+
+#: src/process/do_process.cpp:838
+#, c-format
+msgid "The estimated remaining time is %i hours, %i minutes\n"
+msgstr ""
+
+#: src/process/do_process.cpp:846
+msgid "Summary"
+msgstr "Resumen"
+
+#: src/process/do_process.cpp:846
+msgid "wakeups/second"
+msgstr ""
+
+#: src/process/do_process.cpp:846
+msgid "GPU ops/seconds"
+msgstr ""
+
+#: src/process/do_process.cpp:846
+msgid "VFS ops/sec and"
+msgstr ""
+
+#: src/process/do_process.cpp:846
+msgid "CPU use"
+msgstr ""
+
+#: src/process/do_process.cpp:850
+msgid "Power est."
+msgstr ""
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:1078
+msgid "Events/s"
+msgstr ""
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:931 src/process/do_process.cpp:1079
+msgid "Category"
+msgstr ""
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:932 src/process/do_process.cpp:1080
+#: src/tuning/tuning.cpp:242 src/tuning/tuning.cpp:270
+#: src/tuning/tuning.cpp:295 src/wakeup/waketab.cpp:155
+msgid "Description"
+msgstr ""
+
+#: src/process/do_process.cpp:927
+msgid "Wakeups/s"
+msgstr ""
+
+#: src/process/do_process.cpp:928
+msgid "GPU ops/s"
+msgstr ""
+
+#: src/process/do_process.cpp:929
+msgid "Disk IO/s"
+msgstr ""
+
+#: src/process/do_process.cpp:930
+msgid "GFX Wakeups/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1017
+msgid "Overview of Software Power Consumers"
+msgstr ""
+
+#: src/process/do_process.cpp:1057
+msgid "Target:"
+msgstr ""
+
+#: src/process/do_process.cpp:1058
+msgid "1 units/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1059
+msgid "System: "
+msgstr ""
+
+#: src/process/do_process.cpp:1061
+msgid " wakeup/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1062
+msgid "CPU: "
+msgstr ""
+
+#: src/process/do_process.cpp:1064
+#, c-format
+msgid "% usage"
+msgstr ""
+
+#: src/process/do_process.cpp:1065
+msgid "GPU:"
+msgstr ""
+
+#: src/process/do_process.cpp:1067 src/process/do_process.cpp:1073
+msgid " ops/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1068
+msgid "GFX:"
+msgstr ""
+
+#: src/process/do_process.cpp:1070
+msgid " wakeups/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1071
+msgid "VFS:"
+msgstr ""
+
+#: src/process/do_process.cpp:1139
+msgid "Top 10 Power Consumers"
+msgstr ""
+
+#: src/report/report.cpp:122
+#, fuzzy
+msgid "PowerTOP Version"
+msgstr "PowerTOP "
+
+#: src/report/report.cpp:131
+msgid "Kernel Version"
+msgstr ""
+
+#: src/report/report.cpp:135
+msgid "System Name"
+msgstr ""
+
+#: src/report/report.cpp:142
+msgid "CPU Information"
+msgstr ""
+
+#: src/report/report.cpp:154
+msgid "OS Information"
+msgstr ""
+
+#: src/report/report.cpp:161
+msgid "System Information"
+msgstr ""
+
+#: src/report/report.cpp:195
+#, fuzzy, c-format
+msgid "Cannot open output file %s (%s)\n"
+msgstr "No puede crear archivo temp\n"
+
+#: src/report/report.cpp:211
+#, c-format
+msgid "PowerTOP outputting using base filename %s\n"
+msgstr ""
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:49
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45
+msgid "Good"
+msgstr "Bueno"
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:50
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45
+msgid "Bad"
+msgstr "Malo"
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:51
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45 src/wakeup/wakeup.cpp:50
+msgid "Unknown"
+msgstr "Desconocido"
+
+#: src/tuning/bluetooth.cpp:48
+#, c-format
+msgid "Bluetooth device interface status"
+msgstr "Estado de la interfaz de dispositivo Bluetooth"
+
+#: src/tuning/ethernet.cpp:54 src/wakeup/wakeup_ethernet.cpp:51
+#, c-format
+msgid "Wake-on-lan status for device %s"
+msgstr "Estado Wake-on-lan para dispositivo %s"
+
+#: src/tuning/runtime.cpp:48
+#, c-format
+msgid "Runtime PM for %s device %s"
+msgstr "Tiempo de ejecución PM para %s dispositivo %s"
+
+#: src/tuning/runtime.cpp:50
+#, c-format
+msgid "%s device %s has no runtime power management"
+msgstr ""
+"%s dispositivo %s no tiene administración de energía en tiempo de ejecución"
+
+#: src/tuning/runtime.cpp:74
+#, c-format
+msgid "PCI Device %s has no runtime power management"
+msgstr ""
+"Dispositivo PCI %s no tiene administración de energía en tiempo de ejecución"
+
+#: src/tuning/runtime.cpp:76
+#, c-format
+msgid "Runtime PM for PCI Device %s"
+msgstr "Tiempo de ejecución PM para dispositivo PCI %s"
+
+#: src/tuning/runtime.cpp:80
+#, fuzzy, c-format
+msgid "Runtime PM for port %s of PCI device: %s"
+msgstr "Tiempo de ejecución PM para %s dispositivo %s"
+
+#: src/tuning/runtime.cpp:83
+#, fuzzy, c-format
+msgid "Runtime PM for disk %s"
+msgstr "Tiempo de ejecución PM para %s dispositivo %s"
+
+#: src/tuning/tuning.cpp:62
+msgid "Enable Audio codec power management"
+msgstr "Habilitar administración de energía del codec de Audio "
+
+#: src/tuning/tuning.cpp:63
+msgid "NMI watchdog should be turned off"
+msgstr "Vigilancia NMI se debe apagar"
+
+#: src/tuning/tuning.cpp:64
+msgid "Power Aware CPU scheduler"
+msgstr "Planificador de CPU Consciente de Energía "
+
+#: src/tuning/tuning.cpp:65
+msgid "VM writeback timeout"
+msgstr "Tiempo límite de reescritura VM"
+
+#: src/tuning/tuning.cpp:81
+msgid "Tunables"
+msgstr "Optimizables"
+
+#: src/tuning/tuning.cpp:81
+msgid " <ESC> Exit | <Enter> Toggle tunable | <r> Window refresh"
+msgstr ""
+" Salida de <ESC>| <Enter>Palanca ajustable | Actualización de <r>ventana"
+
+#: src/tuning/tuning.cpp:243 src/wakeup/waketab.cpp:156
+msgid "Script"
+msgstr ""
+
+#: src/tuning/tuning.cpp:257
+msgid "Software Settings in Need of Tuning"
+msgstr ""
+
+#: src/tuning/tuning.cpp:276
+msgid "Untunable Software Issues"
+msgstr ""
+
+#: src/tuning/tuning.cpp:307
+msgid "Optimal Tuned Software Settings"
+msgstr ""
+
+#: src/tuning/tuningi2c.cpp:57
+#, fuzzy, c-format
+msgid "Runtime PM for I2C %s %s (%s)"
+msgstr "Tiempo de ejecución PM para %s dispositivo %s"
+
+#: src/tuning/tuningi2c.cpp:59
+#, fuzzy, c-format
+msgid "I2C %s %s has no runtime power management"
+msgstr ""
+"%s dispositivo %s no tiene administración de energía en tiempo de ejecución"
+
+#: src/tuning/tuningsysfs.cpp:123
+#, fuzzy, c-format
+msgid "Enable SATA link power management for %s"
+msgstr "Habilitar administración de energía del codec de Audio "
+
+#: src/tuning/tuningusb.cpp:54
+#, c-format
+msgid "Autosuspend for unknown USB device %s (%s:%s)"
+msgstr "Autosuspender para dispositivo USB desconocido %s (%s:%s)"
+
+#: src/tuning/tuningusb.cpp:71 src/tuning/tuningusb.cpp:73
+#: src/tuning/tuningusb.cpp:75
+#, c-format
+msgid "Autosuspend for USB device %s [%s]"
+msgstr "Autosuspender para dispositivo USB %s [%s]"
+
+#: src/tuning/wifi.cpp:48
+#, c-format
+msgid "Wireless Power Saving for interface %s"
+msgstr "Ahorro de Energía Wireless para interfaz %s"
+
+#: src/wakeup/waketab.cpp:42
+msgid "WakeUp"
+msgstr ""
+
+#: src/wakeup/waketab.cpp:42
+#, fuzzy
+msgid " <ESC> Exit | <Enter> Toggle wakeup | <r> Window refresh"
+msgstr ""
+" Salida de <ESC>| <Enter>Palanca ajustable | Actualización de <r>ventana"
+
+#: src/wakeup/waketab.cpp:170
+#, fuzzy
+msgid "Wake status of the devices"
+msgstr "Estado Wake-on-lan para dispositivo %s"
+
+#: src/wakeup/wakeup.cpp:48 src/wakeup/wakeup_ethernet.cpp:47
+#: src/wakeup/wakeup_usb.cpp:47
+#, fuzzy
+msgid "Enabled"
+msgstr "Optimizables"
+
+#: src/wakeup/wakeup.cpp:49 src/wakeup/wakeup_ethernet.cpp:47
+#: src/wakeup/wakeup_usb.cpp:47
+msgid "Disabled"
+msgstr ""
+
+#: src/wakeup/wakeup_usb.cpp:51
+#, fuzzy, c-format
+msgid "Wake status for USB device %s"
+msgstr "Estado Wake-on-lan para dispositivo %s"
+
+#~ msgid "Actual"
+#~ msgstr "Actual"
+
+#, fuzzy
+#~ msgid "I2C Device: %s"
+#~ msgstr "Dispositivo PCI: %s"
+
+#~ msgid "Using 'ondemand' cpufreq governor"
+#~ msgstr "Usando 'ondemand' cpufreq governor"
diff --git a/po/fy.po b/po/fy.po
new file mode 100644
index 0000000..44361f3
--- /dev/null
+++ b/po/fy.po
@@ -0,0 +1,992 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Intel Corporation
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Sietse <sietse@vdmolen.eu>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: PowerTOP\n"
+"Report-Msgid-Bugs-To: powertop@lists.01.org\n"
+"POT-Creation-Date: 2019-01-04 13:55-0800\n"
+"PO-Revision-Date: 2013-11-05 08:40+0000\n"
+"Last-Translator: Margie Foster <margie@linux.intel.com>\n"
+"Language-Team: Western Frisian (http://www.transifex.com/projects/p/PowerTOP/"
+"language/fy/)\n"
+"Language: fy\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ../src/calibrate/calibrate.cpp:238
+#, c-format
+msgid "Cannot create temp file\n"
+msgstr "Kin gjin tydlike triem meitsje\\n"
+
+#: ../src/calibrate/calibrate.cpp:258
+#, c-format
+msgid "Calibrating: CPU usage on %i threads\n"
+msgstr "Kalibrearjen: CPU gebrúk op %i threads\\n"
+
+#: ../src/calibrate/calibrate.cpp:273
+#, c-format
+msgid "Calibrating: CPU wakeup power consumption\n"
+msgstr "Kalibrearjen: CPU wakeup krêft gebrúk\\n"
+
+#: ../src/calibrate/calibrate.cpp:290
+#, c-format
+msgid "Calibrating USB devices\n"
+msgstr "USB Apparaten oan it kalibrearjen\\n"
+
+#: ../src/calibrate/calibrate.cpp:292 ../src/calibrate/calibrate.cpp:309
+#: ../src/calibrate/calibrate.cpp:317 ../src/calibrate/calibrate.cpp:334
+#, c-format
+msgid ".... device %s \n"
+msgstr ".... apparaat %s \\n"
+
+#: ../src/calibrate/calibrate.cpp:307
+#, c-format
+msgid "Calibrating radio devices\n"
+msgstr "Radio apparaten oan it kalibrearjen\\n"
+
+#: ../src/calibrate/calibrate.cpp:331
+#, c-format
+msgid "Calibrating backlight\n"
+msgstr "Eftergrûnljocht oan it kalibrearjen\\n"
+
+#: ../src/calibrate/calibrate.cpp:355 ../src/calibrate/calibrate.cpp:365
+#, c-format
+msgid "Calibrating idle\n"
+msgstr "Kalibrearjen yn rêst\\n"
+
+#: ../src/calibrate/calibrate.cpp:378
+#, c-format
+msgid "Calibrating: disk usage \n"
+msgstr "Kalibrearjen: skiff gebrúk\\n"
+
+#: ../src/calibrate/calibrate.cpp:403
+msgid "Starting PowerTOP power estimate calibration \n"
+msgstr "PowerTOP krêft skatting kalibraasje wurd start\\n"
+
+#: ../src/calibrate/calibrate.cpp:426
+msgid "Finishing PowerTOP power estimate calibration \n"
+msgstr "PowerTOP krêft skatting kalibraasje wurd beëine\\n"
+
+#: ../src/calibrate/calibrate.cpp:430
+#, c-format
+msgid "Parameters after calibration:\n"
+msgstr "Parameters nei kalibraasje:\\n"
+
+#: ../src/cpu/abstract_cpu.cpp:74
+msgid "Idle"
+msgstr ""
+
+#: ../src/cpu/abstract_cpu.cpp:76
+msgid "Turbo Mode"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(HW)"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(OS)"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:91 ../src/cpu/intel_cpus.cpp:324
+#, c-format
+msgid " Core"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:85
+#, c-format
+msgid "cpu package %i"
+msgstr "cpu pakket %i"
+
+#: ../src/cpu/cpu.cpp:86
+msgid "cpu package"
+msgstr "cpu pakket"
+
+#: ../src/cpu/cpu.cpp:89 ../src/cpu/cpu.cpp:96
+#, fuzzy, c-format
+msgid "package-%i"
+msgstr "Pakket %i"
+
+#: ../src/cpu/cpu.cpp:90
+msgid "cpu rapl package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:97
+msgid "dram rapl package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:471
+msgid "Processor Idle State Report"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:535 ../src/cpu/cpu.cpp:753
+msgid "Package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:566 ../src/cpu/cpu.cpp:775
+#, fuzzy, c-format
+msgid "Core %d"
+msgstr "Kern %i"
+
+#: ../src/cpu/cpu.cpp:573
+#, fuzzy, c-format
+msgid "GPU %d"
+msgstr "GPU %i"
+
+#: ../src/cpu/cpu.cpp:594
+#, fuzzy
+msgid "CPU"
+msgstr "CPU %i"
+
+#: ../src/cpu/cpu.cpp:676
+msgid "Processor Frequency Report"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:796
+#, fuzzy, c-format
+msgid "CPU %d"
+msgstr "CPU %i"
+
+#: ../src/cpu/cpu.cpp:997
+#, c-format
+msgid "cpu_idle event returned no state?\n"
+msgstr "cpu_idle event hat gjin steat werom jûn?\\n"
+
+#: ../src/cpu/cpu.cpp:1012
+#, c-format
+msgid "power or cpu_frequency event returned no state?\n"
+msgstr ""
+
+#: ../src/cpu/cpu_linux.cpp:79
+msgid "C0 polling"
+msgstr "C0 polling"
+
+#: ../src/cpu/cpu_linux.cpp:242
+#, c-format
+msgid " CPU(OS) %i"
+msgstr ""
+
+#: ../src/cpu/cpu_linux.cpp:341 ../src/cpu/intel_cpus.cpp:651
+#, c-format
+msgid " CPU %i"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(HW)"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(OS)"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:104 ../src/cpu/intel_cpus.cpp:412
+#, c-format
+msgid " Package"
+msgstr ""
+
+#: ../src/cpu/intel_cpus.cpp:129
+#, c-format
+msgid "read_msr cpu%d 0x%llx : "
+msgstr ""
+
+#: ../src/cpu/intel_cpus.cpp:574
+msgid "C0 active"
+msgstr "C0 aktyf"
+
+#: ../src/cpu/intel_cpus.cpp:632
+#, c-format
+msgid "Average"
+msgstr ""
+
+#: ../src/cpu/intel_gpu.cpp:64
+#, fuzzy, c-format
+msgid " GPU "
+msgstr "GPU %i"
+
+#: ../src/devices/ahci.cpp:154
+#, c-format
+msgid "SATA link: %s"
+msgstr "SATA ferbyning: %s"
+
+#: ../src/devices/ahci.cpp:156
+#, c-format
+msgid "SATA disk: %s"
+msgstr "SATA skiif: %s"
+
+#: ../src/devices/ahci.cpp:374
+msgid "AHCI ALPM Residency Statistics - Not supported on this macine"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:389
+msgid "Link"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:390
+#, fuzzy
+msgid "Active"
+msgstr "C0 aktyf"
+
+#: ../src/devices/ahci.cpp:391
+msgid "Partial"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:392
+msgid "Slumber"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:393
+msgid "Devslp"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:399
+msgid "AHCI ALPM Residency Statistics"
+msgstr ""
+
+#: ../src/devices/alsa.cpp:77
+#, c-format
+msgid "Audio codec %s: %s (%s)"
+msgstr "Audio codec %s: %s (%s)"
+
+#: ../src/devices/alsa.cpp:79 ../src/devices/alsa.cpp:81
+#, c-format
+msgid "Audio codec %s: %s"
+msgstr "Audio codec %s: %s"
+
+#: ../src/devices/devfreq.cpp:261
+#, fuzzy
+msgid "Device Freq stats"
+msgstr "Apparaat statistiken"
+
+#: ../src/devices/devfreq.cpp:279
+msgid " Devfreq is not enabled"
+msgstr ""
+
+#: ../src/devices/devfreq.cpp:284
+msgid " No devfreq devices available"
+msgstr ""
+
+#: ../src/devices/device.cpp:172 ../src/process/do_process.cpp:831
+#, c-format
+msgid "The battery reports a discharge rate of %sW\n"
+msgstr "De batterij rapportearret in ûntladings snelheid fan %sW\\n"
+
+#: ../src/devices/device.cpp:174 ../src/process/do_process.cpp:833
+#, c-format
+msgid "The power consumed was %sJ\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:180
+#, c-format
+msgid "System baseline power is estimated at %sW\n"
+msgstr "Basiskrêft fan it systeem is skat op %sW\\n"
+
+#: ../src/devices/device.cpp:187
+msgid "Power est. Usage Device name\n"
+msgstr "Skatte krêft bruk Apparaatnamme\\n"
+
+#: ../src/devices/device.cpp:189
+msgid " Usage Device name\n"
+msgstr "Bruk Apparaatnamme\\n"
+
+#: ../src/devices/device.cpp:256
+#, fuzzy
+msgid "The battery reports a discharge rate of: "
+msgstr "De batterij rapportearret in ûntladings snelheid fan %sW\\n"
+
+#: ../src/devices/device.cpp:261
+msgid "The power consumed was : "
+msgstr ""
+
+#: ../src/devices/device.cpp:268
+#, fuzzy
+msgid "The system baseline power is estimated at: "
+msgstr "Basiskrêft fan it systeem is skat op %sW\\n"
+
+#: ../src/devices/device.cpp:277 ../src/process/do_process.cpp:850
+#: ../src/process/do_process.cpp:852 ../src/process/do_process.cpp:926
+#: ../src/process/do_process.cpp:1077
+msgid "Usage"
+msgstr "Gebrúk"
+
+#: ../src/devices/device.cpp:278
+#, fuzzy
+msgid "Device Name"
+msgstr "Apparaat statistiken"
+
+#: ../src/devices/device.cpp:280 ../src/process/do_process.cpp:935
+#: ../src/process/do_process.cpp:1082
+msgid "PW Estimate"
+msgstr ""
+
+#. Report Output
+#: ../src/devices/device.cpp:317
+msgid "Device Power Report"
+msgstr ""
+
+#: ../src/devices/network.cpp:177
+#, c-format
+msgid "Network interface: %s (%s)"
+msgstr "Netwurk ynterface: %s (%s)"
+
+#: ../src/devices/rfkill.cpp:65 ../src/devices/rfkill.cpp:69
+#, c-format
+msgid "Radio device: %s"
+msgstr "Radio apparaat: %s"
+
+#: ../src/devices/runtime_pm.cpp:216
+#, c-format
+msgid "I2C %s (%s): %s"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216 ../src/tuning/tuningi2c.cpp:57
+#: ../src/tuning/tuningi2c.cpp:59
+msgid "Adapter"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216 ../src/devlist.cpp:331
+#: ../src/tuning/tuningi2c.cpp:57 ../src/tuning/tuningi2c.cpp:59
+#, fuzzy
+msgid "Device"
+msgstr "Apparaat statistiken"
+
+#: ../src/devices/runtime_pm.cpp:241
+#, c-format
+msgid "PCI Device: %s"
+msgstr "PCI Apparaat: %s"
+
+#: ../src/devices/usb.cpp:51 ../src/devices/usb.cpp:96
+#: ../src/devices/usb.cpp:98
+#, c-format
+msgid "USB device: %s"
+msgstr "USB apparaat: %s"
+
+#: ../src/devices/usb.cpp:94
+#, c-format
+msgid "USB device: %s (%s)"
+msgstr "USB apparaat: %s (%s)"
+
+#: ../src/devlist.cpp:330
+msgid "Process"
+msgstr ""
+
+#. Report Output
+#. No div attribute here inherits from device power report
+#: ../src/devlist.cpp:347
+msgid "Process Device Activity"
+msgstr ""
+
+#: ../src/display.cpp:70
+msgid "Overview"
+msgstr "Oersicht"
+
+#: ../src/display.cpp:71
+msgid "Idle stats"
+msgstr "Ûnbrûkt statistiken"
+
+#: ../src/display.cpp:72
+msgid "Frequency stats"
+msgstr "Frekwinsje statistiken"
+
+#: ../src/display.cpp:73
+msgid "Device stats"
+msgstr "Apparaat statistiken"
+
+#: ../src/display.cpp:131
+msgid "Exit"
+msgstr "Ôfslúte"
+
+#: ../src/display.cpp:132
+msgid "Navigate"
+msgstr ""
+
+#: ../src/lib.cpp:288
+#, c-format
+msgid "%7sW"
+msgstr "%7sW"
+
+#: ../src/lib.cpp:291
+#, c-format
+msgid " 0 mW"
+msgstr "0 mW"
+
+#: ../src/lib.cpp:410
+msgid "PS/2 Touchpad / Keyboard / Mouse"
+msgstr "PS/2 Touchpad / Kaaiboerd / Mûs"
+
+#: ../src/lib.cpp:411
+msgid "SATA controller"
+msgstr "SATA stjoerder"
+
+#: ../src/lib.cpp:412
+msgid "Intel built in USB hub"
+msgstr "Intel ynbouwde USB hub"
+
+#: ../src/lib.cpp:467
+#, c-format
+msgid "glob returned GLOB_NOSPACE\n"
+msgstr ""
+
+#: ../src/lib.cpp:471
+#, c-format
+msgid "glob returned GLOB_ABORTED\n"
+msgstr ""
+
+#: ../src/lib.cpp:475
+#, c-format
+msgid "glob returned GLOB_NOMATCH\n"
+msgstr ""
+
+#: ../src/lib.cpp:513 ../src/lib.cpp:549
+#, c-format
+msgid ""
+"Model-specific registers (MSR)\t\t\t not found (try enabling "
+"CONFIG_X86_MSR).\n"
+msgstr ""
+
+#: ../src/main.cpp:103
+#, fuzzy, c-format
+msgid "PowerTOP version "
+msgstr "PowerTOP ferzje"
+
+#: ../src/main.cpp:109
+msgid "Set refresh time out"
+msgstr "Set ferfarskings tiid"
+
+#: ../src/main.cpp:122
+msgid "Usage: powertop [OPTIONS]"
+msgstr "Bruk: powertop [OPSJES]"
+
+#: ../src/main.cpp:123
+msgid "sets all tunable options to their GOOD setting"
+msgstr ""
+
+#: ../src/main.cpp:124
+msgid "runs powertop in calibration mode"
+msgstr "rint powertop yn kalibraasje stân"
+
+#: ../src/main.cpp:125 ../src/main.cpp:128
+msgid "[=filename]"
+msgstr ""
+
+#: ../src/main.cpp:125
+msgid "generate a csv report"
+msgstr "generearje in csv rapport"
+
+#: ../src/main.cpp:126
+msgid "run in \"debug\" mode"
+msgstr "rin in \"debug\" stân"
+
+#: ../src/main.cpp:127
+msgid "[=devnode]"
+msgstr "[=devnode]"
+
+#: ../src/main.cpp:127
+msgid "uses an Extech Power Analyzer for measurements"
+msgstr "Bruket in Extech Power Analyzer foar mjittingen"
+
+#: ../src/main.cpp:128
+msgid "generate a html report"
+msgstr "generearje in html rapport"
+
+#: ../src/main.cpp:129
+msgid "[=iterations] number of times to run each test"
+msgstr "[=iterations] oantal kearen dat eltse test rinne moat"
+
+#: ../src/main.cpp:130
+msgid "suppress stderr output"
+msgstr "underdruk stderr útfier"
+
+#: ../src/main.cpp:131 ../src/main.cpp:132
+msgid "[=seconds]"
+msgstr "[=sekondes]"
+
+#: ../src/main.cpp:131
+msgid "interval for power consumption measurement"
+msgstr ""
+
+#: ../src/main.cpp:132
+msgid "generate a report for 'x' seconds"
+msgstr "generearje in rapport foar 'x' sekonden"
+
+#: ../src/main.cpp:133
+msgid "[=workload]"
+msgstr "[=wurklading]"
+
+#: ../src/main.cpp:133
+msgid "file to execute for workload"
+msgstr "bestân om út te fieren foar wurklading"
+
+#: ../src/main.cpp:134
+msgid "print version information"
+msgstr "print ferzje ynformaasje"
+
+#: ../src/main.cpp:135
+msgid "print this help menu"
+msgstr "print dit help menu"
+
+#: ../src/main.cpp:137
+#, fuzzy
+msgid "For more help please refer to the 'man 8 powertop'"
+msgstr "Foar mear help, lês de README"
+
+#: ../src/main.cpp:232
+#, c-format
+msgid "Unknown issue running workload!\n"
+msgstr ""
+
+#: ../src/main.cpp:289
+msgid "PowerTOP is out of memory. PowerTOP is Aborting"
+msgstr "PowerTOP hat gjin geheugen mear. PowerTOP stoppet"
+
+#. one to warm up everything
+#: ../src/main.cpp:297
+#, c-format
+msgid "Preparing to take measurements\n"
+msgstr "Oan it klearmeitsjen om te mjitten\\n"
+
+#: ../src/main.cpp:302
+#, c-format
+msgid "Taking %d measurement(s) for a duration of %d second(s) each.\n"
+msgstr "Nim %d mjitting(en) foar in duraasje fan %d sekonde(n) elts.\\n"
+
+#: ../src/main.cpp:304
+#, c-format
+msgid "Measuring workload %s.\n"
+msgstr "Wurklading %s wurd mjitten.\\n"
+
+#: ../src/main.cpp:329
+#, c-format
+msgid "PowerTOP "
+msgstr "PowerTOP"
+
+#: ../src/main.cpp:330 ../src/main.cpp:380
+#, c-format
+msgid "exiting...\n"
+msgstr "slút ôf...\\n"
+
+#: ../src/main.cpp:364
+#, c-format
+msgid "modprobe cpufreq_stats failed"
+msgstr ""
+
+#: ../src/main.cpp:367
+#, c-format
+msgid "modprobe msr failed"
+msgstr ""
+
+#: ../src/main.cpp:379 ../src/main.cpp:383
+#, c-format
+msgid "Failed to mount debugfs!\n"
+msgstr "Keppeljen fan debugfs mislearre!\\n"
+
+#: ../src/main.cpp:384
+#, c-format
+msgid "Should still be able to auto tune...\n"
+msgstr ""
+
+#: ../src/main.cpp:466
+#, c-format
+msgid "Invalid CSV filename\n"
+msgstr ""
+
+#: ../src/main.cpp:482
+#, c-format
+msgid "Invalid HTML filename\n"
+msgstr ""
+
+#: ../src/main.cpp:491
+#, c-format
+msgid "Quiet mode failed!\n"
+msgstr ""
+
+#: ../src/main.cpp:559
+msgid "Leaving PowerTOP"
+msgstr "PowerTOP wurd ferlitten"
+
+#: ../src/parameters/persistent.cpp:46 ../src/parameters/persistent.cpp:155
+msgid "Cannot save to file"
+msgstr "Kin net nei triem skriuwe"
+
+#: ../src/parameters/persistent.cpp:89 ../src/parameters/persistent.cpp:180
+msgid "Cannot load from file"
+msgstr "Kin net fan triem lêze"
+
+#. '%i" is for count, do not translate
+#: ../src/parameters/persistent.cpp:138
+#, c-format
+msgid "Loaded %i prior measurements\n"
+msgstr "%i eardere mjittingen laden\\n"
+
+#: ../src/parameters/persistent.cpp:181
+msgid ""
+"File will be loaded after taking minimum number of measurement(s) with "
+"battery only \n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:115
+#, c-format
+msgid ""
+"Too many open files, please increase the limit of open file descriptors.\n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:117
+#, c-format
+msgid "PowerTOP %s needs the kernel to support the 'perf' subsystem\n"
+msgstr "PowerTop %s hat in kernel nedich dy't it 'perf' subsysteem stypet\\n"
+
+#: ../src/perf/perf.cpp:118
+#, c-format
+msgid "as well as support for trace points in the kernel:\n"
+msgstr "en ek trasearingspunten yn de kernel:\\n"
+
+#: ../src/process/do_process.cpp:819
+#, c-format
+msgid ""
+"Estimated power: %5.1f Measured power: %5.1f Sum: %5.1f\n"
+"\n"
+msgstr "Skatte krêft: %5.1f Mjitten krêft: %5.1f Som: %5.1f\\n\\n"
+
+#: ../src/process/do_process.cpp:838
+#, c-format
+msgid "The estimated remaining time is %i hours, %i minutes\n"
+msgstr "The skatte restearjende tiid is %i oeren, %i minuten\\n"
+
+#: ../src/process/do_process.cpp:846
+msgid "Summary"
+msgstr "Gearfetting"
+
+#: ../src/process/do_process.cpp:846
+msgid "wakeups/second"
+msgstr "wakeups/sekonde"
+
+#: ../src/process/do_process.cpp:846
+msgid "GPU ops/seconds"
+msgstr "GPU ops/sekondes"
+
+#: ../src/process/do_process.cpp:846
+msgid "VFS ops/sec and"
+msgstr "VFS ops/sek en"
+
+#: ../src/process/do_process.cpp:846
+msgid "CPU use"
+msgstr "CPU gebrúk"
+
+#: ../src/process/do_process.cpp:850
+msgid "Power est."
+msgstr "Krêft skatting"
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:1078
+msgid "Events/s"
+msgstr "Events/s"
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:931 ../src/process/do_process.cpp:1079
+msgid "Category"
+msgstr "Kategory"
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:932 ../src/process/do_process.cpp:1080
+#: ../src/tuning/tuning.cpp:242 ../src/tuning/tuning.cpp:270
+#: ../src/tuning/tuning.cpp:288 ../src/wakeup/waketab.cpp:155
+msgid "Description"
+msgstr "Beskriuwing"
+
+#: ../src/process/do_process.cpp:927
+msgid "Wakeups/s"
+msgstr "Wakeups/s"
+
+#: ../src/process/do_process.cpp:928
+msgid "GPU ops/s"
+msgstr "GPU ops/s"
+
+#: ../src/process/do_process.cpp:929
+msgid "Disk IO/s"
+msgstr "Disk IO/s"
+
+#: ../src/process/do_process.cpp:930
+msgid "GFX Wakeups/s"
+msgstr "GFX Wakeups/s"
+
+#: ../src/process/do_process.cpp:1017
+msgid "Overview of Software Power Consumers"
+msgstr "Oersjoch fan Software Krêft Brûkers"
+
+#: ../src/process/do_process.cpp:1057
+msgid "Target:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1058
+msgid "1 units/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1059
+msgid "System: "
+msgstr ""
+
+#: ../src/process/do_process.cpp:1061
+#, fuzzy
+msgid " wakeup/s"
+msgstr "Wakeups/s"
+
+#: ../src/process/do_process.cpp:1062
+msgid "CPU: "
+msgstr ""
+
+#: ../src/process/do_process.cpp:1064
+#, fuzzy, c-format
+msgid "% usage"
+msgstr "Gebrúk"
+
+#: ../src/process/do_process.cpp:1065
+msgid "GPU:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1067 ../src/process/do_process.cpp:1073
+#, fuzzy
+msgid " ops/s"
+msgstr "GPU ops/s"
+
+#: ../src/process/do_process.cpp:1068
+msgid "GFX:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1070
+#, fuzzy
+msgid " wakeups/s"
+msgstr "Wakeups/s"
+
+#: ../src/process/do_process.cpp:1071
+msgid "VFS:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1139
+#, fuzzy
+msgid "Top 10 Power Consumers"
+msgstr "Oersjoch fan Software Krêft Brûkers"
+
+#: ../src/report/report.cpp:122
+#, fuzzy
+msgid "PowerTOP Version"
+msgstr "PowerTOP ferzje"
+
+#: ../src/report/report.cpp:131
+#, fuzzy
+msgid "Kernel Version"
+msgstr "PowerTOP ferzje"
+
+#: ../src/report/report.cpp:135
+msgid "System Name"
+msgstr ""
+
+#: ../src/report/report.cpp:142
+msgid "CPU Information"
+msgstr ""
+
+#: ../src/report/report.cpp:154
+msgid "OS Information"
+msgstr ""
+
+#: ../src/report/report.cpp:161
+#, fuzzy
+msgid "System Information"
+msgstr "print ferzje ynformaasje"
+
+#: ../src/report/report.cpp:195
+#, fuzzy, c-format
+msgid "Cannot open output file %s (%s)\n"
+msgstr "Kin gjin tydlike triem meitsje\\n"
+
+#: ../src/report/report.cpp:211
+#, c-format
+msgid "PowerTOP outputing using base filename %s\n"
+msgstr ""
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:49
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+msgid "Good"
+msgstr "Goed"
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:50
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+msgid "Bad"
+msgstr "Min"
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:51
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+#: ../src/wakeup/wakeup.cpp:50
+msgid "Unknown"
+msgstr "Unbekind"
+
+#: ../src/tuning/bluetooth.cpp:48
+#, c-format
+msgid "Bluetooth device interface status"
+msgstr "Bluetooth apparaat ynterface status"
+
+#: ../src/tuning/ethernet.cpp:54 ../src/wakeup/wakeup_ethernet.cpp:51
+#, c-format
+msgid "Wake-on-lan status for device %s"
+msgstr "Wake-on-lan status foar apparaat %s"
+
+#: ../src/tuning/runtime.cpp:48
+#, c-format
+msgid "Runtime PM for %s device %s"
+msgstr "Runtime PM foar %s apparaat %s"
+
+#: ../src/tuning/runtime.cpp:50
+#, c-format
+msgid "%s device %s has no runtime power management"
+msgstr "%s apparaat %s hat gjin runtime krêft regelder"
+
+#: ../src/tuning/runtime.cpp:74
+#, c-format
+msgid "PCI Device %s has no runtime power management"
+msgstr "PCI Apparaat %s hat gjin runtime krêft regelder"
+
+#: ../src/tuning/runtime.cpp:76
+#, c-format
+msgid "Runtime PM for PCI Device %s"
+msgstr "Runtime KR for PCI Apparaat %s"
+
+#: ../src/tuning/tuning.cpp:62
+msgid "Enable Audio codec power management"
+msgstr "Skeakelje Audio codec krêft behearder yn"
+
+#: ../src/tuning/tuning.cpp:63
+msgid "NMI watchdog should be turned off"
+msgstr "NMI wachthûn soe útset wurde moatte"
+
+#: ../src/tuning/tuning.cpp:64
+msgid "Power Aware CPU scheduler"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:65
+msgid "VM writeback timeout"
+msgstr "VM writeback timeout"
+
+#: ../src/tuning/tuning.cpp:81
+msgid "Tunables"
+msgstr "Ôfstellers"
+
+#: ../src/tuning/tuning.cpp:81
+msgid " <ESC> Exit | <Enter> Toggle tunable | <r> Window refresh"
+msgstr "<ESC> Ôfslúte | <Enter> Skeakelje ôfsteller | <r> Ferfarskje skerm"
+
+#: ../src/tuning/tuning.cpp:243 ../src/wakeup/waketab.cpp:156
+msgid "Script"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:257
+msgid "Software Settings in Need of Tuning"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:276
+msgid "Untunable Software Issues"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:300
+msgid "Optimal Tuned Software Settings"
+msgstr ""
+
+#: ../src/tuning/tuningi2c.cpp:57
+#, fuzzy, c-format
+msgid "Runtime PM for I2C %s %s (%s)"
+msgstr "Runtime PM foar %s apparaat %s"
+
+#: ../src/tuning/tuningi2c.cpp:59
+#, fuzzy, c-format
+msgid "I2C %s %s has no runtime power management"
+msgstr "%s apparaat %s hat gjin runtime krêft regelder"
+
+#: ../src/tuning/tuningsysfs.cpp:123
+#, fuzzy, c-format
+msgid "Enable SATA link power management for %s"
+msgstr "Skeakelje SATA link krêft behear yn foar %s"
+
+#: ../src/tuning/tuningusb.cpp:54
+#, c-format
+msgid "Autosuspend for unknown USB device %s (%s:%s)"
+msgstr "Autosliepstân foan ûnbekind USB apparaat %s (%s:%s)"
+
+#: ../src/tuning/tuningusb.cpp:71 ../src/tuning/tuningusb.cpp:73
+#: ../src/tuning/tuningusb.cpp:75
+#, c-format
+msgid "Autosuspend for USB device %s [%s]"
+msgstr "Autosliepstân foar USB apparaat %s [%s]"
+
+#: ../src/tuning/wifi.cpp:48
+#, c-format
+msgid "Wireless Power Saving for interface %s"
+msgstr "Triedleaze Krêft Sparring foar ynterface %s"
+
+#: ../src/wakeup/waketab.cpp:42
+#, fuzzy
+msgid "WakeUp"
+msgstr "Wakeups/s"
+
+#: ../src/wakeup/waketab.cpp:42
+#, fuzzy
+msgid " <ESC> Exit | <Enter> Toggle wakeup | <r> Window refresh"
+msgstr "<ESC> Ôfslúte | <Enter> Skeakelje ôfsteller | <r> Ferfarskje skerm"
+
+#. Report Output
+#: ../src/wakeup/waketab.cpp:170
+#, fuzzy
+msgid "Wake status of the devices"
+msgstr "Wake-on-lan status foar apparaat %s"
+
+#: ../src/wakeup/wakeup.cpp:48 ../src/wakeup/wakeup_ethernet.cpp:47
+#: ../src/wakeup/wakeup_usb.cpp:47
+#, fuzzy
+msgid "Enable"
+msgstr "Ôfstellers"
+
+#: ../src/wakeup/wakeup.cpp:49 ../src/wakeup/wakeup_ethernet.cpp:47
+#: ../src/wakeup/wakeup_usb.cpp:47
+msgid "Disable"
+msgstr ""
+
+#: ../src/wakeup/wakeup_usb.cpp:51
+#, fuzzy, c-format
+msgid "Wake status for USB device %s"
+msgstr "Wake-on-lan status foar apparaat %s"
+
+#~ msgid "Actual"
+#~ msgstr "Aktueel"
+
+#~ msgid "Power Consumption Summary"
+#~ msgstr "Krêft Bruk Oersjoch"
+
+#~ msgid "GPU ops/second"
+#~ msgstr "GPU ops/sekonde"
+
+#~ msgid "VFS ops/sec"
+#~ msgstr "VFS ops/sek"
+
+#~ msgid "GFX wakes/sec and"
+#~ msgstr "GFX wakes/sek en"
+
+#~ msgid "Using 'ondemand' cpufreq governor"
+#~ msgstr "Brukt 'ondemand' cpufreq ynsteller"
+
+#~ msgid "[=FILENAME]"
+#~ msgstr "[=FILENAME]"
diff --git a/po/hi.po b/po/hi.po
new file mode 100644
index 0000000..5fa3bb7
--- /dev/null
+++ b/po/hi.po
@@ -0,0 +1,996 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Intel Corporation
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# piyushkumarchauhan <piyushkumarchauhan@live.in>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: PowerTOP\n"
+"Report-Msgid-Bugs-To: powertop@lists.01.org\n"
+"POT-Creation-Date: 2019-01-04 13:55-0800\n"
+"PO-Revision-Date: 2013-11-05 08:40+0000\n"
+"Last-Translator: Margie Foster <margie@linux.intel.com>\n"
+"Language-Team: Hindi (http://www.transifex.com/projects/p/PowerTOP/language/"
+"hi/)\n"
+"Language: hi\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ../src/calibrate/calibrate.cpp:238
+#, c-format
+msgid "Cannot create temp file\n"
+msgstr "अस्थायी फ़ाइल नहीं बना सकते\n"
+
+#: ../src/calibrate/calibrate.cpp:258
+#, c-format
+msgid "Calibrating: CPU usage on %i threads\n"
+msgstr "केलिब्रतिंग: सीपीयू की खपत %i है लड़ियाँ पे\n"
+
+#: ../src/calibrate/calibrate.cpp:273
+#, c-format
+msgid "Calibrating: CPU wakeup power consumption\n"
+msgstr "केलिब्रतिंग: सीपीयू के सतर्क होने के समय की शक्ति की खपत\n"
+
+#: ../src/calibrate/calibrate.cpp:290
+#, c-format
+msgid "Calibrating USB devices\n"
+msgstr "यूएसबी उपकरण केलिब्रेट हो रहे हैं\n"
+
+#: ../src/calibrate/calibrate.cpp:292 ../src/calibrate/calibrate.cpp:309
+#: ../src/calibrate/calibrate.cpp:317 ../src/calibrate/calibrate.cpp:334
+#, c-format
+msgid ".... device %s \n"
+msgstr "...उपकरण %s\n"
+
+#: ../src/calibrate/calibrate.cpp:307
+#, c-format
+msgid "Calibrating radio devices\n"
+msgstr "रेडियो उपकरण केलिब्रेट हो रहे हैं\n"
+
+#: ../src/calibrate/calibrate.cpp:331
+#, c-format
+msgid "Calibrating backlight\n"
+msgstr "बेकलाईट केलिब्रेट हो रहा है \n"
+
+#: ../src/calibrate/calibrate.cpp:355 ../src/calibrate/calibrate.cpp:365
+#, c-format
+msgid "Calibrating idle\n"
+msgstr "निष्क्रिय केलिब्रेट हो रहा है\n"
+
+#: ../src/calibrate/calibrate.cpp:378
+#, c-format
+msgid "Calibrating: disk usage \n"
+msgstr "कलिब्रटिंग: डिस्क की खपत \n"
+
+#: ../src/calibrate/calibrate.cpp:403
+msgid "Starting PowerTOP power estimate calibration \n"
+msgstr "PowerTOP की शक्ति का अनुमान का केलिब्रेसन सुरु हो रहा हैं\n"
+
+#: ../src/calibrate/calibrate.cpp:426
+msgid "Finishing PowerTOP power estimate calibration \n"
+msgstr "PowerTOP की शक्ति का अनुमान का केलिब्रेसन समाप्त हो रहा हैं\n"
+
+#: ../src/calibrate/calibrate.cpp:430
+#, c-format
+msgid "Parameters after calibration:\n"
+msgstr "केलिब्रेसन के बाद पैरामीटर्स:\n"
+
+#: ../src/cpu/abstract_cpu.cpp:74
+msgid "Idle"
+msgstr ""
+
+#: ../src/cpu/abstract_cpu.cpp:76
+msgid "Turbo Mode"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(HW)"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(OS)"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:91 ../src/cpu/intel_cpus.cpp:324
+#, c-format
+msgid " Core"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:85
+#, c-format
+msgid "cpu package %i"
+msgstr "सीपीयू पैकेज %i"
+
+#: ../src/cpu/cpu.cpp:86
+msgid "cpu package"
+msgstr "सीपीयू पैकेज"
+
+#: ../src/cpu/cpu.cpp:89 ../src/cpu/cpu.cpp:96
+#, fuzzy, c-format
+msgid "package-%i"
+msgstr "सीपीयू पैकेज %i"
+
+#: ../src/cpu/cpu.cpp:90
+msgid "cpu rapl package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:97
+msgid "dram rapl package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:471
+msgid "Processor Idle State Report"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:535 ../src/cpu/cpu.cpp:753
+msgid "Package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:566 ../src/cpu/cpu.cpp:775
+#, c-format
+msgid "Core %d"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:573
+#, c-format
+msgid "GPU %d"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:594
+#, fuzzy
+msgid "CPU"
+msgstr "सीपीयू उपयोग"
+
+#: ../src/cpu/cpu.cpp:676
+msgid "Processor Frequency Report"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:796
+#, fuzzy, c-format
+msgid "CPU %d"
+msgstr "सीपीयू उपयोग"
+
+#: ../src/cpu/cpu.cpp:997
+#, c-format
+msgid "cpu_idle event returned no state?\n"
+msgstr "cpu_idle की घटना ने किसी भी तरीके की स्थिति नहीं लोटायी है?\n"
+
+#: ../src/cpu/cpu.cpp:1012
+#, c-format
+msgid "power or cpu_frequency event returned no state?\n"
+msgstr ""
+
+#: ../src/cpu/cpu_linux.cpp:79
+msgid "C0 polling"
+msgstr "C0 मतदान"
+
+#: ../src/cpu/cpu_linux.cpp:242
+#, c-format
+msgid " CPU(OS) %i"
+msgstr ""
+
+#: ../src/cpu/cpu_linux.cpp:341 ../src/cpu/intel_cpus.cpp:651
+#, c-format
+msgid " CPU %i"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(HW)"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(OS)"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:104 ../src/cpu/intel_cpus.cpp:412
+#, c-format
+msgid " Package"
+msgstr ""
+
+#: ../src/cpu/intel_cpus.cpp:129
+#, c-format
+msgid "read_msr cpu%d 0x%llx : "
+msgstr ""
+
+#: ../src/cpu/intel_cpus.cpp:574
+msgid "C0 active"
+msgstr "C0 सक्रिय"
+
+#: ../src/cpu/intel_cpus.cpp:632
+#, c-format
+msgid "Average"
+msgstr ""
+
+#: ../src/cpu/intel_gpu.cpp:64
+#, c-format
+msgid " GPU "
+msgstr ""
+
+#: ../src/devices/ahci.cpp:154
+#, c-format
+msgid "SATA link: %s"
+msgstr "SATA कड़ी: %s"
+
+#: ../src/devices/ahci.cpp:156
+#, c-format
+msgid "SATA disk: %s"
+msgstr "SATA डिस्क: %s"
+
+#: ../src/devices/ahci.cpp:374
+msgid "AHCI ALPM Residency Statistics - Not supported on this macine"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:389
+msgid "Link"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:390
+#, fuzzy
+msgid "Active"
+msgstr "C0 सक्रिय"
+
+#: ../src/devices/ahci.cpp:391
+msgid "Partial"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:392
+msgid "Slumber"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:393
+msgid "Devslp"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:399
+msgid "AHCI ALPM Residency Statistics"
+msgstr ""
+
+#: ../src/devices/alsa.cpp:77
+#, c-format
+msgid "Audio codec %s: %s (%s)"
+msgstr "श्रव्य कोडेक %s: %s (%s)"
+
+#: ../src/devices/alsa.cpp:79 ../src/devices/alsa.cpp:81
+#, c-format
+msgid "Audio codec %s: %s"
+msgstr "श्रव्य कोडेक %s: %s"
+
+#: ../src/devices/devfreq.cpp:261
+#, fuzzy
+msgid "Device Freq stats"
+msgstr " उपकरण आँकड़े"
+
+#: ../src/devices/devfreq.cpp:279
+msgid " Devfreq is not enabled"
+msgstr ""
+
+#: ../src/devices/devfreq.cpp:284
+msgid " No devfreq devices available"
+msgstr ""
+
+#: ../src/devices/device.cpp:172 ../src/process/do_process.cpp:831
+#, c-format
+msgid "The battery reports a discharge rate of %sW\n"
+msgstr ""
+"बैटरी रिपोर्ट कर रही हैं %sW की चुकौती दर\n"
+"\n"
+
+#: ../src/devices/device.cpp:174 ../src/process/do_process.cpp:833
+#, c-format
+msgid "The power consumed was %sJ\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:180
+#, c-format
+msgid "System baseline power is estimated at %sW\n"
+msgstr "प्रणाली आधारभूत शक्ति का अनुमान %sW से लगाया जा चूका हैं\n"
+
+#: ../src/devices/device.cpp:187
+msgid "Power est. Usage Device name\n"
+msgstr "शक्ति अनुमानित उपयोग उपकरण का नाम \n"
+
+#: ../src/devices/device.cpp:189
+msgid " Usage Device name\n"
+msgstr "खपत उपकरण नाम\n"
+
+#: ../src/devices/device.cpp:256
+#, fuzzy
+msgid "The battery reports a discharge rate of: "
+msgstr ""
+"बैटरी रिपोर्ट कर रही हैं %sW की चुकौती दर\n"
+"\n"
+
+#: ../src/devices/device.cpp:261
+msgid "The power consumed was : "
+msgstr ""
+
+#: ../src/devices/device.cpp:268
+#, fuzzy
+msgid "The system baseline power is estimated at: "
+msgstr "प्रणाली आधारभूत शक्ति का अनुमान %sW से लगाया जा चूका हैं\n"
+
+#: ../src/devices/device.cpp:277 ../src/process/do_process.cpp:850
+#: ../src/process/do_process.cpp:852 ../src/process/do_process.cpp:926
+#: ../src/process/do_process.cpp:1077
+msgid "Usage"
+msgstr "खपत"
+
+#: ../src/devices/device.cpp:278
+#, fuzzy
+msgid "Device Name"
+msgstr " उपकरण आँकड़े"
+
+#: ../src/devices/device.cpp:280 ../src/process/do_process.cpp:935
+#: ../src/process/do_process.cpp:1082
+msgid "PW Estimate"
+msgstr ""
+
+#. Report Output
+#: ../src/devices/device.cpp:317
+msgid "Device Power Report"
+msgstr ""
+
+#: ../src/devices/network.cpp:177
+#, c-format
+msgid "Network interface: %s (%s)"
+msgstr "संजाल अंतराफलक: %s (%s)"
+
+#: ../src/devices/rfkill.cpp:65 ../src/devices/rfkill.cpp:69
+#, c-format
+msgid "Radio device: %s"
+msgstr "रेडियो उपकरण: %s"
+
+#: ../src/devices/runtime_pm.cpp:216
+#, c-format
+msgid "I2C %s (%s): %s"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216 ../src/tuning/tuningi2c.cpp:57
+#: ../src/tuning/tuningi2c.cpp:59
+msgid "Adapter"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216 ../src/devlist.cpp:331
+#: ../src/tuning/tuningi2c.cpp:57 ../src/tuning/tuningi2c.cpp:59
+#, fuzzy
+msgid "Device"
+msgstr " उपकरण आँकड़े"
+
+#: ../src/devices/runtime_pm.cpp:241
+#, c-format
+msgid "PCI Device: %s"
+msgstr "पीसीआई उपकरण: %s"
+
+#: ../src/devices/usb.cpp:51 ../src/devices/usb.cpp:96
+#: ../src/devices/usb.cpp:98
+#, c-format
+msgid "USB device: %s"
+msgstr "यूएसबी उपकरण: %s "
+
+#: ../src/devices/usb.cpp:94
+#, c-format
+msgid "USB device: %s (%s)"
+msgstr "यूएसबी उपकरण: %s (%s)"
+
+#: ../src/devlist.cpp:330
+msgid "Process"
+msgstr ""
+
+#. Report Output
+#. No div attribute here inherits from device power report
+#: ../src/devlist.cpp:347
+msgid "Process Device Activity"
+msgstr ""
+
+#: ../src/display.cpp:70
+msgid "Overview"
+msgstr " विवरण"
+
+#: ../src/display.cpp:71
+msgid "Idle stats"
+msgstr "निष्क्रिय आँकड़े"
+
+#: ../src/display.cpp:72
+msgid "Frequency stats"
+msgstr " आवृति आँकड़े"
+
+#: ../src/display.cpp:73
+msgid "Device stats"
+msgstr " उपकरण आँकड़े"
+
+#: ../src/display.cpp:131
+msgid "Exit"
+msgstr "बाहर निकलें"
+
+#: ../src/display.cpp:132
+msgid "Navigate"
+msgstr ""
+
+#: ../src/lib.cpp:288
+#, c-format
+msgid "%7sW"
+msgstr "%7sW"
+
+#: ../src/lib.cpp:291
+#, c-format
+msgid " 0 mW"
+msgstr "0 मेगावाट"
+
+#: ../src/lib.cpp:410
+msgid "PS/2 Touchpad / Keyboard / Mouse"
+msgstr "पीएस/2 टचपैड / कुंजीपटल / माउस "
+
+#: ../src/lib.cpp:411
+msgid "SATA controller"
+msgstr "SATA नियंत्रक"
+
+#: ../src/lib.cpp:412
+msgid "Intel built in USB hub"
+msgstr "इंटेल में निर्मित यूएसबी हब "
+
+#: ../src/lib.cpp:467
+#, c-format
+msgid "glob returned GLOB_NOSPACE\n"
+msgstr ""
+
+#: ../src/lib.cpp:471
+#, c-format
+msgid "glob returned GLOB_ABORTED\n"
+msgstr ""
+
+#: ../src/lib.cpp:475
+#, c-format
+msgid "glob returned GLOB_NOMATCH\n"
+msgstr ""
+
+#: ../src/lib.cpp:513 ../src/lib.cpp:549
+#, c-format
+msgid ""
+"Model-specific registers (MSR)\t\t\t not found (try enabling "
+"CONFIG_X86_MSR).\n"
+msgstr ""
+
+#: ../src/main.cpp:103
+#, fuzzy, c-format
+msgid "PowerTOP version "
+msgstr "PowerTOP संस्करण"
+
+#: ../src/main.cpp:109
+msgid "Set refresh time out"
+msgstr "ताज़ा करने के टाइम-आउट को नियत करें"
+
+#: ../src/main.cpp:122
+msgid "Usage: powertop [OPTIONS]"
+msgstr "खपत: पॉवरटॉप [विकल्प]"
+
+#: ../src/main.cpp:123
+msgid "sets all tunable options to their GOOD setting"
+msgstr ""
+
+#: ../src/main.cpp:124
+msgid "runs powertop in calibration mode"
+msgstr "पॉवरटॉप को केलिब्रेसन मोड में चलाता हैं"
+
+#: ../src/main.cpp:125 ../src/main.cpp:128
+msgid "[=filename]"
+msgstr ""
+
+#: ../src/main.cpp:125
+msgid "generate a csv report"
+msgstr "एक सीएसवी रिपोर्ट उत्पन्न करना"
+
+#: ../src/main.cpp:126
+msgid "run in \"debug\" mode"
+msgstr "\"डिबग\" मोड में चलाये"
+
+#: ../src/main.cpp:127
+msgid "[=devnode]"
+msgstr "[=devnode]"
+
+#: ../src/main.cpp:127
+msgid "uses an Extech Power Analyzer for measurements"
+msgstr "माप के लिए एक Extech पावर विश्लेषक का उपयोग करता है"
+
+#: ../src/main.cpp:128
+msgid "generate a html report"
+msgstr "एक एचटीएमएल रिपोर्ट उत्पन्न करना"
+
+#: ../src/main.cpp:129
+msgid "[=iterations] number of times to run each test"
+msgstr "[=संतृप्ति] प्रत्येक परीक्षा को चलाने की संख्या"
+
+#: ../src/main.cpp:130
+msgid "suppress stderr output"
+msgstr ""
+
+#: ../src/main.cpp:131 ../src/main.cpp:132
+msgid "[=seconds]"
+msgstr "[=सेकण्ड्स]"
+
+#: ../src/main.cpp:131
+msgid "interval for power consumption measurement"
+msgstr ""
+
+#: ../src/main.cpp:132
+msgid "generate a report for 'x' seconds"
+msgstr "'x' सेकंड के लिए एक रिपोर्ट उत्पन्न करना"
+
+#: ../src/main.cpp:133
+msgid "[=workload]"
+msgstr ""
+
+#: ../src/main.cpp:133
+msgid "file to execute for workload"
+msgstr ""
+
+#: ../src/main.cpp:134
+msgid "print version information"
+msgstr "संस्करण जानकारी को छापें"
+
+#: ../src/main.cpp:135
+msgid "print this help menu"
+msgstr "इस सहायक मेन्यू को छापें"
+
+#: ../src/main.cpp:137
+#, fuzzy
+msgid "For more help please refer to the 'man 8 powertop'"
+msgstr "अधिक सहायता के लिए कृपया रीडमी देखें"
+
+#: ../src/main.cpp:232
+#, c-format
+msgid "Unknown issue running workload!\n"
+msgstr ""
+
+#: ../src/main.cpp:289
+msgid "PowerTOP is out of memory. PowerTOP is Aborting"
+msgstr "PowerTOP स्मृति से बाहर है. PowerTOP रद्द कर रहा है"
+
+#. one to warm up everything
+#: ../src/main.cpp:297
+#, c-format
+msgid "Preparing to take measurements\n"
+msgstr "माप लेने के लिए तैयार होना \n"
+
+#: ../src/main.cpp:302
+#, c-format
+msgid "Taking %d measurement(s) for a duration of %d second(s) each.\n"
+msgstr "%d का माप लिया जा रहा है प्रत्येक %d सेकण्ड की अवधि के लिए.\n"
+
+#: ../src/main.cpp:304
+#, c-format
+msgid "Measuring workload %s.\n"
+msgstr ""
+
+#: ../src/main.cpp:329
+#, c-format
+msgid "PowerTOP "
+msgstr "PowerTOP"
+
+#: ../src/main.cpp:330 ../src/main.cpp:380
+#, c-format
+msgid "exiting...\n"
+msgstr "बाहर हो रहे है ...\n"
+
+#: ../src/main.cpp:364
+#, c-format
+msgid "modprobe cpufreq_stats failed"
+msgstr ""
+
+#: ../src/main.cpp:367
+#, c-format
+msgid "modprobe msr failed"
+msgstr ""
+
+#: ../src/main.cpp:379 ../src/main.cpp:383
+#, c-format
+msgid "Failed to mount debugfs!\n"
+msgstr "Debugfs को आरोहित करने में असफल रहे!\n"
+
+#: ../src/main.cpp:384
+#, c-format
+msgid "Should still be able to auto tune...\n"
+msgstr ""
+
+#: ../src/main.cpp:466
+#, c-format
+msgid "Invalid CSV filename\n"
+msgstr ""
+
+#: ../src/main.cpp:482
+#, c-format
+msgid "Invalid HTML filename\n"
+msgstr ""
+
+#: ../src/main.cpp:491
+#, c-format
+msgid "Quiet mode failed!\n"
+msgstr ""
+
+#: ../src/main.cpp:559
+msgid "Leaving PowerTOP"
+msgstr "PowerTOP को छोड़ना"
+
+#: ../src/parameters/persistent.cpp:46 ../src/parameters/persistent.cpp:155
+msgid "Cannot save to file"
+msgstr ""
+
+#: ../src/parameters/persistent.cpp:89 ../src/parameters/persistent.cpp:180
+msgid "Cannot load from file"
+msgstr ""
+
+#. '%i" is for count, do not translate
+#: ../src/parameters/persistent.cpp:138
+#, c-format
+msgid "Loaded %i prior measurements\n"
+msgstr "%i पूर्व माप लोड किया जा चूका हैं \n"
+
+#: ../src/parameters/persistent.cpp:181
+msgid ""
+"File will be loaded after taking minimum number of measurement(s) with "
+"battery only \n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:115
+#, c-format
+msgid ""
+"Too many open files, please increase the limit of open file descriptors.\n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:117
+#, c-format
+msgid "PowerTOP %s needs the kernel to support the 'perf' subsystem\n"
+msgstr "PowerTOP %s को 'perf' उपतंत्र को समर्थन देने के लिए kernel की जरुरत होती है \n"
+
+#: ../src/perf/perf.cpp:118
+#, c-format
+msgid "as well as support for trace points in the kernel:\n"
+msgstr "तथा kernel के ट्रेस अंक को समर्थन:\n"
+
+#: ../src/process/do_process.cpp:819
+#, c-format
+msgid ""
+"Estimated power: %5.1f Measured power: %5.1f Sum: %5.1f\n"
+"\n"
+msgstr "अनुमानित शक्ति: %5.1f मापित शक्ति: %5.1f जोड़: %5.1f\n"
+
+#: ../src/process/do_process.cpp:838
+#, c-format
+msgid "The estimated remaining time is %i hours, %i minutes\n"
+msgstr "अनुमानित शेष समय %i घंटे, %i मिनट हैं \n"
+
+#: ../src/process/do_process.cpp:846
+msgid "Summary"
+msgstr "संक्षेप"
+
+#: ../src/process/do_process.cpp:846
+msgid "wakeups/second"
+msgstr "वेकअप/सेकेंड"
+
+#: ../src/process/do_process.cpp:846
+msgid "GPU ops/seconds"
+msgstr "GPU ऑप्स/सेकण्ड्स"
+
+#: ../src/process/do_process.cpp:846
+msgid "VFS ops/sec and"
+msgstr "VFS ऑप्स/सेकंड और"
+
+#: ../src/process/do_process.cpp:846
+msgid "CPU use"
+msgstr "सीपीयू उपयोग"
+
+#: ../src/process/do_process.cpp:850
+msgid "Power est."
+msgstr "शक्ति अनुमानित."
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:1078
+msgid "Events/s"
+msgstr "घटना/सेकेंड"
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:931 ../src/process/do_process.cpp:1079
+msgid "Category"
+msgstr "श्रेणी"
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:932 ../src/process/do_process.cpp:1080
+#: ../src/tuning/tuning.cpp:242 ../src/tuning/tuning.cpp:270
+#: ../src/tuning/tuning.cpp:288 ../src/wakeup/waketab.cpp:155
+msgid "Description"
+msgstr "विवरण"
+
+#: ../src/process/do_process.cpp:927
+msgid "Wakeups/s"
+msgstr "वेकअप/सेकेंड"
+
+#: ../src/process/do_process.cpp:928
+msgid "GPU ops/s"
+msgstr "GPU ऑप्स/सेकेंड"
+
+#: ../src/process/do_process.cpp:929
+msgid "Disk IO/s"
+msgstr "डिस्क IO/सेकेंड"
+
+#: ../src/process/do_process.cpp:930
+msgid "GFX Wakeups/s"
+msgstr "GFX वेकअप/सेकेंड"
+
+#: ../src/process/do_process.cpp:1017
+msgid "Overview of Software Power Consumers"
+msgstr "सॉफ्टवेयर बिजली उपभोक्ताओं का विवरण"
+
+#: ../src/process/do_process.cpp:1057
+msgid "Target:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1058
+msgid "1 units/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1059
+msgid "System: "
+msgstr ""
+
+#: ../src/process/do_process.cpp:1061
+#, fuzzy
+msgid " wakeup/s"
+msgstr "वेकअप/सेकेंड"
+
+#: ../src/process/do_process.cpp:1062
+msgid "CPU: "
+msgstr ""
+
+#: ../src/process/do_process.cpp:1064
+#, fuzzy, c-format
+msgid "% usage"
+msgstr "खपत"
+
+#: ../src/process/do_process.cpp:1065
+msgid "GPU:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1067 ../src/process/do_process.cpp:1073
+#, fuzzy
+msgid " ops/s"
+msgstr "GPU ऑप्स/सेकेंड"
+
+#: ../src/process/do_process.cpp:1068
+msgid "GFX:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1070
+#, fuzzy
+msgid " wakeups/s"
+msgstr "वेकअप/सेकेंड"
+
+#: ../src/process/do_process.cpp:1071
+msgid "VFS:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1139
+#, fuzzy
+msgid "Top 10 Power Consumers"
+msgstr "सॉफ्टवेयर बिजली उपभोक्ताओं का विवरण"
+
+#: ../src/report/report.cpp:122
+#, fuzzy
+msgid "PowerTOP Version"
+msgstr "PowerTOP संस्करण"
+
+#: ../src/report/report.cpp:131
+#, fuzzy
+msgid "Kernel Version"
+msgstr "PowerTOP संस्करण"
+
+#: ../src/report/report.cpp:135
+msgid "System Name"
+msgstr ""
+
+#: ../src/report/report.cpp:142
+msgid "CPU Information"
+msgstr ""
+
+#: ../src/report/report.cpp:154
+msgid "OS Information"
+msgstr ""
+
+#: ../src/report/report.cpp:161
+#, fuzzy
+msgid "System Information"
+msgstr "संस्करण जानकारी को छापें"
+
+#: ../src/report/report.cpp:195
+#, fuzzy, c-format
+msgid "Cannot open output file %s (%s)\n"
+msgstr "अस्थायी फ़ाइल नहीं बना सकते\n"
+
+#: ../src/report/report.cpp:211
+#, c-format
+msgid "PowerTOP outputing using base filename %s\n"
+msgstr ""
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:49
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+msgid "Good"
+msgstr "अच्छा"
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:50
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+msgid "Bad"
+msgstr "बुरा"
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:51
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+#: ../src/wakeup/wakeup.cpp:50
+msgid "Unknown"
+msgstr "अनजान"
+
+#: ../src/tuning/bluetooth.cpp:48
+#, c-format
+msgid "Bluetooth device interface status"
+msgstr "ब्लूटूथ उपकरण अंतराफलक की स्थिति"
+
+#: ../src/tuning/ethernet.cpp:54 ../src/wakeup/wakeup_ethernet.cpp:51
+#, c-format
+msgid "Wake-on-lan status for device %s"
+msgstr "स्थानीय क्षेत्र तंत्र की स्थिति को उपकरण %s के लिए जागृत करना "
+
+#: ../src/tuning/runtime.cpp:48
+#, c-format
+msgid "Runtime PM for %s device %s"
+msgstr "%s उपकरण %s के लिए PM कार्यावधि करे "
+
+#: ../src/tuning/runtime.cpp:50
+#, c-format
+msgid "%s device %s has no runtime power management"
+msgstr "%s उपकरण %s के पास कार्यावधि शक्ति प्रबंधन नहीं हैं "
+
+#: ../src/tuning/runtime.cpp:74
+#, c-format
+msgid "PCI Device %s has no runtime power management"
+msgstr "पीसीआई उपकरण %s के पास कार्यावधि शक्ति प्रबंधन नहीं हैं "
+
+#: ../src/tuning/runtime.cpp:76
+#, c-format
+msgid "Runtime PM for PCI Device %s"
+msgstr "पीसीआई उपकरण %s के लिए PM कार्यावधि करे"
+
+#: ../src/tuning/tuning.cpp:62
+msgid "Enable Audio codec power management"
+msgstr "श्रव्य कोडेक ऊर्जा प्रबंधन को सक्षम बनाए"
+
+#: ../src/tuning/tuning.cpp:63
+msgid "NMI watchdog should be turned off"
+msgstr "एनएमआई पर निगरानी को बंद कर दिया जाएँ"
+
+#: ../src/tuning/tuning.cpp:64
+msgid "Power Aware CPU scheduler"
+msgstr "पावर अवगत सीपीयू अनुसूचक "
+
+#: ../src/tuning/tuning.cpp:65
+msgid "VM writeback timeout"
+msgstr "VM को प्रतिलेखन करने का समय समाप्त "
+
+#: ../src/tuning/tuning.cpp:81
+msgid "Tunables"
+msgstr "ट्यून करने योग्य"
+
+#: ../src/tuning/tuning.cpp:81
+msgid " <ESC> Exit | <Enter> Toggle tunable | <r> Window refresh"
+msgstr "<ESC> बाहर निकलें | <Enter> टॉगल tunable | <r> विंडो ताजा करे "
+
+#: ../src/tuning/tuning.cpp:243 ../src/wakeup/waketab.cpp:156
+msgid "Script"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:257
+msgid "Software Settings in Need of Tuning"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:276
+msgid "Untunable Software Issues"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:300
+msgid "Optimal Tuned Software Settings"
+msgstr ""
+
+#: ../src/tuning/tuningi2c.cpp:57
+#, fuzzy, c-format
+msgid "Runtime PM for I2C %s %s (%s)"
+msgstr "%s उपकरण %s के लिए PM कार्यावधि करे "
+
+#: ../src/tuning/tuningi2c.cpp:59
+#, fuzzy, c-format
+msgid "I2C %s %s has no runtime power management"
+msgstr "%s उपकरण %s के पास कार्यावधि शक्ति प्रबंधन नहीं हैं "
+
+#: ../src/tuning/tuningsysfs.cpp:123
+#, fuzzy, c-format
+msgid "Enable SATA link power management for %s"
+msgstr "श्रव्य कोडेक ऊर्जा प्रबंधन को सक्षम बनाए"
+
+#: ../src/tuning/tuningusb.cpp:54
+#, c-format
+msgid "Autosuspend for unknown USB device %s (%s:%s)"
+msgstr "अज्ञात यूएसबी उपकरण के लिए स्वतःस्थगित होना %s (%s:%s) "
+
+#: ../src/tuning/tuningusb.cpp:71 ../src/tuning/tuningusb.cpp:73
+#: ../src/tuning/tuningusb.cpp:75
+#, c-format
+msgid "Autosuspend for USB device %s [%s]"
+msgstr "यूएसबी उपकरण के लिए स्वतःस्थगित होना %s [%s]"
+
+#: ../src/tuning/wifi.cpp:48
+#, c-format
+msgid "Wireless Power Saving for interface %s"
+msgstr "बेतार संप्रेषण शक्ति बचत के लिए अंतराफलक %s"
+
+#: ../src/wakeup/waketab.cpp:42
+#, fuzzy
+msgid "WakeUp"
+msgstr "वेकअप/सेकेंड"
+
+#: ../src/wakeup/waketab.cpp:42
+#, fuzzy
+msgid " <ESC> Exit | <Enter> Toggle wakeup | <r> Window refresh"
+msgstr "<ESC> बाहर निकलें | <Enter> टॉगल tunable | <r> विंडो ताजा करे "
+
+#. Report Output
+#: ../src/wakeup/waketab.cpp:170
+#, fuzzy
+msgid "Wake status of the devices"
+msgstr "स्थानीय क्षेत्र तंत्र की स्थिति को उपकरण %s के लिए जागृत करना "
+
+#: ../src/wakeup/wakeup.cpp:48 ../src/wakeup/wakeup_ethernet.cpp:47
+#: ../src/wakeup/wakeup_usb.cpp:47
+#, fuzzy
+msgid "Enable"
+msgstr "ट्यून करने योग्य"
+
+#: ../src/wakeup/wakeup.cpp:49 ../src/wakeup/wakeup_ethernet.cpp:47
+#: ../src/wakeup/wakeup_usb.cpp:47
+msgid "Disable"
+msgstr ""
+
+#: ../src/wakeup/wakeup_usb.cpp:51
+#, fuzzy, c-format
+msgid "Wake status for USB device %s"
+msgstr "स्थानीय क्षेत्र तंत्र की स्थिति को उपकरण %s के लिए जागृत करना "
+
+#~ msgid "Actual"
+#~ msgstr "वास्तविक"
+
+#~ msgid "Power Consumption Summary"
+#~ msgstr "विद्युत उपभोग सारांश"
+
+#~ msgid "GPU ops/second"
+#~ msgstr "GPU ऑप्स/सेकेंड"
+
+#~ msgid "VFS ops/sec"
+#~ msgstr "VFS ऑप्स/सेकेंड"
+
+#~ msgid "GFX wakes/sec and"
+#~ msgstr "GFX वेक/सेकेंड और"
+
+#~ msgid "Using 'ondemand' cpufreq governor"
+#~ msgstr "'ondemand' सीपीयू आवृति नियन्त्रक का उपयोग"
+
+#~ msgid "[=FILENAME]"
+#~ msgstr "[=फ़ाइलनाम]"
diff --git a/po/hu_HU.po b/po/hu_HU.po
new file mode 100644
index 0000000..e9d985e
--- /dev/null
+++ b/po/hu_HU.po
@@ -0,0 +1,1002 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Intel Corporation
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# ceferron <chris.e.ferron@linux.intel.com>, 2012
+# Márton Németh <nemeth.marton@gmail.com>, 2012
+# Márton Németh <nm127@freemail.hu>, 2012
+# Zoltan Hoppár <hopparz@gmail.com>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: PowerTOP\n"
+"Report-Msgid-Bugs-To: \"powertop@lists.01.org\"\n"
+"POT-Creation-Date: 2022-09-29 04:45-0700\n"
+"PO-Revision-Date: 2013-11-05 08:40+0000\n"
+"Last-Translator: Margie Foster <margie@linux.intel.com>\n"
+"Language-Team: Hungarian (Hungary) (http://www.transifex.com/projects/p/"
+"PowerTOP/language/hu_HU/)\n"
+"Language: hu_HU\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/calibrate/calibrate.cpp:238
+#, c-format
+msgid "Cannot create temp file\n"
+msgstr "Nem tudok létrehozni ideiglenes fájlt\n"
+
+#: src/calibrate/calibrate.cpp:258
+#, c-format
+msgid "Calibrating: CPU usage on %i threads\n"
+msgstr "Kalibrálás: CPU használtság %i szálon\n"
+
+#: src/calibrate/calibrate.cpp:273
+#, c-format
+msgid "Calibrating: CPU wakeup power consumption\n"
+msgstr "Kalibrálás: CPU felébredési teljesítményfelvétel\n"
+
+#: src/calibrate/calibrate.cpp:290
+#, c-format
+msgid "Calibrating USB devices\n"
+msgstr "USB eszközök kalibrálása\n"
+
+#: src/calibrate/calibrate.cpp:292 src/calibrate/calibrate.cpp:309
+#: src/calibrate/calibrate.cpp:317 src/calibrate/calibrate.cpp:334
+#, c-format
+msgid ".... device %s \n"
+msgstr ".... %s eszköz \n"
+
+#: src/calibrate/calibrate.cpp:307
+#, c-format
+msgid "Calibrating radio devices\n"
+msgstr "Rádiós eszközök kalibrálása\n"
+
+#: src/calibrate/calibrate.cpp:331
+#, c-format
+msgid "Calibrating backlight\n"
+msgstr "Háttérvilágítás kalibrálása\n"
+
+#: src/calibrate/calibrate.cpp:355 src/calibrate/calibrate.cpp:365
+#, c-format
+msgid "Calibrating idle\n"
+msgstr "Üresjárat kalibrálása\n"
+
+#: src/calibrate/calibrate.cpp:378
+#, c-format
+msgid "Calibrating: disk usage \n"
+msgstr "Kalibrálás: lemezhasználat \n"
+
+#: src/calibrate/calibrate.cpp:403
+msgid "Starting PowerTOP power estimate calibration \n"
+msgstr "PowerTop teljesítménybecslés kalibrálás indítása \n"
+
+#: src/calibrate/calibrate.cpp:426
+msgid "Finishing PowerTOP power estimate calibration \n"
+msgstr "PowerTop teljesítménybecslés-kalibrálás befejezése \n"
+
+#: src/calibrate/calibrate.cpp:430
+#, c-format
+msgid "Parameters after calibration:\n"
+msgstr "Paraméterek a kalibrálás után:\n"
+
+#: src/cpu/abstract_cpu.cpp:74
+msgid "Idle"
+msgstr ""
+
+#: src/cpu/abstract_cpu.cpp:76
+msgid "Turbo Mode"
+msgstr ""
+
+#: src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(HW)"
+msgstr ""
+
+#: src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(OS)"
+msgstr ""
+
+#: src/cpu/cpu_core.cpp:91 src/cpu/intel_cpus.cpp:367
+#, c-format
+msgid " Core"
+msgstr ""
+
+#: src/cpu/cpu.cpp:85
+#, c-format
+msgid "cpu package %i"
+msgstr "CPU tok %i"
+
+#: src/cpu/cpu.cpp:86
+msgid "cpu package"
+msgstr "CPU tok"
+
+#: src/cpu/cpu.cpp:89 src/cpu/cpu.cpp:96
+#, fuzzy, c-format
+msgid "package-%i"
+msgstr "Csomag %i"
+
+#: src/cpu/cpu.cpp:90
+msgid "cpu rapl package"
+msgstr ""
+
+#: src/cpu/cpu.cpp:97
+msgid "dram rapl package"
+msgstr ""
+
+#: src/cpu/cpu.cpp:471
+msgid "Processor Idle State Report"
+msgstr ""
+
+#: src/cpu/cpu.cpp:535 src/cpu/cpu.cpp:761
+msgid "Package"
+msgstr ""
+
+#: src/cpu/cpu.cpp:572 src/cpu/cpu.cpp:783
+#, fuzzy, c-format
+msgid "Core %d"
+msgstr "Mag %i"
+
+#: src/cpu/cpu.cpp:579
+#, fuzzy, c-format
+msgid "GPU %d"
+msgstr "GPU %i"
+
+#: src/cpu/cpu.cpp:602
+#, fuzzy
+msgid "CPU"
+msgstr "CPU %i"
+
+#: src/cpu/cpu.cpp:684
+msgid "Processor Frequency Report"
+msgstr ""
+
+#: src/cpu/cpu.cpp:804
+#, fuzzy, c-format
+msgid "CPU %d"
+msgstr "CPU %i"
+
+#: src/cpu/cpu.cpp:1005
+#, c-format
+msgid "cpu_idle event returned no state?\n"
+msgstr "a CPU üresjáratesemény nem adott vissza állapotot?\n"
+
+#: src/cpu/cpu.cpp:1020
+#, c-format
+msgid "power or cpu_frequency event returned no state?\n"
+msgstr ""
+
+#: src/cpu/cpu_linux.cpp:79
+msgid "C0 polling"
+msgstr "C0 ciklikus lekérdezés"
+
+#: src/cpu/cpu_linux.cpp:242
+#, c-format
+msgid " CPU(OS) %i"
+msgstr ""
+
+#: src/cpu/cpu_linux.cpp:341 src/cpu/intel_cpus.cpp:733
+#, c-format
+msgid " CPU %i"
+msgstr ""
+
+#: src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(HW)"
+msgstr ""
+
+#: src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(OS)"
+msgstr ""
+
+#: src/cpu/cpu_package.cpp:104 src/cpu/intel_cpus.cpp:498
+#, c-format
+msgid " Package"
+msgstr ""
+
+#: src/cpu/intel_cpus.cpp:152
+#, c-format
+msgid "read_msr cpu%d 0x%llx : "
+msgstr ""
+
+#: src/cpu/intel_cpus.cpp:656
+msgid "C0 active"
+msgstr "C0 aktív"
+
+#: src/cpu/intel_cpus.cpp:714
+#, c-format
+msgid "Average"
+msgstr ""
+
+#: src/cpu/intel_gpu.cpp:64
+#, fuzzy, c-format
+msgid " GPU "
+msgstr "GPU %i"
+
+#: src/devices/ahci.cpp:154
+#, c-format
+msgid "SATA link: %s"
+msgstr "SATA kapcsolat: %s"
+
+#: src/devices/ahci.cpp:156
+#, c-format
+msgid "SATA disk: %s"
+msgstr "SATA lemez: %s"
+
+#: src/devices/ahci.cpp:374
+msgid "AHCI ALPM Residency Statistics - Not supported on this macine"
+msgstr ""
+
+#: src/devices/ahci.cpp:389
+msgid "Link"
+msgstr ""
+
+#: src/devices/ahci.cpp:390
+#, fuzzy
+msgid "Active"
+msgstr "C0 aktív"
+
+#: src/devices/ahci.cpp:391
+msgid "Partial"
+msgstr ""
+
+#: src/devices/ahci.cpp:392
+msgid "Slumber"
+msgstr ""
+
+#: src/devices/ahci.cpp:393
+msgid "Devslp"
+msgstr ""
+
+#: src/devices/ahci.cpp:399
+msgid "AHCI ALPM Residency Statistics"
+msgstr ""
+
+#: src/devices/alsa.cpp:77
+#, c-format
+msgid "Audio codec %s: %s (%s)"
+msgstr "Hangkodek %s: %s (%s)"
+
+#: src/devices/alsa.cpp:79 src/devices/alsa.cpp:81
+#, c-format
+msgid "Audio codec %s: %s"
+msgstr "Hangkodek %s: %s"
+
+#: src/devices/devfreq.cpp:260
+#, fuzzy
+msgid "Device Freq stats"
+msgstr "Eszközstatisztika"
+
+#: src/devices/devfreq.cpp:278
+msgid " Devfreq is not enabled"
+msgstr ""
+
+#: src/devices/devfreq.cpp:283
+msgid " No devfreq devices available"
+msgstr ""
+
+#: src/devices/device.cpp:172 src/process/do_process.cpp:831
+#, c-format
+msgid "The battery reports a discharge rate of %sW\n"
+msgstr "Az akkumulátor %sW kisülési sebességet jelent\n"
+
+#: src/devices/device.cpp:174 src/process/do_process.cpp:833
+#, c-format
+msgid "The energy consumed was %sJ\n"
+msgstr ""
+
+#: src/devices/device.cpp:180
+#, c-format
+msgid "System baseline power is estimated at %sW\n"
+msgstr "%sW a rendszer becsült alapteljesítménye\n"
+
+#: src/devices/device.cpp:187
+msgid "Power est. Usage Device name\n"
+msgstr "Becsült telj. Használat Eszköz név\n"
+
+#: src/devices/device.cpp:189
+msgid " Usage Device name\n"
+msgstr " Használat Eszköz név\n"
+
+#: src/devices/device.cpp:256
+#, fuzzy
+msgid "The battery reports a discharge rate of: "
+msgstr "Az akkumulátor %sW kisülési sebességet jelent\n"
+
+#: src/devices/device.cpp:261
+msgid "The energy consumed was : "
+msgstr ""
+
+#: src/devices/device.cpp:268
+#, fuzzy
+msgid "The system baseline power is estimated at: "
+msgstr "%sW a rendszer becsült alapteljesítménye\n"
+
+#: src/devices/device.cpp:277 src/process/do_process.cpp:850
+#: src/process/do_process.cpp:852 src/process/do_process.cpp:926
+#: src/process/do_process.cpp:1077
+msgid "Usage"
+msgstr "Használat"
+
+#: src/devices/device.cpp:278
+#, fuzzy
+msgid "Device Name"
+msgstr "Eszközstatisztika"
+
+#: src/devices/device.cpp:280 src/process/do_process.cpp:935
+#: src/process/do_process.cpp:1082
+msgid "PW Estimate"
+msgstr ""
+
+#: src/devices/device.cpp:317
+msgid "Device Power Report"
+msgstr ""
+
+#: src/devices/network.cpp:177
+#, c-format
+msgid "Network interface: %s (%s)"
+msgstr "Hálózati csatoló: %s (%s)"
+
+#: src/devices/rfkill.cpp:65 src/devices/rfkill.cpp:69
+#, c-format
+msgid "Radio device: %s"
+msgstr "Rádiós eszköz: %s"
+
+#: src/devices/runtime_pm.cpp:216
+#, c-format
+msgid "I2C %s (%s): %s"
+msgstr ""
+
+#: src/devices/runtime_pm.cpp:216 src/tuning/tuningi2c.cpp:57
+#: src/tuning/tuningi2c.cpp:59
+msgid "Adapter"
+msgstr ""
+
+#: src/devices/runtime_pm.cpp:216 src/devlist.cpp:331
+#: src/tuning/tuningi2c.cpp:57 src/tuning/tuningi2c.cpp:59
+#, fuzzy
+msgid "Device"
+msgstr "Eszközstatisztika"
+
+#: src/devices/runtime_pm.cpp:241
+#, c-format
+msgid "PCI Device: %s"
+msgstr "PCI eszköz: %s"
+
+#: src/devices/usb.cpp:51 src/devices/usb.cpp:96 src/devices/usb.cpp:98
+#, c-format
+msgid "USB device: %s"
+msgstr "USB eszköz: %s"
+
+#: src/devices/usb.cpp:94
+#, c-format
+msgid "USB device: %s (%s)"
+msgstr "USB eszköz: %s (%s)"
+
+#: src/devlist.cpp:330
+msgid "Process"
+msgstr ""
+
+#: src/devlist.cpp:347
+msgid "Process Device Activity"
+msgstr ""
+
+#: src/display.cpp:70
+msgid "Overview"
+msgstr "Áttekintés"
+
+#: src/display.cpp:71
+msgid "Idle stats"
+msgstr "Üresjárat-statisztika"
+
+#: src/display.cpp:72
+msgid "Frequency stats"
+msgstr "Frekvenciastatisztika"
+
+#: src/display.cpp:73
+msgid "Device stats"
+msgstr "Eszközstatisztika"
+
+#: src/display.cpp:131
+msgid "Exit"
+msgstr "Kilépés"
+
+#: src/display.cpp:132
+msgid "Navigate"
+msgstr ""
+
+#: src/lib.cpp:288
+#, c-format
+msgid "%7sW"
+msgstr "%7sW"
+
+#: src/lib.cpp:291
+#, c-format
+msgid " 0 mW"
+msgstr " 0 mW"
+
+#: src/lib.cpp:410
+msgid "PS/2 Touchpad / Keyboard / Mouse"
+msgstr "PS/2 tapipad / billentyűzet / egér"
+
+#: src/lib.cpp:411
+msgid "SATA controller"
+msgstr "SATA vezérlő"
+
+#: src/lib.cpp:412
+msgid "Intel built in USB hub"
+msgstr "Beépített Intel USB hub"
+
+#: src/lib.cpp:467
+#, c-format
+msgid "glob returned GLOB_NOSPACE\n"
+msgstr ""
+
+#: src/lib.cpp:471
+#, c-format
+msgid "glob returned GLOB_ABORTED\n"
+msgstr ""
+
+#: src/lib.cpp:475
+#, c-format
+msgid "glob returned GLOB_NOMATCH\n"
+msgstr ""
+
+#: src/lib.cpp:513 src/lib.cpp:549
+#, c-format
+msgid ""
+"Model-specific registers (MSR)\t\t\t not found (try enabling "
+"CONFIG_X86_MSR).\n"
+msgstr ""
+
+#: src/main.cpp:104
+#, fuzzy, c-format
+msgid "PowerTOP version "
+msgstr "PowerTOP verzió"
+
+#: src/main.cpp:110
+msgid "Set refresh time out"
+msgstr "Frissítés időkorlát leteltének beállítása"
+
+#: src/main.cpp:123
+msgid "Usage: powertop [OPTIONS]"
+msgstr "Használat: powertop [OPCIÓK]"
+
+#: src/main.cpp:124
+msgid "sets all tunable options to their GOOD setting"
+msgstr ""
+
+#: src/main.cpp:125
+msgid "runs powertop in calibration mode"
+msgstr "a powertop futtatása kalibrációs módban"
+
+#: src/main.cpp:126 src/main.cpp:129
+msgid "[=filename]"
+msgstr ""
+
+#: src/main.cpp:126
+msgid "generate a csv report"
+msgstr "CSV jelentés készítése"
+
+#: src/main.cpp:127
+msgid "run in \"debug\" mode"
+msgstr "futtatás hibakeresési módban"
+
+#: src/main.cpp:128
+msgid "[=devnode]"
+msgstr "[=eszköznév]"
+
+#: src/main.cpp:128
+msgid "uses an Extech Power Analyzer for measurements"
+msgstr "Extech Power Analyzer eszköz használata a mérésekhez"
+
+#: src/main.cpp:129
+msgid "generate a html report"
+msgstr "HTML jelentés készítése"
+
+#: src/main.cpp:130
+msgid "[=iterations] number of times to run each test"
+msgstr "[=iterációk] ennyiszer fusson le minden egyes teszt"
+
+#: src/main.cpp:131
+msgid "suppress stderr output"
+msgstr "szabványos hibakimenet elnyomása"
+
+#: src/main.cpp:132 src/main.cpp:133
+msgid "[=seconds]"
+msgstr "[=másodperc]"
+
+#: src/main.cpp:132
+msgid "interval for power consumption measurement"
+msgstr ""
+
+#: src/main.cpp:133
+msgid "generate a report for 'x' seconds"
+msgstr "ennyi másodpercig készüljön a jelentés"
+
+#: src/main.cpp:134
+msgid "[=workload]"
+msgstr "[=terhelés]"
+
+#: src/main.cpp:134
+msgid "file to execute for workload"
+msgstr "végrehajtandó fájl a terheléshez"
+
+#: src/main.cpp:135
+msgid "print version information"
+msgstr "verzió-információ kiíratása"
+
+#: src/main.cpp:136
+msgid "print this help menu"
+msgstr "e súgó kiíratása"
+
+#: src/main.cpp:138
+#, fuzzy
+msgid "For more help please refer to the 'man 8 powertop'"
+msgstr "További információk a README fájlban találhatók"
+
+#: src/main.cpp:233
+#, c-format
+msgid "Unknown issue running workload!\n"
+msgstr ""
+
+#: src/main.cpp:290
+msgid "PowerTOP is out of memory. PowerTOP is Aborting"
+msgstr "Nincs elég memória a PowerTOP-nak. A PowerTOP futása megszakad"
+
+#: src/main.cpp:298
+#, c-format
+msgid "Preparing to take measurements\n"
+msgstr "Előkészülés a mérések elvégzéséhez\n"
+
+#: src/main.cpp:303
+#, c-format
+msgid "Taking %d measurement(s) for a duration of %d second(s) each.\n"
+msgstr "%d darab, egyenként %d másodperces mérés készítése.\n"
+
+#: src/main.cpp:305
+#, c-format
+msgid "Measuring workload %s.\n"
+msgstr "Terhelés mérése %s.\n"
+
+#: src/main.cpp:330
+#, c-format
+msgid "PowerTOP "
+msgstr "PowerTOP "
+
+#: src/main.cpp:331 src/main.cpp:381
+#, c-format
+msgid "exiting...\n"
+msgstr "kilépés...\n"
+
+#: src/main.cpp:365
+#, c-format
+msgid "modprobe cpufreq_stats failed\n"
+msgstr ""
+
+#: src/main.cpp:368
+#, c-format
+msgid "modprobe msr failed\n"
+msgstr ""
+
+#: src/main.cpp:380 src/main.cpp:384
+#, c-format
+msgid "Failed to mount debugfs!\n"
+msgstr "Nem tudtam csatolni a debugfs-t!\n"
+
+#: src/main.cpp:385
+#, c-format
+msgid "Should still be able to auto tune...\n"
+msgstr ""
+
+#: src/main.cpp:467
+#, c-format
+msgid "Invalid CSV filename\n"
+msgstr ""
+
+#: src/main.cpp:483
+#, c-format
+msgid "Invalid HTML filename\n"
+msgstr ""
+
+#: src/main.cpp:492
+#, c-format
+msgid "Quiet mode failed!\n"
+msgstr ""
+
+#: src/main.cpp:560
+msgid "Leaving PowerTOP"
+msgstr "A PowerTOP elhagyása"
+
+#: src/parameters/persistent.cpp:46 src/parameters/persistent.cpp:155
+msgid "Cannot save to file"
+msgstr "Nem lehet elmenteni a fájlba "
+
+#: src/parameters/persistent.cpp:89 src/parameters/persistent.cpp:180
+msgid "Cannot load from file"
+msgstr "Nem lehet betölteni a fájlból"
+
+#: src/parameters/persistent.cpp:138
+#, c-format
+msgid "Loaded %i prior measurements\n"
+msgstr "%i korábbi mérés betöltve\n"
+
+#: src/parameters/persistent.cpp:181
+msgid ""
+"File will be loaded after taking minimum number of measurement(s) with "
+"battery only \n"
+msgstr ""
+
+#: src/perf/perf.cpp:115
+#, c-format
+msgid ""
+"Too many open files, please increase the limit of open file descriptors.\n"
+msgstr ""
+
+#: src/perf/perf.cpp:117
+#, c-format
+msgid "PowerTOP %s needs the kernel to support the 'perf' subsystem\n"
+msgstr ""
+"A PowerTOP %s verziójának szüksége van arra, hogy a rendszermag támogassa a "
+"„perf” alrendszert\n"
+
+#: src/perf/perf.cpp:118
+#, c-format
+msgid "as well as support for trace points in the kernel:\n"
+msgstr "valamint a nyomkövetési pontokra is a rendszermagban:\n"
+
+#: src/process/do_process.cpp:819
+#, c-format
+msgid ""
+"Estimated power: %5.1f Measured power: %5.1f Sum: %5.1f\n"
+"\n"
+msgstr ""
+"Becsült teljesítmény: %5.1f Mért teljesítmény: %5.1f Összeg: %5.1f\n"
+"\n"
+
+#: src/process/do_process.cpp:838
+#, c-format
+msgid "The estimated remaining time is %i hours, %i minutes\n"
+msgstr "Becsült hátralévő idő %i óra %i perc\n"
+
+#: src/process/do_process.cpp:846
+msgid "Summary"
+msgstr "Összefoglalás"
+
+#: src/process/do_process.cpp:846
+msgid "wakeups/second"
+msgstr "felébredés/másodperc"
+
+#: src/process/do_process.cpp:846
+msgid "GPU ops/seconds"
+msgstr "GPU művelet/másodperc"
+
+#: src/process/do_process.cpp:846
+msgid "VFS ops/sec and"
+msgstr "VFS művelet/másodperc"
+
+#: src/process/do_process.cpp:846
+msgid "CPU use"
+msgstr "CPU használtság"
+
+#: src/process/do_process.cpp:850
+msgid "Power est."
+msgstr "Becsült telj."
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:1078
+msgid "Events/s"
+msgstr "Esemény/s"
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:931 src/process/do_process.cpp:1079
+msgid "Category"
+msgstr "Kategória"
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:932 src/process/do_process.cpp:1080
+#: src/tuning/tuning.cpp:242 src/tuning/tuning.cpp:270
+#: src/tuning/tuning.cpp:295 src/wakeup/waketab.cpp:155
+msgid "Description"
+msgstr "Leírás"
+
+#: src/process/do_process.cpp:927
+msgid "Wakeups/s"
+msgstr "Felébredés/s"
+
+#: src/process/do_process.cpp:928
+msgid "GPU ops/s"
+msgstr "GPU művelet/s"
+
+#: src/process/do_process.cpp:929
+msgid "Disk IO/s"
+msgstr "Lemez BK/s"
+
+#: src/process/do_process.cpp:930
+msgid "GFX Wakeups/s"
+msgstr "GFX felébredés/s"
+
+#: src/process/do_process.cpp:1017
+msgid "Overview of Software Power Consumers"
+msgstr "Szofver teljesítményfogyasztók áttekintése"
+
+#: src/process/do_process.cpp:1057
+msgid "Target:"
+msgstr ""
+
+#: src/process/do_process.cpp:1058
+msgid "1 units/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1059
+msgid "System: "
+msgstr ""
+
+#: src/process/do_process.cpp:1061
+#, fuzzy
+msgid " wakeup/s"
+msgstr "Felébredés/s"
+
+#: src/process/do_process.cpp:1062
+msgid "CPU: "
+msgstr ""
+
+#: src/process/do_process.cpp:1064
+#, fuzzy, c-format
+msgid "% usage"
+msgstr "Használat"
+
+#: src/process/do_process.cpp:1065
+msgid "GPU:"
+msgstr ""
+
+#: src/process/do_process.cpp:1067 src/process/do_process.cpp:1073
+#, fuzzy
+msgid " ops/s"
+msgstr "GPU művelet/s"
+
+#: src/process/do_process.cpp:1068
+msgid "GFX:"
+msgstr ""
+
+#: src/process/do_process.cpp:1070
+#, fuzzy
+msgid " wakeups/s"
+msgstr "Felébredés/s"
+
+#: src/process/do_process.cpp:1071
+msgid "VFS:"
+msgstr ""
+
+#: src/process/do_process.cpp:1139
+#, fuzzy
+msgid "Top 10 Power Consumers"
+msgstr "Szofver teljesítményfogyasztók áttekintése"
+
+#: src/report/report.cpp:122
+#, fuzzy
+msgid "PowerTOP Version"
+msgstr "PowerTOP verzió"
+
+#: src/report/report.cpp:131
+#, fuzzy
+msgid "Kernel Version"
+msgstr "PowerTOP verzió"
+
+#: src/report/report.cpp:135
+msgid "System Name"
+msgstr ""
+
+#: src/report/report.cpp:142
+msgid "CPU Information"
+msgstr ""
+
+#: src/report/report.cpp:154
+msgid "OS Information"
+msgstr ""
+
+#: src/report/report.cpp:161
+#, fuzzy
+msgid "System Information"
+msgstr "verzió-információ kiíratása"
+
+#: src/report/report.cpp:195
+#, fuzzy, c-format
+msgid "Cannot open output file %s (%s)\n"
+msgstr "Nem tudok létrehozni ideiglenes fájlt\n"
+
+#: src/report/report.cpp:211
+#, c-format
+msgid "PowerTOP outputting using base filename %s\n"
+msgstr ""
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:49
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45
+msgid "Good"
+msgstr "Jó"
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:50
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45
+msgid "Bad"
+msgstr "Rossz"
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:51
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45 src/wakeup/wakeup.cpp:50
+msgid "Unknown"
+msgstr "Ismeretlen"
+
+#: src/tuning/bluetooth.cpp:48
+#, c-format
+msgid "Bluetooth device interface status"
+msgstr "Bluetooth eszközcsatoló állapota"
+
+#: src/tuning/ethernet.cpp:54 src/wakeup/wakeup_ethernet.cpp:51
+#, c-format
+msgid "Wake-on-lan status for device %s"
+msgstr "Felébredés hálózati eseményre (wake-on-lan) állapot a(z) %s eszközön"
+
+#: src/tuning/runtime.cpp:48
+#, c-format
+msgid "Runtime PM for %s device %s"
+msgstr "Futásidejű energiagazdálkodás a(z) %s buszon és %s eszközön"
+
+#: src/tuning/runtime.cpp:50
+#, c-format
+msgid "%s device %s has no runtime power management"
+msgstr "A(z) %s busz %s eszközének nincs futásidejű energiagazdálkodása"
+
+#: src/tuning/runtime.cpp:74
+#, c-format
+msgid "PCI Device %s has no runtime power management"
+msgstr "A(z) %s PCI eszköznek nincs futásidejű energiagazdálkodása"
+
+#: src/tuning/runtime.cpp:76
+#, c-format
+msgid "Runtime PM for PCI Device %s"
+msgstr "Futásidejű energiagazdálkodás a(z) %s PCI eszközön"
+
+#: src/tuning/runtime.cpp:80
+#, fuzzy, c-format
+msgid "Runtime PM for port %s of PCI device: %s"
+msgstr "Futásidejű energiagazdálkodás a(z) %s buszon és %s eszközön"
+
+#: src/tuning/runtime.cpp:83
+#, fuzzy, c-format
+msgid "Runtime PM for disk %s"
+msgstr "Futásidejű energiagazdálkodás a(z) %s buszon és %s eszközön"
+
+#: src/tuning/tuning.cpp:62
+msgid "Enable Audio codec power management"
+msgstr "A hang kodek energiagazdálkodásának engedélyezése"
+
+#: src/tuning/tuning.cpp:63
+msgid "NMI watchdog should be turned off"
+msgstr "NMI felügyeletnek (watchdog) kikapcsolva kellene lennie"
+
+#: src/tuning/tuning.cpp:64
+msgid "Power Aware CPU scheduler"
+msgstr "Teljesítményt figyelembevevő CPU ütemező"
+
+#: src/tuning/tuning.cpp:65
+msgid "VM writeback timeout"
+msgstr "VM visszaírás időtúllépése"
+
+#: src/tuning/tuning.cpp:81
+msgid "Tunables"
+msgstr "Hangolások"
+
+#: src/tuning/tuning.cpp:81
+msgid " <ESC> Exit | <Enter> Toggle tunable | <r> Window refresh"
+msgstr " <ESC> Kilépés | <Enter> Hangolás átkapcsolása | <r> Ablak frissítése"
+
+#: src/tuning/tuning.cpp:243 src/wakeup/waketab.cpp:156
+msgid "Script"
+msgstr ""
+
+#: src/tuning/tuning.cpp:257
+msgid "Software Settings in Need of Tuning"
+msgstr ""
+
+#: src/tuning/tuning.cpp:276
+msgid "Untunable Software Issues"
+msgstr ""
+
+#: src/tuning/tuning.cpp:307
+msgid "Optimal Tuned Software Settings"
+msgstr ""
+
+#: src/tuning/tuningi2c.cpp:57
+#, fuzzy, c-format
+msgid "Runtime PM for I2C %s %s (%s)"
+msgstr "Futásidejű energiagazdálkodás a(z) %s buszon és %s eszközön"
+
+#: src/tuning/tuningi2c.cpp:59
+#, fuzzy, c-format
+msgid "I2C %s %s has no runtime power management"
+msgstr "A(z) %s busz %s eszközének nincs futásidejű energiagazdálkodása"
+
+#: src/tuning/tuningsysfs.cpp:123
+#, fuzzy, c-format
+msgid "Enable SATA link power management for %s"
+msgstr "SATA link energiaszabályozás engedélyezése %s számára"
+
+#: src/tuning/tuningusb.cpp:54
+#, c-format
+msgid "Autosuspend for unknown USB device %s (%s:%s)"
+msgstr "Automatikus felfüggesztés a(z) %s (%s:%s) ismeretlen USB eszközön"
+
+#: src/tuning/tuningusb.cpp:71 src/tuning/tuningusb.cpp:73
+#: src/tuning/tuningusb.cpp:75
+#, c-format
+msgid "Autosuspend for USB device %s [%s]"
+msgstr "Automatikus felfüggesztés a(z) %s [%s] USB eszközön"
+
+#: src/tuning/wifi.cpp:48
+#, c-format
+msgid "Wireless Power Saving for interface %s"
+msgstr "Vezeték nélküli teljesítménymegtakarítás a(z) %s illesztőegységen"
+
+#: src/wakeup/waketab.cpp:42
+#, fuzzy
+msgid "WakeUp"
+msgstr "Felébredés/s"
+
+#: src/wakeup/waketab.cpp:42
+#, fuzzy
+msgid " <ESC> Exit | <Enter> Toggle wakeup | <r> Window refresh"
+msgstr " <ESC> Kilépés | <Enter> Hangolás átkapcsolása | <r> Ablak frissítése"
+
+#: src/wakeup/waketab.cpp:170
+#, fuzzy
+msgid "Wake status of the devices"
+msgstr "Felébredés hálózati eseményre (wake-on-lan) állapot a(z) %s eszközön"
+
+#: src/wakeup/wakeup.cpp:48 src/wakeup/wakeup_ethernet.cpp:47
+#: src/wakeup/wakeup_usb.cpp:47
+#, fuzzy
+msgid "Enabled"
+msgstr "Hangolások"
+
+#: src/wakeup/wakeup.cpp:49 src/wakeup/wakeup_ethernet.cpp:47
+#: src/wakeup/wakeup_usb.cpp:47
+msgid "Disabled"
+msgstr ""
+
+#: src/wakeup/wakeup_usb.cpp:51
+#, fuzzy, c-format
+msgid "Wake status for USB device %s"
+msgstr "Felébredés hálózati eseményre (wake-on-lan) állapot a(z) %s eszközön"
+
+#~ msgid "Actual"
+#~ msgstr "Aktuális"
+
+#, fuzzy
+#~ msgid "I2C Device: %s"
+#~ msgstr "PCI eszköz: %s"
+
+#~ msgid "[=FILENAME]"
+#~ msgstr "[=FÁJLNÉV]"
+
+#~ msgid "Using 'ondemand' cpufreq governor"
+#~ msgstr "Igény szerinti (ondemand) cpufreq vezérlő használata"
+
+#~ msgid "Power Consumption Summary"
+#~ msgstr "Teljesítményfelvétel összefoglaló"
+
+#~ msgid "GPU ops/second"
+#~ msgstr "GPU művelet/másodperc"
+
+#~ msgid "VFS ops/sec"
+#~ msgstr "VFS művelet/mp"
+
+#~ msgid "GFX wakes/sec and"
+#~ msgstr "GFX felébredés/mp és"
diff --git a/po/id_ID.po b/po/id_ID.po
new file mode 100644
index 0000000..ef1d8c5
--- /dev/null
+++ b/po/id_ID.po
@@ -0,0 +1,997 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Intel Corporation
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Andika Triwidada <andika@gmail.com>, 2012-2013
+msgid ""
+msgstr ""
+"Project-Id-Version: PowerTOP\n"
+"Report-Msgid-Bugs-To: \"powertop@lists.01.org\"\n"
+"POT-Creation-Date: 2022-09-29 04:45-0700\n"
+"PO-Revision-Date: 2013-11-05 08:40+0000\n"
+"Last-Translator: Margie Foster <margie@linux.intel.com>\n"
+"Language-Team: Indonesian (Indonesia) (http://www.transifex.com/projects/p/"
+"PowerTOP/language/id_ID/)\n"
+"Language: id_ID\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: src/calibrate/calibrate.cpp:238
+#, c-format
+msgid "Cannot create temp file\n"
+msgstr "Tak bisa membuat berkas temp\n"
+
+#: src/calibrate/calibrate.cpp:258
+#, c-format
+msgid "Calibrating: CPU usage on %i threads\n"
+msgstr "Kalibrasi: Pemakaian CPU pada %i thread \n"
+
+#: src/calibrate/calibrate.cpp:273
+#, c-format
+msgid "Calibrating: CPU wakeup power consumption\n"
+msgstr "Kalibrasi: Konsumsi daya CPU bangun \n"
+
+#: src/calibrate/calibrate.cpp:290
+#, c-format
+msgid "Calibrating USB devices\n"
+msgstr "Kalibrasi perangkat USB \n"
+
+#: src/calibrate/calibrate.cpp:292 src/calibrate/calibrate.cpp:309
+#: src/calibrate/calibrate.cpp:317 src/calibrate/calibrate.cpp:334
+#, c-format
+msgid ".... device %s \n"
+msgstr ".... perangkat %s \n"
+
+#: src/calibrate/calibrate.cpp:307
+#, c-format
+msgid "Calibrating radio devices\n"
+msgstr "Kalibrasi perangkat radio \n"
+
+#: src/calibrate/calibrate.cpp:331
+#, c-format
+msgid "Calibrating backlight\n"
+msgstr "Kalibrasi cahaya latar \n"
+
+#: src/calibrate/calibrate.cpp:355 src/calibrate/calibrate.cpp:365
+#, c-format
+msgid "Calibrating idle\n"
+msgstr "Kalibrasi menganggur \n"
+
+#: src/calibrate/calibrate.cpp:378
+#, c-format
+msgid "Calibrating: disk usage \n"
+msgstr "Kalibrasi: pemakaian disk \n"
+
+#: src/calibrate/calibrate.cpp:403
+msgid "Starting PowerTOP power estimate calibration \n"
+msgstr "Memulai kalibrasi estimasi daya PowerTop \n"
+
+#: src/calibrate/calibrate.cpp:426
+msgid "Finishing PowerTOP power estimate calibration \n"
+msgstr "Mengakhiri kalibrasi estimasi daya PowerTop \n"
+
+#: src/calibrate/calibrate.cpp:430
+#, c-format
+msgid "Parameters after calibration:\n"
+msgstr "Parameter setelah kalibrasi:\n"
+
+#: src/cpu/abstract_cpu.cpp:74
+msgid "Idle"
+msgstr ""
+
+#: src/cpu/abstract_cpu.cpp:76
+msgid "Turbo Mode"
+msgstr ""
+
+#: src/cpu/cpu_core.cpp:37
+#, fuzzy, c-format
+msgid " Core(HW)"
+msgstr " Core"
+
+#: src/cpu/cpu_core.cpp:37
+#, fuzzy, c-format
+msgid " Core(OS)"
+msgstr " Core"
+
+#: src/cpu/cpu_core.cpp:91 src/cpu/intel_cpus.cpp:367
+#, c-format
+msgid " Core"
+msgstr " Core"
+
+#: src/cpu/cpu.cpp:85
+#, c-format
+msgid "cpu package %i"
+msgstr "paket %i cpu"
+
+#: src/cpu/cpu.cpp:86
+msgid "cpu package"
+msgstr "paket cpu"
+
+#: src/cpu/cpu.cpp:89 src/cpu/cpu.cpp:96
+#, fuzzy, c-format
+msgid "package-%i"
+msgstr "Paket %i"
+
+#: src/cpu/cpu.cpp:90
+msgid "cpu rapl package"
+msgstr ""
+
+#: src/cpu/cpu.cpp:97
+msgid "dram rapl package"
+msgstr ""
+
+#: src/cpu/cpu.cpp:471
+msgid "Processor Idle State Report"
+msgstr ""
+
+#: src/cpu/cpu.cpp:535 src/cpu/cpu.cpp:761
+msgid "Package"
+msgstr "Paket"
+
+#: src/cpu/cpu.cpp:572 src/cpu/cpu.cpp:783
+#, fuzzy, c-format
+msgid "Core %d"
+msgstr "Core %i"
+
+#: src/cpu/cpu.cpp:579
+#, fuzzy, c-format
+msgid "GPU %d"
+msgstr "GPU %i"
+
+#: src/cpu/cpu.cpp:602
+#, fuzzy
+msgid "CPU"
+msgstr "CPU %i"
+
+#: src/cpu/cpu.cpp:684
+msgid "Processor Frequency Report"
+msgstr ""
+
+#: src/cpu/cpu.cpp:804
+#, fuzzy, c-format
+msgid "CPU %d"
+msgstr "CPU %i"
+
+#: src/cpu/cpu.cpp:1005
+#, c-format
+msgid "cpu_idle event returned no state?\n"
+msgstr "kejadian cpu_idle tak mengembalikan keadaan?\n"
+
+#: src/cpu/cpu.cpp:1020
+#, c-format
+msgid "power or cpu_frequency event returned no state?\n"
+msgstr "kejadian power atau cpu_frequency tak mengembalikan keadaan?\n"
+
+#: src/cpu/cpu_linux.cpp:79
+msgid "C0 polling"
+msgstr "C0 polling"
+
+#: src/cpu/cpu_linux.cpp:242
+#, fuzzy, c-format
+msgid " CPU(OS) %i"
+msgstr " CPU %i"
+
+#: src/cpu/cpu_linux.cpp:341 src/cpu/intel_cpus.cpp:733
+#, c-format
+msgid " CPU %i"
+msgstr " CPU %i"
+
+#: src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(HW)"
+msgstr ""
+
+#: src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(OS)"
+msgstr ""
+
+#: src/cpu/cpu_package.cpp:104 src/cpu/intel_cpus.cpp:498
+#, c-format
+msgid " Package"
+msgstr "Paket"
+
+#: src/cpu/intel_cpus.cpp:152
+#, c-format
+msgid "read_msr cpu%d 0x%llx : "
+msgstr ""
+
+#: src/cpu/intel_cpus.cpp:656
+msgid "C0 active"
+msgstr "C0 aktif"
+
+#: src/cpu/intel_cpus.cpp:714
+#, c-format
+msgid "Average"
+msgstr ""
+
+#: src/cpu/intel_gpu.cpp:64
+#, fuzzy, c-format
+msgid " GPU "
+msgstr "GPU %i"
+
+#: src/devices/ahci.cpp:154
+#, c-format
+msgid "SATA link: %s"
+msgstr "Link SATA: %s"
+
+#: src/devices/ahci.cpp:156
+#, c-format
+msgid "SATA disk: %s"
+msgstr "Disk SATA: %s"
+
+#: src/devices/ahci.cpp:374
+msgid "AHCI ALPM Residency Statistics - Not supported on this macine"
+msgstr ""
+
+#: src/devices/ahci.cpp:389
+msgid "Link"
+msgstr ""
+
+#: src/devices/ahci.cpp:390
+#, fuzzy
+msgid "Active"
+msgstr "C0 aktif"
+
+#: src/devices/ahci.cpp:391
+msgid "Partial"
+msgstr ""
+
+#: src/devices/ahci.cpp:392
+msgid "Slumber"
+msgstr ""
+
+#: src/devices/ahci.cpp:393
+msgid "Devslp"
+msgstr ""
+
+#: src/devices/ahci.cpp:399
+msgid "AHCI ALPM Residency Statistics"
+msgstr ""
+
+#: src/devices/alsa.cpp:77
+#, c-format
+msgid "Audio codec %s: %s (%s)"
+msgstr "Codec audio %s: %s (%s)"
+
+#: src/devices/alsa.cpp:79 src/devices/alsa.cpp:81
+#, c-format
+msgid "Audio codec %s: %s"
+msgstr "Codec audio %s: %s"
+
+#: src/devices/devfreq.cpp:260
+#, fuzzy
+msgid "Device Freq stats"
+msgstr "Stat perangkat"
+
+#: src/devices/devfreq.cpp:278
+msgid " Devfreq is not enabled"
+msgstr ""
+
+#: src/devices/devfreq.cpp:283
+msgid " No devfreq devices available"
+msgstr ""
+
+#: src/devices/device.cpp:172 src/process/do_process.cpp:831
+#, c-format
+msgid "The battery reports a discharge rate of %sW\n"
+msgstr "Baterai melaporkan laju pengosongan %sW\n"
+
+#: src/devices/device.cpp:174 src/process/do_process.cpp:833
+#, c-format
+msgid "The energy consumed was %sJ\n"
+msgstr ""
+
+#: src/devices/device.cpp:180
+#, c-format
+msgid "System baseline power is estimated at %sW\n"
+msgstr "Daya baseline sistem diperkirakan %sW\n"
+
+#: src/devices/device.cpp:187
+msgid "Power est. Usage Device name\n"
+msgstr "Est. daya Pakai Nama perangkat\n"
+
+#: src/devices/device.cpp:189
+msgid " Usage Device name\n"
+msgstr " Pakai Nama perangkat\n"
+
+#: src/devices/device.cpp:256
+#, fuzzy
+msgid "The battery reports a discharge rate of: "
+msgstr "Baterai melaporkan laju pengosongan %sW\n"
+
+#: src/devices/device.cpp:261
+msgid "The energy consumed was : "
+msgstr ""
+
+#: src/devices/device.cpp:268
+#, fuzzy
+msgid "The system baseline power is estimated at: "
+msgstr "Daya baseline sistem diperkirakan %sW\n"
+
+#: src/devices/device.cpp:277 src/process/do_process.cpp:850
+#: src/process/do_process.cpp:852 src/process/do_process.cpp:926
+#: src/process/do_process.cpp:1077
+msgid "Usage"
+msgstr "Pakai"
+
+#: src/devices/device.cpp:278
+#, fuzzy
+msgid "Device Name"
+msgstr "Stat perangkat"
+
+#: src/devices/device.cpp:280 src/process/do_process.cpp:935
+#: src/process/do_process.cpp:1082
+msgid "PW Estimate"
+msgstr ""
+
+#: src/devices/device.cpp:317
+msgid "Device Power Report"
+msgstr ""
+
+#: src/devices/network.cpp:177
+#, c-format
+msgid "Network interface: %s (%s)"
+msgstr "Antarmuka jaringa: %s (%s)"
+
+#: src/devices/rfkill.cpp:65 src/devices/rfkill.cpp:69
+#, c-format
+msgid "Radio device: %s"
+msgstr "Perangkat radio: %s"
+
+#: src/devices/runtime_pm.cpp:216
+#, c-format
+msgid "I2C %s (%s): %s"
+msgstr ""
+
+#: src/devices/runtime_pm.cpp:216 src/tuning/tuningi2c.cpp:57
+#: src/tuning/tuningi2c.cpp:59
+msgid "Adapter"
+msgstr ""
+
+#: src/devices/runtime_pm.cpp:216 src/devlist.cpp:331
+#: src/tuning/tuningi2c.cpp:57 src/tuning/tuningi2c.cpp:59
+#, fuzzy
+msgid "Device"
+msgstr "Stat perangkat"
+
+#: src/devices/runtime_pm.cpp:241
+#, c-format
+msgid "PCI Device: %s"
+msgstr "Perangkat PCI: %s"
+
+#: src/devices/usb.cpp:51 src/devices/usb.cpp:96 src/devices/usb.cpp:98
+#, c-format
+msgid "USB device: %s"
+msgstr "Perangkat USB: %s"
+
+#: src/devices/usb.cpp:94
+#, c-format
+msgid "USB device: %s (%s)"
+msgstr "Perangkat USB: %s (%s)"
+
+#: src/devlist.cpp:330
+msgid "Process"
+msgstr ""
+
+#: src/devlist.cpp:347
+msgid "Process Device Activity"
+msgstr ""
+
+#: src/display.cpp:70
+msgid "Overview"
+msgstr "Ringkasan"
+
+#: src/display.cpp:71
+msgid "Idle stats"
+msgstr "Stat menganggur"
+
+#: src/display.cpp:72
+msgid "Frequency stats"
+msgstr "Stat frekuensi"
+
+#: src/display.cpp:73
+msgid "Device stats"
+msgstr "Stat perangkat"
+
+#: src/display.cpp:131
+msgid "Exit"
+msgstr "Keluar"
+
+#: src/display.cpp:132
+msgid "Navigate"
+msgstr ""
+
+#: src/lib.cpp:288
+#, c-format
+msgid "%7sW"
+msgstr "%7sW"
+
+#: src/lib.cpp:291
+#, c-format
+msgid " 0 mW"
+msgstr " 0 mW"
+
+#: src/lib.cpp:410
+msgid "PS/2 Touchpad / Keyboard / Mouse"
+msgstr "PS/2 Touchpad / Keyboard / Mouse"
+
+#: src/lib.cpp:411
+msgid "SATA controller"
+msgstr "Pengendali SATA"
+
+#: src/lib.cpp:412
+msgid "Intel built in USB hub"
+msgstr "Hub USB built in Intel"
+
+#: src/lib.cpp:467
+#, c-format
+msgid "glob returned GLOB_NOSPACE\n"
+msgstr ""
+
+#: src/lib.cpp:471
+#, c-format
+msgid "glob returned GLOB_ABORTED\n"
+msgstr ""
+
+#: src/lib.cpp:475
+#, c-format
+msgid "glob returned GLOB_NOMATCH\n"
+msgstr ""
+
+#: src/lib.cpp:513 src/lib.cpp:549
+#, c-format
+msgid ""
+"Model-specific registers (MSR)\t\t\t not found (try enabling "
+"CONFIG_X86_MSR).\n"
+msgstr ""
+
+#: src/main.cpp:104
+#, fuzzy, c-format
+msgid "PowerTOP version "
+msgstr "PowerTop versi"
+
+#: src/main.cpp:110
+msgid "Set refresh time out"
+msgstr "Tata tenggang waktu penyegaran"
+
+#: src/main.cpp:123
+msgid "Usage: powertop [OPTIONS]"
+msgstr "Cara pakai: powertop [OPSI]"
+
+#: src/main.cpp:124
+msgid "sets all tunable options to their GOOD setting"
+msgstr ""
+
+#: src/main.cpp:125
+msgid "runs powertop in calibration mode"
+msgstr "jalankan powertop dalam mode kalibrasi"
+
+#: src/main.cpp:126 src/main.cpp:129
+msgid "[=filename]"
+msgstr ""
+
+#: src/main.cpp:126
+msgid "generate a csv report"
+msgstr "buat laporan csv"
+
+#: src/main.cpp:127
+msgid "run in \"debug\" mode"
+msgstr "jalankan dalam mode \"debug\""
+
+#: src/main.cpp:128
+msgid "[=devnode]"
+msgstr "[=devnode]"
+
+#: src/main.cpp:128
+msgid "uses an Extech Power Analyzer for measurements"
+msgstr "pakai Extech Power Analyzer untuk pengukuran"
+
+#: src/main.cpp:129
+msgid "generate a html report"
+msgstr "buat laporan html"
+
+#: src/main.cpp:130
+msgid "[=iterations] number of times to run each test"
+msgstr "[=iterasi] berapa kali menjalankan tiap tes"
+
+#: src/main.cpp:131
+msgid "suppress stderr output"
+msgstr "redam keluaran stderr"
+
+#: src/main.cpp:132 src/main.cpp:133
+msgid "[=seconds]"
+msgstr "[=detik]"
+
+#: src/main.cpp:132
+msgid "interval for power consumption measurement"
+msgstr ""
+
+#: src/main.cpp:133
+msgid "generate a report for 'x' seconds"
+msgstr "buat laporan untuk 'x' detik"
+
+#: src/main.cpp:134
+msgid "[=workload]"
+msgstr "[=beban kerja]"
+
+#: src/main.cpp:134
+msgid "file to execute for workload"
+msgstr "berkas yang akan dieksekusi untuk beban kerja"
+
+#: src/main.cpp:135
+msgid "print version information"
+msgstr "cetak informasi versi"
+
+#: src/main.cpp:136
+msgid "print this help menu"
+msgstr "cetik menu bantuan ini"
+
+#: src/main.cpp:138
+#, fuzzy
+msgid "For more help please refer to the 'man 8 powertop'"
+msgstr "Untuk bantuan lebih lanjut lihatlah README"
+
+#: src/main.cpp:233
+#, c-format
+msgid "Unknown issue running workload!\n"
+msgstr "Masalah tak dikenal saat menjalankan beban!\n"
+
+#: src/main.cpp:290
+msgid "PowerTOP is out of memory. PowerTOP is Aborting"
+msgstr "PowerTop kehabisan memori. PowerTop digugurkan."
+
+#: src/main.cpp:298
+#, c-format
+msgid "Preparing to take measurements\n"
+msgstr "Bersiap melakukan pengkukuran\n"
+
+#: src/main.cpp:303
+#, c-format
+msgid "Taking %d measurement(s) for a duration of %d second(s) each.\n"
+msgstr "Melakukan %d pengukuran selama masing-masing %d detik.\n"
+
+#: src/main.cpp:305
+#, c-format
+msgid "Measuring workload %s.\n"
+msgstr "Mengukur beban kerja %s.\n"
+
+#: src/main.cpp:330
+#, c-format
+msgid "PowerTOP "
+msgstr "PowerTOP "
+
+#: src/main.cpp:331 src/main.cpp:381
+#, c-format
+msgid "exiting...\n"
+msgstr "keluar...\n"
+
+#: src/main.cpp:365
+#, c-format
+msgid "modprobe cpufreq_stats failed\n"
+msgstr ""
+
+#: src/main.cpp:368
+#, fuzzy, c-format
+msgid "modprobe msr failed\n"
+msgstr "Mode hening gagal!\n"
+
+#: src/main.cpp:380 src/main.cpp:384
+#, c-format
+msgid "Failed to mount debugfs!\n"
+msgstr "Gagal mengait debugfs!\n"
+
+#: src/main.cpp:385
+#, c-format
+msgid "Should still be able to auto tune...\n"
+msgstr ""
+
+#: src/main.cpp:467
+#, c-format
+msgid "Invalid CSV filename\n"
+msgstr ""
+
+#: src/main.cpp:483
+#, c-format
+msgid "Invalid HTML filename\n"
+msgstr ""
+
+#: src/main.cpp:492
+#, fuzzy, c-format
+msgid "Quiet mode failed!\n"
+msgstr "Mode hening gagal!\n"
+
+#: src/main.cpp:560
+msgid "Leaving PowerTOP"
+msgstr "Meninggalkan PowerTop"
+
+#: src/parameters/persistent.cpp:46 src/parameters/persistent.cpp:155
+msgid "Cannot save to file"
+msgstr "Tak bisa menyimpan ke berkas"
+
+#: src/parameters/persistent.cpp:89 src/parameters/persistent.cpp:180
+msgid "Cannot load from file"
+msgstr "Tak bisa memuat dari berkas"
+
+#: src/parameters/persistent.cpp:138
+#, c-format
+msgid "Loaded %i prior measurements\n"
+msgstr "Dimuat %i pengukuran sebelumnya\n"
+
+#: src/parameters/persistent.cpp:181
+msgid ""
+"File will be loaded after taking minimum number of measurement(s) with "
+"battery only \n"
+msgstr ""
+
+#: src/perf/perf.cpp:115
+#, c-format
+msgid ""
+"Too many open files, please increase the limit of open file descriptors.\n"
+msgstr ""
+
+#: src/perf/perf.cpp:117
+#, c-format
+msgid "PowerTOP %s needs the kernel to support the 'perf' subsystem\n"
+msgstr "PowerTop %s memerlukan kernel yang mendukung subsistem 'perf'\n"
+
+#: src/perf/perf.cpp:118
+#, c-format
+msgid "as well as support for trace points in the kernel:\n"
+msgstr "dan juga dukungan trace point dalam kernel:\n"
+
+#: src/process/do_process.cpp:819
+#, c-format
+msgid ""
+"Estimated power: %5.1f Measured power: %5.1f Sum: %5.1f\n"
+"\n"
+msgstr ""
+"Perkiraan daya: %5.1f Daya terukur: %5.1f Jumlah: %5.1f\n"
+"\n"
+
+#: src/process/do_process.cpp:838
+#, c-format
+msgid "The estimated remaining time is %i hours, %i minutes\n"
+msgstr "Perkiraan sisa waktu adalah %i jam, %i menit\n"
+
+#: src/process/do_process.cpp:846
+msgid "Summary"
+msgstr "Ringkasan"
+
+#: src/process/do_process.cpp:846
+msgid "wakeups/second"
+msgstr "bangun/detik"
+
+#: src/process/do_process.cpp:846
+msgid "GPU ops/seconds"
+msgstr "op GPU/detik"
+
+#: src/process/do_process.cpp:846
+msgid "VFS ops/sec and"
+msgstr "op VFS/detik"
+
+#: src/process/do_process.cpp:846
+msgid "CPU use"
+msgstr "pakai CPU"
+
+#: src/process/do_process.cpp:850
+msgid "Power est."
+msgstr "Est. daya"
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:1078
+msgid "Events/s"
+msgstr "Kejadian/d"
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:931 src/process/do_process.cpp:1079
+msgid "Category"
+msgstr "Kategori"
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:932 src/process/do_process.cpp:1080
+#: src/tuning/tuning.cpp:242 src/tuning/tuning.cpp:270
+#: src/tuning/tuning.cpp:295 src/wakeup/waketab.cpp:155
+msgid "Description"
+msgstr "Deskripsi"
+
+#: src/process/do_process.cpp:927
+msgid "Wakeups/s"
+msgstr "Bangun/d"
+
+#: src/process/do_process.cpp:928
+msgid "GPU ops/s"
+msgstr "Op GPU/d"
+
+#: src/process/do_process.cpp:929
+msgid "Disk IO/s"
+msgstr "IO Disk/d"
+
+#: src/process/do_process.cpp:930
+msgid "GFX Wakeups/s"
+msgstr "GFX Bangun/d"
+
+#: src/process/do_process.cpp:1017
+msgid "Overview of Software Power Consumers"
+msgstr "Ringkasan Pemakai Daya Perangkat Lunak"
+
+#: src/process/do_process.cpp:1057
+msgid "Target:"
+msgstr ""
+
+#: src/process/do_process.cpp:1058
+msgid "1 units/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1059
+msgid "System: "
+msgstr ""
+
+#: src/process/do_process.cpp:1061
+#, fuzzy
+msgid " wakeup/s"
+msgstr "Bangun/d"
+
+#: src/process/do_process.cpp:1062
+msgid "CPU: "
+msgstr ""
+
+#: src/process/do_process.cpp:1064
+#, fuzzy, c-format
+msgid "% usage"
+msgstr "Pakai"
+
+#: src/process/do_process.cpp:1065
+msgid "GPU:"
+msgstr ""
+
+#: src/process/do_process.cpp:1067 src/process/do_process.cpp:1073
+#, fuzzy
+msgid " ops/s"
+msgstr "Op GPU/d"
+
+#: src/process/do_process.cpp:1068
+msgid "GFX:"
+msgstr ""
+
+#: src/process/do_process.cpp:1070
+#, fuzzy
+msgid " wakeups/s"
+msgstr "Bangun/d"
+
+#: src/process/do_process.cpp:1071
+msgid "VFS:"
+msgstr ""
+
+#: src/process/do_process.cpp:1139
+#, fuzzy
+msgid "Top 10 Power Consumers"
+msgstr "Ringkasan Pemakai Daya Perangkat Lunak"
+
+#: src/report/report.cpp:122
+#, fuzzy
+msgid "PowerTOP Version"
+msgstr "PowerTop versi"
+
+#: src/report/report.cpp:131
+#, fuzzy
+msgid "Kernel Version"
+msgstr "PowerTop versi"
+
+#: src/report/report.cpp:135
+msgid "System Name"
+msgstr ""
+
+#: src/report/report.cpp:142
+msgid "CPU Information"
+msgstr ""
+
+#: src/report/report.cpp:154
+msgid "OS Information"
+msgstr ""
+
+#: src/report/report.cpp:161
+#, fuzzy
+msgid "System Information"
+msgstr "cetak informasi versi"
+
+#: src/report/report.cpp:195
+#, fuzzy, c-format
+msgid "Cannot open output file %s (%s)\n"
+msgstr "Tak bisa membuat berkas temp\n"
+
+#: src/report/report.cpp:211
+#, c-format
+msgid "PowerTOP outputting using base filename %s\n"
+msgstr ""
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:49
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45
+msgid "Good"
+msgstr "Baik"
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:50
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45
+msgid "Bad"
+msgstr "Buruk"
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:51
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45 src/wakeup/wakeup.cpp:50
+msgid "Unknown"
+msgstr "Tak diketahui"
+
+#: src/tuning/bluetooth.cpp:48
+#, c-format
+msgid "Bluetooth device interface status"
+msgstr "Status antarmuka perangkat Bluetooth"
+
+#: src/tuning/ethernet.cpp:54 src/wakeup/wakeup_ethernet.cpp:51
+#, c-format
+msgid "Wake-on-lan status for device %s"
+msgstr "Status wake-on-lan bagi perangkat %s"
+
+#: src/tuning/runtime.cpp:48
+#, c-format
+msgid "Runtime PM for %s device %s"
+msgstr "PM runtime bagi %s perangkat %s"
+
+#: src/tuning/runtime.cpp:50
+#, c-format
+msgid "%s device %s has no runtime power management"
+msgstr "%s perangkat %s tak memiliki manajemen daya runtime"
+
+#: src/tuning/runtime.cpp:74
+#, c-format
+msgid "PCI Device %s has no runtime power management"
+msgstr "Perangkat PCI %s tak memiliki manajemen daya runtime"
+
+#: src/tuning/runtime.cpp:76
+#, c-format
+msgid "Runtime PM for PCI Device %s"
+msgstr "PM runtime bagi Perangkat PCI %s"
+
+#: src/tuning/runtime.cpp:80
+#, fuzzy, c-format
+msgid "Runtime PM for port %s of PCI device: %s"
+msgstr "PM runtime bagi %s perangkat %s"
+
+#: src/tuning/runtime.cpp:83
+#, fuzzy, c-format
+msgid "Runtime PM for disk %s"
+msgstr "PM runtime bagi %s perangkat %s"
+
+#: src/tuning/tuning.cpp:62
+msgid "Enable Audio codec power management"
+msgstr "Aktifkan manajemen daya codec audio"
+
+#: src/tuning/tuning.cpp:63
+msgid "NMI watchdog should be turned off"
+msgstr "Watchdog NMI mesti dimatikan"
+
+#: src/tuning/tuning.cpp:64
+msgid "Power Aware CPU scheduler"
+msgstr "Scheduler CPU Sadar Daya"
+
+#: src/tuning/tuning.cpp:65
+msgid "VM writeback timeout"
+msgstr "Tenggang waktu writeback VM"
+
+#: src/tuning/tuning.cpp:81
+msgid "Tunables"
+msgstr "Tunables"
+
+#: src/tuning/tuning.cpp:81
+msgid " <ESC> Exit | <Enter> Toggle tunable | <r> Window refresh"
+msgstr " <ESC> Keluar | <Enter> Jungkit tunable | <r> Segarkan jendela"
+
+#: src/tuning/tuning.cpp:243 src/wakeup/waketab.cpp:156
+msgid "Script"
+msgstr ""
+
+#: src/tuning/tuning.cpp:257
+msgid "Software Settings in Need of Tuning"
+msgstr ""
+
+#: src/tuning/tuning.cpp:276
+msgid "Untunable Software Issues"
+msgstr ""
+
+#: src/tuning/tuning.cpp:307
+msgid "Optimal Tuned Software Settings"
+msgstr ""
+
+#: src/tuning/tuningi2c.cpp:57
+#, fuzzy, c-format
+msgid "Runtime PM for I2C %s %s (%s)"
+msgstr "PM runtime bagi %s perangkat %s"
+
+#: src/tuning/tuningi2c.cpp:59
+#, fuzzy, c-format
+msgid "I2C %s %s has no runtime power management"
+msgstr "%s perangkat %s tak memiliki manajemen daya runtime"
+
+#: src/tuning/tuningsysfs.cpp:123
+#, fuzzy, c-format
+msgid "Enable SATA link power management for %s"
+msgstr "Fungsikan Manajemen daya link SATA bagi %s"
+
+#: src/tuning/tuningusb.cpp:54
+#, c-format
+msgid "Autosuspend for unknown USB device %s (%s:%s)"
+msgstr "Suspensi otomatis bagi perangkat USB tak dikenal %s (%s:%s)"
+
+#: src/tuning/tuningusb.cpp:71 src/tuning/tuningusb.cpp:73
+#: src/tuning/tuningusb.cpp:75
+#, c-format
+msgid "Autosuspend for USB device %s [%s]"
+msgstr "Suspensi otomatis bagi perangkat USB %s [%s]"
+
+#: src/tuning/wifi.cpp:48
+#, c-format
+msgid "Wireless Power Saving for interface %s"
+msgstr "Penghematan Daya Nirkabel bagi antarmuka %s"
+
+#: src/wakeup/waketab.cpp:42
+#, fuzzy
+msgid "WakeUp"
+msgstr "Bangun/d"
+
+#: src/wakeup/waketab.cpp:42
+#, fuzzy
+msgid " <ESC> Exit | <Enter> Toggle wakeup | <r> Window refresh"
+msgstr " <ESC> Keluar | <Enter> Jungkit tunable | <r> Segarkan jendela"
+
+#: src/wakeup/waketab.cpp:170
+#, fuzzy
+msgid "Wake status of the devices"
+msgstr "Status wake-on-lan bagi perangkat %s"
+
+#: src/wakeup/wakeup.cpp:48 src/wakeup/wakeup_ethernet.cpp:47
+#: src/wakeup/wakeup_usb.cpp:47
+#, fuzzy
+msgid "Enabled"
+msgstr "Tunables"
+
+#: src/wakeup/wakeup.cpp:49 src/wakeup/wakeup_ethernet.cpp:47
+#: src/wakeup/wakeup_usb.cpp:47
+msgid "Disabled"
+msgstr ""
+
+#: src/wakeup/wakeup_usb.cpp:51
+#, fuzzy, c-format
+msgid "Wake status for USB device %s"
+msgstr "Status wake-on-lan bagi perangkat %s"
+
+#~ msgid "Actual"
+#~ msgstr "Aktual"
+
+#, fuzzy
+#~ msgid "I2C Device: %s"
+#~ msgstr "Perangkat PCI: %s"
+
+#~ msgid "[=FILENAME]"
+#~ msgstr "[=NAMAFILE]"
+
+#~ msgid "Using 'ondemand' cpufreq governor"
+#~ msgstr "Memakai governor cpufreq 'ondemand'"
+
+#~ msgid "Power Consumption Summary"
+#~ msgstr "Ringkasan Konsumsi Daya"
+
+#~ msgid "GPU ops/second"
+#~ msgstr "Op GPU/detik"
+
+#~ msgid "VFS ops/sec"
+#~ msgstr "Op VFS/det"
+
+#~ msgid "GFX wakes/sec and"
+#~ msgstr "GFX bangu/det dan"
diff --git a/po/it_IT.po b/po/it_IT.po
new file mode 100644
index 0000000..a3164c7
--- /dev/null
+++ b/po/it_IT.po
@@ -0,0 +1,994 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Intel Corporation
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Random_R, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: PowerTOP\n"
+"Report-Msgid-Bugs-To: powertop@lists.01.org\n"
+"POT-Creation-Date: 2019-01-04 13:55-0800\n"
+"PO-Revision-Date: 2013-11-05 08:40+0000\n"
+"Last-Translator: Margie Foster <margie@linux.intel.com>\n"
+"Language-Team: Italian (Italy) (http://www.transifex.com/projects/p/PowerTOP/"
+"language/it_IT/)\n"
+"Language: it_IT\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ../src/calibrate/calibrate.cpp:238
+#, c-format
+msgid "Cannot create temp file\n"
+msgstr "Impossibile creare file temporaneo\n"
+
+#: ../src/calibrate/calibrate.cpp:258
+#, c-format
+msgid "Calibrating: CPU usage on %i threads\n"
+msgstr "Calibrazione: uso CPU su %i threads\n"
+
+#: ../src/calibrate/calibrate.cpp:273
+#, c-format
+msgid "Calibrating: CPU wakeup power consumption\n"
+msgstr "Calibrazione: consumo energetico wakeup CPU\n"
+
+#: ../src/calibrate/calibrate.cpp:290
+#, c-format
+msgid "Calibrating USB devices\n"
+msgstr "Calibrazione dispositivi USB\n"
+
+#: ../src/calibrate/calibrate.cpp:292 ../src/calibrate/calibrate.cpp:309
+#: ../src/calibrate/calibrate.cpp:317 ../src/calibrate/calibrate.cpp:334
+#, c-format
+msgid ".... device %s \n"
+msgstr ".... dispositivo %s \n"
+
+#: ../src/calibrate/calibrate.cpp:307
+#, c-format
+msgid "Calibrating radio devices\n"
+msgstr "Calibrazione dispositivi radio\n"
+
+#: ../src/calibrate/calibrate.cpp:331
+#, c-format
+msgid "Calibrating backlight\n"
+msgstr "Calibrazione retroilluminazione\n"
+
+#: ../src/calibrate/calibrate.cpp:355 ../src/calibrate/calibrate.cpp:365
+#, c-format
+msgid "Calibrating idle\n"
+msgstr "Calibrazione idle\n"
+
+#: ../src/calibrate/calibrate.cpp:378
+#, c-format
+msgid "Calibrating: disk usage \n"
+msgstr "Calibrazione: uso disco \n"
+
+#: ../src/calibrate/calibrate.cpp:403
+msgid "Starting PowerTOP power estimate calibration \n"
+msgstr "Avvio calibrazione stima energetica PowerTOP \n"
+
+#: ../src/calibrate/calibrate.cpp:426
+msgid "Finishing PowerTOP power estimate calibration \n"
+msgstr "Termino calibrazione stima energetica PowerTOP \n"
+
+#: ../src/calibrate/calibrate.cpp:430
+#, c-format
+msgid "Parameters after calibration:\n"
+msgstr "Parametri dopo la calibrazione:\n"
+
+#: ../src/cpu/abstract_cpu.cpp:74
+msgid "Idle"
+msgstr ""
+
+#: ../src/cpu/abstract_cpu.cpp:76
+msgid "Turbo Mode"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:37
+#, fuzzy, c-format
+msgid " Core(HW)"
+msgstr " Core"
+
+#: ../src/cpu/cpu_core.cpp:37
+#, fuzzy, c-format
+msgid " Core(OS)"
+msgstr " Core"
+
+#: ../src/cpu/cpu_core.cpp:91 ../src/cpu/intel_cpus.cpp:324
+#, c-format
+msgid " Core"
+msgstr " Core"
+
+#: ../src/cpu/cpu.cpp:85
+#, c-format
+msgid "cpu package %i"
+msgstr "pacchetto cpu %i"
+
+#: ../src/cpu/cpu.cpp:86
+msgid "cpu package"
+msgstr "pacchetto cpu"
+
+#: ../src/cpu/cpu.cpp:89 ../src/cpu/cpu.cpp:96
+#, fuzzy, c-format
+msgid "package-%i"
+msgstr "Pacchetto %i"
+
+#: ../src/cpu/cpu.cpp:90
+msgid "cpu rapl package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:97
+msgid "dram rapl package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:471
+msgid "Processor Idle State Report"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:535 ../src/cpu/cpu.cpp:753
+msgid "Package"
+msgstr "Pacchetto"
+
+#: ../src/cpu/cpu.cpp:566 ../src/cpu/cpu.cpp:775
+#, fuzzy, c-format
+msgid "Core %d"
+msgstr "Core %i"
+
+#: ../src/cpu/cpu.cpp:573
+#, fuzzy, c-format
+msgid "GPU %d"
+msgstr "GPU %i"
+
+#: ../src/cpu/cpu.cpp:594
+#, fuzzy
+msgid "CPU"
+msgstr "CPU %i"
+
+#: ../src/cpu/cpu.cpp:676
+msgid "Processor Frequency Report"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:796
+#, fuzzy, c-format
+msgid "CPU %d"
+msgstr "CPU %i"
+
+#: ../src/cpu/cpu.cpp:997
+#, c-format
+msgid "cpu_idle event returned no state?\n"
+msgstr "l'evento cpu_idle non ha riportato alcuno stato?\n"
+
+#: ../src/cpu/cpu.cpp:1012
+#, c-format
+msgid "power or cpu_frequency event returned no state?\n"
+msgstr ""
+
+#: ../src/cpu/cpu_linux.cpp:79
+msgid "C0 polling"
+msgstr "C0 polling"
+
+#: ../src/cpu/cpu_linux.cpp:242
+#, fuzzy, c-format
+msgid " CPU(OS) %i"
+msgstr " CPU %i"
+
+#: ../src/cpu/cpu_linux.cpp:341 ../src/cpu/intel_cpus.cpp:651
+#, c-format
+msgid " CPU %i"
+msgstr " CPU %i"
+
+#: ../src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(HW)"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(OS)"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:104 ../src/cpu/intel_cpus.cpp:412
+#, c-format
+msgid " Package"
+msgstr " Pacchetto"
+
+#: ../src/cpu/intel_cpus.cpp:129
+#, c-format
+msgid "read_msr cpu%d 0x%llx : "
+msgstr ""
+
+#: ../src/cpu/intel_cpus.cpp:574
+msgid "C0 active"
+msgstr "C0 attivo"
+
+#: ../src/cpu/intel_cpus.cpp:632
+#, c-format
+msgid "Average"
+msgstr ""
+
+#: ../src/cpu/intel_gpu.cpp:64
+#, fuzzy, c-format
+msgid " GPU "
+msgstr "GPU %i"
+
+#: ../src/devices/ahci.cpp:154
+#, c-format
+msgid "SATA link: %s"
+msgstr "Link SATA: %s"
+
+#: ../src/devices/ahci.cpp:156
+#, c-format
+msgid "SATA disk: %s"
+msgstr "Disco SATA: %s"
+
+#: ../src/devices/ahci.cpp:374
+msgid "AHCI ALPM Residency Statistics - Not supported on this macine"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:389
+msgid "Link"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:390
+#, fuzzy
+msgid "Active"
+msgstr "C0 attivo"
+
+#: ../src/devices/ahci.cpp:391
+msgid "Partial"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:392
+msgid "Slumber"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:393
+msgid "Devslp"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:399
+msgid "AHCI ALPM Residency Statistics"
+msgstr ""
+
+#: ../src/devices/alsa.cpp:77
+#, c-format
+msgid "Audio codec %s: %s (%s)"
+msgstr "Codec audio %s: %s (%s)"
+
+#: ../src/devices/alsa.cpp:79 ../src/devices/alsa.cpp:81
+#, c-format
+msgid "Audio codec %s: %s"
+msgstr "Codec audio %s: %s"
+
+#: ../src/devices/devfreq.cpp:261
+#, fuzzy
+msgid "Device Freq stats"
+msgstr "Stat. dispos."
+
+#: ../src/devices/devfreq.cpp:279
+msgid " Devfreq is not enabled"
+msgstr ""
+
+#: ../src/devices/devfreq.cpp:284
+msgid " No devfreq devices available"
+msgstr ""
+
+#: ../src/devices/device.cpp:172 ../src/process/do_process.cpp:831
+#, c-format
+msgid "The battery reports a discharge rate of %sW\n"
+msgstr "La batteria riporta un tasso di scarica di %sW\n"
+
+#: ../src/devices/device.cpp:174 ../src/process/do_process.cpp:833
+#, c-format
+msgid "The power consumed was %sJ\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:180
+#, c-format
+msgid "System baseline power is estimated at %sW\n"
+msgstr "La potenza di base del sistema è stimata sui %sW\n"
+
+#: ../src/devices/device.cpp:187
+msgid "Power est. Usage Device name\n"
+msgstr "Potenza stim. Uso Nome dispositivo\n"
+
+#: ../src/devices/device.cpp:189
+msgid " Usage Device name\n"
+msgstr " Uso Nome dispositivo\n"
+
+#: ../src/devices/device.cpp:256
+#, fuzzy
+msgid "The battery reports a discharge rate of: "
+msgstr "La batteria riporta un tasso di scarica di %sW\n"
+
+#: ../src/devices/device.cpp:261
+msgid "The power consumed was : "
+msgstr ""
+
+#: ../src/devices/device.cpp:268
+#, fuzzy
+msgid "The system baseline power is estimated at: "
+msgstr "La potenza di base del sistema è stimata sui %sW\n"
+
+#: ../src/devices/device.cpp:277 ../src/process/do_process.cpp:850
+#: ../src/process/do_process.cpp:852 ../src/process/do_process.cpp:926
+#: ../src/process/do_process.cpp:1077
+msgid "Usage"
+msgstr "Uso"
+
+#: ../src/devices/device.cpp:278
+#, fuzzy
+msgid "Device Name"
+msgstr "Stat. dispos."
+
+#: ../src/devices/device.cpp:280 ../src/process/do_process.cpp:935
+#: ../src/process/do_process.cpp:1082
+msgid "PW Estimate"
+msgstr ""
+
+#. Report Output
+#: ../src/devices/device.cpp:317
+msgid "Device Power Report"
+msgstr ""
+
+#: ../src/devices/network.cpp:177
+#, c-format
+msgid "Network interface: %s (%s)"
+msgstr "Interfaccia di rete: %s (%s)"
+
+#: ../src/devices/rfkill.cpp:65 ../src/devices/rfkill.cpp:69
+#, c-format
+msgid "Radio device: %s"
+msgstr "Dispositivo Radio: %s"
+
+#: ../src/devices/runtime_pm.cpp:216
+#, c-format
+msgid "I2C %s (%s): %s"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216 ../src/tuning/tuningi2c.cpp:57
+#: ../src/tuning/tuningi2c.cpp:59
+msgid "Adapter"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216 ../src/devlist.cpp:331
+#: ../src/tuning/tuningi2c.cpp:57 ../src/tuning/tuningi2c.cpp:59
+#, fuzzy
+msgid "Device"
+msgstr "Stat. dispos."
+
+#: ../src/devices/runtime_pm.cpp:241
+#, c-format
+msgid "PCI Device: %s"
+msgstr "Dispositivo PCI: %s"
+
+#: ../src/devices/usb.cpp:51 ../src/devices/usb.cpp:96
+#: ../src/devices/usb.cpp:98
+#, c-format
+msgid "USB device: %s"
+msgstr "Dispositivo USB: %s"
+
+#: ../src/devices/usb.cpp:94
+#, c-format
+msgid "USB device: %s (%s)"
+msgstr "Dispositivo USB: %s (%s)"
+
+#: ../src/devlist.cpp:330
+msgid "Process"
+msgstr ""
+
+#. Report Output
+#. No div attribute here inherits from device power report
+#: ../src/devlist.cpp:347
+msgid "Process Device Activity"
+msgstr ""
+
+#: ../src/display.cpp:70
+msgid "Overview"
+msgstr "Riepilogo"
+
+#: ../src/display.cpp:71
+msgid "Idle stats"
+msgstr "Stat. idle"
+
+#: ../src/display.cpp:72
+msgid "Frequency stats"
+msgstr "Stat. frequenza"
+
+#: ../src/display.cpp:73
+msgid "Device stats"
+msgstr "Stat. dispos."
+
+#: ../src/display.cpp:131
+msgid "Exit"
+msgstr "Esci"
+
+#: ../src/display.cpp:132
+msgid "Navigate"
+msgstr ""
+
+#: ../src/lib.cpp:288
+#, c-format
+msgid "%7sW"
+msgstr "%7sW"
+
+#: ../src/lib.cpp:291
+#, c-format
+msgid " 0 mW"
+msgstr "0 mW"
+
+#: ../src/lib.cpp:410
+msgid "PS/2 Touchpad / Keyboard / Mouse"
+msgstr "Touchpad / Tastiera / Mouse PS/2"
+
+#: ../src/lib.cpp:411
+msgid "SATA controller"
+msgstr "Controller SATA"
+
+#: ../src/lib.cpp:412
+msgid "Intel built in USB hub"
+msgstr "Hub USB Intel integrato"
+
+#: ../src/lib.cpp:467
+#, c-format
+msgid "glob returned GLOB_NOSPACE\n"
+msgstr ""
+
+#: ../src/lib.cpp:471
+#, c-format
+msgid "glob returned GLOB_ABORTED\n"
+msgstr ""
+
+#: ../src/lib.cpp:475
+#, c-format
+msgid "glob returned GLOB_NOMATCH\n"
+msgstr ""
+
+#: ../src/lib.cpp:513 ../src/lib.cpp:549
+#, c-format
+msgid ""
+"Model-specific registers (MSR)\t\t\t not found (try enabling "
+"CONFIG_X86_MSR).\n"
+msgstr ""
+
+#: ../src/main.cpp:103
+#, fuzzy, c-format
+msgid "PowerTOP version "
+msgstr "Versione PowerTOP"
+
+#: ../src/main.cpp:109
+msgid "Set refresh time out"
+msgstr "Imposta time out del refresh"
+
+#: ../src/main.cpp:122
+msgid "Usage: powertop [OPTIONS]"
+msgstr "Uso: powertop [OPZIONI]"
+
+#: ../src/main.cpp:123
+msgid "sets all tunable options to their GOOD setting"
+msgstr ""
+
+#: ../src/main.cpp:124
+msgid "runs powertop in calibration mode"
+msgstr "avvia powertop in modalità calibrazione"
+
+#: ../src/main.cpp:125 ../src/main.cpp:128
+msgid "[=filename]"
+msgstr ""
+
+#: ../src/main.cpp:125
+msgid "generate a csv report"
+msgstr "genera un resoconto csv"
+
+#: ../src/main.cpp:126
+msgid "run in \"debug\" mode"
+msgstr "avvia in modalità \"debug\""
+
+#: ../src/main.cpp:127
+msgid "[=devnode]"
+msgstr "[=devnode]"
+
+#: ../src/main.cpp:127
+msgid "uses an Extech Power Analyzer for measurements"
+msgstr "usa un Analizzatore Energetico Extech per le misurazioni"
+
+#: ../src/main.cpp:128
+msgid "generate a html report"
+msgstr "genera un resoconto html"
+
+#: ../src/main.cpp:129
+msgid "[=iterations] number of times to run each test"
+msgstr "[=iterazioni] numero di esecuzioni per ogni test"
+
+#: ../src/main.cpp:130
+msgid "suppress stderr output"
+msgstr "sopprimi output stderr"
+
+#: ../src/main.cpp:131 ../src/main.cpp:132
+msgid "[=seconds]"
+msgstr "[=secondi]"
+
+#: ../src/main.cpp:131
+msgid "interval for power consumption measurement"
+msgstr ""
+
+#: ../src/main.cpp:132
+msgid "generate a report for 'x' seconds"
+msgstr "genera un resoconto per 'x' secondi"
+
+#: ../src/main.cpp:133
+msgid "[=workload]"
+msgstr ""
+
+#: ../src/main.cpp:133
+msgid "file to execute for workload"
+msgstr ""
+
+#: ../src/main.cpp:134
+msgid "print version information"
+msgstr "stampa informazioni sulla versione"
+
+#: ../src/main.cpp:135
+msgid "print this help menu"
+msgstr "stampa questo menu di aiuto"
+
+#: ../src/main.cpp:137
+#, fuzzy
+msgid "For more help please refer to the 'man 8 powertop'"
+msgstr "Per ulteriore aiuto si prega di rivolgersi al README"
+
+#: ../src/main.cpp:232
+#, c-format
+msgid "Unknown issue running workload!\n"
+msgstr ""
+
+#: ../src/main.cpp:289
+msgid "PowerTOP is out of memory. PowerTOP is Aborting"
+msgstr "PowerTOP non ha memoria disponibile. Uscita da PowerTOP"
+
+#. one to warm up everything
+#: ../src/main.cpp:297
+#, c-format
+msgid "Preparing to take measurements\n"
+msgstr "Preparazione per il rilevamento delle misure\n"
+
+#: ../src/main.cpp:302
+#, c-format
+msgid "Taking %d measurement(s) for a duration of %d second(s) each.\n"
+msgstr ""
+"Rilevamento di %d misurazione(i) per una durata di %d secondo(i) ciascuna.\n"
+
+#: ../src/main.cpp:304
+#, c-format
+msgid "Measuring workload %s.\n"
+msgstr ""
+
+#: ../src/main.cpp:329
+#, c-format
+msgid "PowerTOP "
+msgstr "PowerTOP "
+
+#: ../src/main.cpp:330 ../src/main.cpp:380
+#, c-format
+msgid "exiting...\n"
+msgstr "uscita...\n"
+
+#: ../src/main.cpp:364
+#, c-format
+msgid "modprobe cpufreq_stats failed"
+msgstr ""
+
+#: ../src/main.cpp:367
+#, c-format
+msgid "modprobe msr failed"
+msgstr ""
+
+#: ../src/main.cpp:379 ../src/main.cpp:383
+#, c-format
+msgid "Failed to mount debugfs!\n"
+msgstr "Impossibile montare debugfs!\n"
+
+#: ../src/main.cpp:384
+#, c-format
+msgid "Should still be able to auto tune...\n"
+msgstr ""
+
+#: ../src/main.cpp:466
+#, c-format
+msgid "Invalid CSV filename\n"
+msgstr ""
+
+#: ../src/main.cpp:482
+#, c-format
+msgid "Invalid HTML filename\n"
+msgstr ""
+
+#: ../src/main.cpp:491
+#, c-format
+msgid "Quiet mode failed!\n"
+msgstr ""
+
+#: ../src/main.cpp:559
+msgid "Leaving PowerTOP"
+msgstr "Uscita da PowerTOP"
+
+#: ../src/parameters/persistent.cpp:46 ../src/parameters/persistent.cpp:155
+msgid "Cannot save to file"
+msgstr "Impossibile salvare nel file"
+
+#: ../src/parameters/persistent.cpp:89 ../src/parameters/persistent.cpp:180
+msgid "Cannot load from file"
+msgstr "Impossibile caricare dal file"
+
+#. '%i" is for count, do not translate
+#: ../src/parameters/persistent.cpp:138
+#, c-format
+msgid "Loaded %i prior measurements\n"
+msgstr "Caricati %i prima delle misurazioni\n"
+
+#: ../src/parameters/persistent.cpp:181
+msgid ""
+"File will be loaded after taking minimum number of measurement(s) with "
+"battery only \n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:115
+#, c-format
+msgid ""
+"Too many open files, please increase the limit of open file descriptors.\n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:117
+#, c-format
+msgid "PowerTOP %s needs the kernel to support the 'perf' subsystem\n"
+msgstr "PowerTOP %s richiede il kernel per supportare il sottosistema 'perf'\n"
+
+#: ../src/perf/perf.cpp:118
+#, c-format
+msgid "as well as support for trace points in the kernel:\n"
+msgstr "e per supportare i trace points nel kernel:\n"
+
+#: ../src/process/do_process.cpp:819
+#, c-format
+msgid ""
+"Estimated power: %5.1f Measured power: %5.1f Sum: %5.1f\n"
+"\n"
+msgstr ""
+"Potenza stimata: %5.1f Potenza misurata: %5.1f Som: %5.1f\n"
+"\n"
+
+#: ../src/process/do_process.cpp:838
+#, c-format
+msgid "The estimated remaining time is %i hours, %i minutes\n"
+msgstr "Il tempo rimanente stimato è di %i ore, %i minuti\n"
+
+#: ../src/process/do_process.cpp:846
+msgid "Summary"
+msgstr "Riepilogo"
+
+#: ../src/process/do_process.cpp:846
+msgid "wakeups/second"
+msgstr "wakeup/secondo"
+
+#: ../src/process/do_process.cpp:846
+msgid "GPU ops/seconds"
+msgstr "GPU op/secondo"
+
+#: ../src/process/do_process.cpp:846
+msgid "VFS ops/sec and"
+msgstr "VFS op/sec e"
+
+#: ../src/process/do_process.cpp:846
+msgid "CPU use"
+msgstr "uso CPU"
+
+#: ../src/process/do_process.cpp:850
+msgid "Power est."
+msgstr "Stima energetica"
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:1078
+msgid "Events/s"
+msgstr "Eventi/s"
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:931 ../src/process/do_process.cpp:1079
+msgid "Category"
+msgstr "Categoria"
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:932 ../src/process/do_process.cpp:1080
+#: ../src/tuning/tuning.cpp:242 ../src/tuning/tuning.cpp:270
+#: ../src/tuning/tuning.cpp:288 ../src/wakeup/waketab.cpp:155
+msgid "Description"
+msgstr "Descrizione"
+
+#: ../src/process/do_process.cpp:927
+msgid "Wakeups/s"
+msgstr "Wakeup/s"
+
+#: ../src/process/do_process.cpp:928
+msgid "GPU ops/s"
+msgstr "GPU op/s"
+
+#: ../src/process/do_process.cpp:929
+msgid "Disk IO/s"
+msgstr "Disco IO/s"
+
+#: ../src/process/do_process.cpp:930
+msgid "GFX Wakeups/s"
+msgstr "GFX Wakeup/s"
+
+#: ../src/process/do_process.cpp:1017
+msgid "Overview of Software Power Consumers"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1057
+msgid "Target:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1058
+msgid "1 units/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1059
+msgid "System: "
+msgstr ""
+
+#: ../src/process/do_process.cpp:1061
+#, fuzzy
+msgid " wakeup/s"
+msgstr "Wakeup/s"
+
+#: ../src/process/do_process.cpp:1062
+msgid "CPU: "
+msgstr ""
+
+#: ../src/process/do_process.cpp:1064
+#, fuzzy, c-format
+msgid "% usage"
+msgstr "Uso"
+
+#: ../src/process/do_process.cpp:1065
+msgid "GPU:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1067 ../src/process/do_process.cpp:1073
+#, fuzzy
+msgid " ops/s"
+msgstr "GPU op/s"
+
+#: ../src/process/do_process.cpp:1068
+msgid "GFX:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1070
+#, fuzzy
+msgid " wakeups/s"
+msgstr "Wakeup/s"
+
+#: ../src/process/do_process.cpp:1071
+msgid "VFS:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1139
+msgid "Top 10 Power Consumers"
+msgstr ""
+
+#: ../src/report/report.cpp:122
+#, fuzzy
+msgid "PowerTOP Version"
+msgstr "Versione PowerTOP"
+
+#: ../src/report/report.cpp:131
+#, fuzzy
+msgid "Kernel Version"
+msgstr "Versione PowerTOP"
+
+#: ../src/report/report.cpp:135
+msgid "System Name"
+msgstr ""
+
+#: ../src/report/report.cpp:142
+msgid "CPU Information"
+msgstr ""
+
+#: ../src/report/report.cpp:154
+msgid "OS Information"
+msgstr ""
+
+#: ../src/report/report.cpp:161
+#, fuzzy
+msgid "System Information"
+msgstr "stampa informazioni sulla versione"
+
+#: ../src/report/report.cpp:195
+#, fuzzy, c-format
+msgid "Cannot open output file %s (%s)\n"
+msgstr "Impossibile creare file temporaneo\n"
+
+#: ../src/report/report.cpp:211
+#, c-format
+msgid "PowerTOP outputing using base filename %s\n"
+msgstr ""
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:49
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+msgid "Good"
+msgstr "Positivo"
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:50
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+msgid "Bad"
+msgstr "Negativo"
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:51
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+#: ../src/wakeup/wakeup.cpp:50
+msgid "Unknown"
+msgstr "Sconosciuto"
+
+#: ../src/tuning/bluetooth.cpp:48
+#, c-format
+msgid "Bluetooth device interface status"
+msgstr "Stato interfaccia dispositivo bluetooth"
+
+#: ../src/tuning/ethernet.cpp:54 ../src/wakeup/wakeup_ethernet.cpp:51
+#, c-format
+msgid "Wake-on-lan status for device %s"
+msgstr "Stato wake-on-lan per il dispositivo %s"
+
+#: ../src/tuning/runtime.cpp:48
+#, c-format
+msgid "Runtime PM for %s device %s"
+msgstr "PM runtime per %s dispositivo %s"
+
+#: ../src/tuning/runtime.cpp:50
+#, c-format
+msgid "%s device %s has no runtime power management"
+msgstr "%s dispositivo %s non ha alcuna gestione energetica runtime"
+
+#: ../src/tuning/runtime.cpp:74
+#, c-format
+msgid "PCI Device %s has no runtime power management"
+msgstr "Il dispositivo PCI %s non ha alcuna gestione energetica runtime"
+
+#: ../src/tuning/runtime.cpp:76
+#, c-format
+msgid "Runtime PM for PCI Device %s"
+msgstr "PM runtime per il dispositivo PCI %s"
+
+#: ../src/tuning/tuning.cpp:62
+msgid "Enable Audio codec power management"
+msgstr "Abilitazione della gestione energetica dei codec audio"
+
+#: ../src/tuning/tuning.cpp:63
+msgid "NMI watchdog should be turned off"
+msgstr "NMI watchdog dovrebbe essere disattivato"
+
+#: ../src/tuning/tuning.cpp:64
+msgid "Power Aware CPU scheduler"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:65
+msgid "VM writeback timeout"
+msgstr "Timeout del VM writeback"
+
+#: ../src/tuning/tuning.cpp:81
+msgid "Tunables"
+msgstr "Regolazioni"
+
+#: ../src/tuning/tuning.cpp:81
+msgid " <ESC> Exit | <Enter> Toggle tunable | <r> Window refresh"
+msgstr " <ESC> Esci | <Invio> Commuta regolazione | <r> Aggiorna finestra"
+
+#: ../src/tuning/tuning.cpp:243 ../src/wakeup/waketab.cpp:156
+msgid "Script"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:257
+msgid "Software Settings in Need of Tuning"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:276
+msgid "Untunable Software Issues"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:300
+msgid "Optimal Tuned Software Settings"
+msgstr ""
+
+#: ../src/tuning/tuningi2c.cpp:57
+#, fuzzy, c-format
+msgid "Runtime PM for I2C %s %s (%s)"
+msgstr "PM runtime per %s dispositivo %s"
+
+#: ../src/tuning/tuningi2c.cpp:59
+#, fuzzy, c-format
+msgid "I2C %s %s has no runtime power management"
+msgstr "%s dispositivo %s non ha alcuna gestione energetica runtime"
+
+#: ../src/tuning/tuningsysfs.cpp:123
+#, fuzzy, c-format
+msgid "Enable SATA link power management for %s"
+msgstr "Abilita gestione energetica link SATA per %s"
+
+#: ../src/tuning/tuningusb.cpp:54
+#, c-format
+msgid "Autosuspend for unknown USB device %s (%s:%s)"
+msgstr "Autosospensione per il dispositivo USB sconosciuto %s (%s:%s)"
+
+#: ../src/tuning/tuningusb.cpp:71 ../src/tuning/tuningusb.cpp:73
+#: ../src/tuning/tuningusb.cpp:75
+#, c-format
+msgid "Autosuspend for USB device %s [%s]"
+msgstr "Autosospensione per il dispositivo USB %s [%s]"
+
+#: ../src/tuning/wifi.cpp:48
+#, c-format
+msgid "Wireless Power Saving for interface %s"
+msgstr "Risparmio energetico del dispositivo senza fili per l'interfaccia %s"
+
+#: ../src/wakeup/waketab.cpp:42
+#, fuzzy
+msgid "WakeUp"
+msgstr "Wakeup/s"
+
+#: ../src/wakeup/waketab.cpp:42
+#, fuzzy
+msgid " <ESC> Exit | <Enter> Toggle wakeup | <r> Window refresh"
+msgstr " <ESC> Esci | <Invio> Commuta regolazione | <r> Aggiorna finestra"
+
+#. Report Output
+#: ../src/wakeup/waketab.cpp:170
+#, fuzzy
+msgid "Wake status of the devices"
+msgstr "Stato wake-on-lan per il dispositivo %s"
+
+#: ../src/wakeup/wakeup.cpp:48 ../src/wakeup/wakeup_ethernet.cpp:47
+#: ../src/wakeup/wakeup_usb.cpp:47
+#, fuzzy
+msgid "Enable"
+msgstr "Regolazioni"
+
+#: ../src/wakeup/wakeup.cpp:49 ../src/wakeup/wakeup_ethernet.cpp:47
+#: ../src/wakeup/wakeup_usb.cpp:47
+msgid "Disable"
+msgstr ""
+
+#: ../src/wakeup/wakeup_usb.cpp:51
+#, fuzzy, c-format
+msgid "Wake status for USB device %s"
+msgstr "Stato wake-on-lan per il dispositivo %s"
+
+#~ msgid "Actual"
+#~ msgstr "Attuale"
+
+#~ msgid "Power Consumption Summary"
+#~ msgstr "Riepilogo Consumo Energetico"
+
+#~ msgid "GPU ops/second"
+#~ msgstr "GPU op/secondo"
+
+#~ msgid "VFS ops/sec"
+#~ msgstr "VFS op/sec"
+
+#~ msgid "GFX wakes/sec and"
+#~ msgstr "GFX wake/sec e"
+
+#~ msgid "Using 'ondemand' cpufreq governor"
+#~ msgstr "Uso del regolatore \"ondemand\" della frequenza della CPU"
+
+#~ msgid "[=FILENAME]"
+#~ msgstr "[=NOMEFILE]"
diff --git a/po/ja_JP.po b/po/ja_JP.po
new file mode 100644
index 0000000..ff83211
--- /dev/null
+++ b/po/ja_JP.po
@@ -0,0 +1,951 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Intel Corporation
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: PowerTOP\n"
+"Report-Msgid-Bugs-To: powertop@lists.01.org\n"
+"POT-Creation-Date: 2019-01-04 13:55-0800\n"
+"PO-Revision-Date: 2013-11-05 08:40+0000\n"
+"Last-Translator: Margie Foster <margie@linux.intel.com>\n"
+"Language-Team: Japanese (Japan) (http://www.transifex.com/projects/p/"
+"PowerTOP/language/ja_JP/)\n"
+"Language: ja_JP\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: ../src/calibrate/calibrate.cpp:238
+#, c-format
+msgid "Cannot create temp file\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:258
+#, c-format
+msgid "Calibrating: CPU usage on %i threads\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:273
+#, c-format
+msgid "Calibrating: CPU wakeup power consumption\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:290
+#, c-format
+msgid "Calibrating USB devices\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:292 ../src/calibrate/calibrate.cpp:309
+#: ../src/calibrate/calibrate.cpp:317 ../src/calibrate/calibrate.cpp:334
+#, c-format
+msgid ".... device %s \n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:307
+#, c-format
+msgid "Calibrating radio devices\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:331
+#, c-format
+msgid "Calibrating backlight\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:355 ../src/calibrate/calibrate.cpp:365
+#, c-format
+msgid "Calibrating idle\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:378
+#, c-format
+msgid "Calibrating: disk usage \n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:403
+msgid "Starting PowerTOP power estimate calibration \n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:426
+msgid "Finishing PowerTOP power estimate calibration \n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:430
+#, c-format
+msgid "Parameters after calibration:\n"
+msgstr ""
+
+#: ../src/cpu/abstract_cpu.cpp:74
+msgid "Idle"
+msgstr ""
+
+#: ../src/cpu/abstract_cpu.cpp:76
+msgid "Turbo Mode"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(HW)"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(OS)"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:91 ../src/cpu/intel_cpus.cpp:324
+#, c-format
+msgid " Core"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:85
+#, c-format
+msgid "cpu package %i"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:86
+msgid "cpu package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:89 ../src/cpu/cpu.cpp:96
+#, c-format
+msgid "package-%i"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:90
+msgid "cpu rapl package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:97
+msgid "dram rapl package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:471
+msgid "Processor Idle State Report"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:535 ../src/cpu/cpu.cpp:753
+msgid "Package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:566 ../src/cpu/cpu.cpp:775
+#, c-format
+msgid "Core %d"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:573
+#, c-format
+msgid "GPU %d"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:594
+msgid "CPU"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:676
+msgid "Processor Frequency Report"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:796
+#, c-format
+msgid "CPU %d"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:997
+#, c-format
+msgid "cpu_idle event returned no state?\n"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:1012
+#, c-format
+msgid "power or cpu_frequency event returned no state?\n"
+msgstr ""
+
+#: ../src/cpu/cpu_linux.cpp:79
+msgid "C0 polling"
+msgstr ""
+
+#: ../src/cpu/cpu_linux.cpp:242
+#, c-format
+msgid " CPU(OS) %i"
+msgstr ""
+
+#: ../src/cpu/cpu_linux.cpp:341 ../src/cpu/intel_cpus.cpp:651
+#, c-format
+msgid " CPU %i"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(HW)"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(OS)"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:104 ../src/cpu/intel_cpus.cpp:412
+#, c-format
+msgid " Package"
+msgstr ""
+
+#: ../src/cpu/intel_cpus.cpp:129
+#, c-format
+msgid "read_msr cpu%d 0x%llx : "
+msgstr ""
+
+#: ../src/cpu/intel_cpus.cpp:574
+msgid "C0 active"
+msgstr ""
+
+#: ../src/cpu/intel_cpus.cpp:632
+#, c-format
+msgid "Average"
+msgstr ""
+
+#: ../src/cpu/intel_gpu.cpp:64
+#, c-format
+msgid " GPU "
+msgstr ""
+
+#: ../src/devices/ahci.cpp:154
+#, c-format
+msgid "SATA link: %s"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:156
+#, c-format
+msgid "SATA disk: %s"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:374
+msgid "AHCI ALPM Residency Statistics - Not supported on this macine"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:389
+msgid "Link"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:390
+msgid "Active"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:391
+msgid "Partial"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:392
+msgid "Slumber"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:393
+msgid "Devslp"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:399
+msgid "AHCI ALPM Residency Statistics"
+msgstr ""
+
+#: ../src/devices/alsa.cpp:77
+#, c-format
+msgid "Audio codec %s: %s (%s)"
+msgstr ""
+
+#: ../src/devices/alsa.cpp:79 ../src/devices/alsa.cpp:81
+#, c-format
+msgid "Audio codec %s: %s"
+msgstr ""
+
+#: ../src/devices/devfreq.cpp:261
+msgid "Device Freq stats"
+msgstr ""
+
+#: ../src/devices/devfreq.cpp:279
+msgid " Devfreq is not enabled"
+msgstr ""
+
+#: ../src/devices/devfreq.cpp:284
+msgid " No devfreq devices available"
+msgstr ""
+
+#: ../src/devices/device.cpp:172 ../src/process/do_process.cpp:831
+#, c-format
+msgid "The battery reports a discharge rate of %sW\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:174 ../src/process/do_process.cpp:833
+#, c-format
+msgid "The power consumed was %sJ\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:180
+#, c-format
+msgid "System baseline power is estimated at %sW\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:187
+msgid "Power est. Usage Device name\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:189
+msgid " Usage Device name\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:256
+msgid "The battery reports a discharge rate of: "
+msgstr ""
+
+#: ../src/devices/device.cpp:261
+msgid "The power consumed was : "
+msgstr ""
+
+#: ../src/devices/device.cpp:268
+msgid "The system baseline power is estimated at: "
+msgstr ""
+
+#: ../src/devices/device.cpp:277 ../src/process/do_process.cpp:850
+#: ../src/process/do_process.cpp:852 ../src/process/do_process.cpp:926
+#: ../src/process/do_process.cpp:1077
+msgid "Usage"
+msgstr ""
+
+#: ../src/devices/device.cpp:278
+msgid "Device Name"
+msgstr ""
+
+#: ../src/devices/device.cpp:280 ../src/process/do_process.cpp:935
+#: ../src/process/do_process.cpp:1082
+msgid "PW Estimate"
+msgstr ""
+
+#. Report Output
+#: ../src/devices/device.cpp:317
+msgid "Device Power Report"
+msgstr ""
+
+#: ../src/devices/network.cpp:177
+#, c-format
+msgid "Network interface: %s (%s)"
+msgstr ""
+
+#: ../src/devices/rfkill.cpp:65 ../src/devices/rfkill.cpp:69
+#, c-format
+msgid "Radio device: %s"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216
+#, c-format
+msgid "I2C %s (%s): %s"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216 ../src/tuning/tuningi2c.cpp:57
+#: ../src/tuning/tuningi2c.cpp:59
+msgid "Adapter"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216 ../src/devlist.cpp:331
+#: ../src/tuning/tuningi2c.cpp:57 ../src/tuning/tuningi2c.cpp:59
+msgid "Device"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:241
+#, c-format
+msgid "PCI Device: %s"
+msgstr ""
+
+#: ../src/devices/usb.cpp:51 ../src/devices/usb.cpp:96
+#: ../src/devices/usb.cpp:98
+#, c-format
+msgid "USB device: %s"
+msgstr ""
+
+#: ../src/devices/usb.cpp:94
+#, c-format
+msgid "USB device: %s (%s)"
+msgstr ""
+
+#: ../src/devlist.cpp:330
+msgid "Process"
+msgstr ""
+
+#. Report Output
+#. No div attribute here inherits from device power report
+#: ../src/devlist.cpp:347
+msgid "Process Device Activity"
+msgstr ""
+
+#: ../src/display.cpp:70
+msgid "Overview"
+msgstr ""
+
+#: ../src/display.cpp:71
+msgid "Idle stats"
+msgstr ""
+
+#: ../src/display.cpp:72
+msgid "Frequency stats"
+msgstr ""
+
+#: ../src/display.cpp:73
+msgid "Device stats"
+msgstr ""
+
+#: ../src/display.cpp:131
+msgid "Exit"
+msgstr ""
+
+#: ../src/display.cpp:132
+msgid "Navigate"
+msgstr ""
+
+#: ../src/lib.cpp:288
+#, c-format
+msgid "%7sW"
+msgstr ""
+
+#: ../src/lib.cpp:291
+#, c-format
+msgid " 0 mW"
+msgstr ""
+
+#: ../src/lib.cpp:410
+msgid "PS/2 Touchpad / Keyboard / Mouse"
+msgstr ""
+
+#: ../src/lib.cpp:411
+msgid "SATA controller"
+msgstr ""
+
+#: ../src/lib.cpp:412
+msgid "Intel built in USB hub"
+msgstr ""
+
+#: ../src/lib.cpp:467
+#, c-format
+msgid "glob returned GLOB_NOSPACE\n"
+msgstr ""
+
+#: ../src/lib.cpp:471
+#, c-format
+msgid "glob returned GLOB_ABORTED\n"
+msgstr ""
+
+#: ../src/lib.cpp:475
+#, c-format
+msgid "glob returned GLOB_NOMATCH\n"
+msgstr ""
+
+#: ../src/lib.cpp:513 ../src/lib.cpp:549
+#, c-format
+msgid ""
+"Model-specific registers (MSR)\t\t\t not found (try enabling "
+"CONFIG_X86_MSR).\n"
+msgstr ""
+
+#: ../src/main.cpp:103
+#, c-format
+msgid "PowerTOP version "
+msgstr ""
+
+#: ../src/main.cpp:109
+msgid "Set refresh time out"
+msgstr ""
+
+#: ../src/main.cpp:122
+msgid "Usage: powertop [OPTIONS]"
+msgstr ""
+
+#: ../src/main.cpp:123
+msgid "sets all tunable options to their GOOD setting"
+msgstr ""
+
+#: ../src/main.cpp:124
+msgid "runs powertop in calibration mode"
+msgstr ""
+
+#: ../src/main.cpp:125 ../src/main.cpp:128
+msgid "[=filename]"
+msgstr ""
+
+#: ../src/main.cpp:125
+msgid "generate a csv report"
+msgstr ""
+
+#: ../src/main.cpp:126
+msgid "run in \"debug\" mode"
+msgstr ""
+
+#: ../src/main.cpp:127
+msgid "[=devnode]"
+msgstr ""
+
+#: ../src/main.cpp:127
+msgid "uses an Extech Power Analyzer for measurements"
+msgstr ""
+
+#: ../src/main.cpp:128
+msgid "generate a html report"
+msgstr ""
+
+#: ../src/main.cpp:129
+msgid "[=iterations] number of times to run each test"
+msgstr ""
+
+#: ../src/main.cpp:130
+msgid "suppress stderr output"
+msgstr ""
+
+#: ../src/main.cpp:131 ../src/main.cpp:132
+msgid "[=seconds]"
+msgstr ""
+
+#: ../src/main.cpp:131
+msgid "interval for power consumption measurement"
+msgstr ""
+
+#: ../src/main.cpp:132
+msgid "generate a report for 'x' seconds"
+msgstr ""
+
+#: ../src/main.cpp:133
+msgid "[=workload]"
+msgstr ""
+
+#: ../src/main.cpp:133
+msgid "file to execute for workload"
+msgstr ""
+
+#: ../src/main.cpp:134
+msgid "print version information"
+msgstr ""
+
+#: ../src/main.cpp:135
+msgid "print this help menu"
+msgstr ""
+
+#: ../src/main.cpp:137
+msgid "For more help please refer to the 'man 8 powertop'"
+msgstr ""
+
+#: ../src/main.cpp:232
+#, c-format
+msgid "Unknown issue running workload!\n"
+msgstr ""
+
+#: ../src/main.cpp:289
+msgid "PowerTOP is out of memory. PowerTOP is Aborting"
+msgstr ""
+
+#. one to warm up everything
+#: ../src/main.cpp:297
+#, c-format
+msgid "Preparing to take measurements\n"
+msgstr ""
+
+#: ../src/main.cpp:302
+#, c-format
+msgid "Taking %d measurement(s) for a duration of %d second(s) each.\n"
+msgstr ""
+
+#: ../src/main.cpp:304
+#, c-format
+msgid "Measuring workload %s.\n"
+msgstr ""
+
+#: ../src/main.cpp:329
+#, c-format
+msgid "PowerTOP "
+msgstr ""
+
+#: ../src/main.cpp:330 ../src/main.cpp:380
+#, c-format
+msgid "exiting...\n"
+msgstr ""
+
+#: ../src/main.cpp:364
+#, c-format
+msgid "modprobe cpufreq_stats failed"
+msgstr ""
+
+#: ../src/main.cpp:367
+#, c-format
+msgid "modprobe msr failed"
+msgstr ""
+
+#: ../src/main.cpp:379 ../src/main.cpp:383
+#, c-format
+msgid "Failed to mount debugfs!\n"
+msgstr ""
+
+#: ../src/main.cpp:384
+#, c-format
+msgid "Should still be able to auto tune...\n"
+msgstr ""
+
+#: ../src/main.cpp:466
+#, c-format
+msgid "Invalid CSV filename\n"
+msgstr ""
+
+#: ../src/main.cpp:482
+#, c-format
+msgid "Invalid HTML filename\n"
+msgstr ""
+
+#: ../src/main.cpp:491
+#, c-format
+msgid "Quiet mode failed!\n"
+msgstr ""
+
+#: ../src/main.cpp:559
+msgid "Leaving PowerTOP"
+msgstr ""
+
+#: ../src/parameters/persistent.cpp:46 ../src/parameters/persistent.cpp:155
+msgid "Cannot save to file"
+msgstr ""
+
+#: ../src/parameters/persistent.cpp:89 ../src/parameters/persistent.cpp:180
+msgid "Cannot load from file"
+msgstr ""
+
+#. '%i" is for count, do not translate
+#: ../src/parameters/persistent.cpp:138
+#, c-format
+msgid "Loaded %i prior measurements\n"
+msgstr ""
+
+#: ../src/parameters/persistent.cpp:181
+msgid ""
+"File will be loaded after taking minimum number of measurement(s) with "
+"battery only \n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:115
+#, c-format
+msgid ""
+"Too many open files, please increase the limit of open file descriptors.\n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:117
+#, c-format
+msgid "PowerTOP %s needs the kernel to support the 'perf' subsystem\n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:118
+#, c-format
+msgid "as well as support for trace points in the kernel:\n"
+msgstr ""
+
+#: ../src/process/do_process.cpp:819
+#, c-format
+msgid ""
+"Estimated power: %5.1f Measured power: %5.1f Sum: %5.1f\n"
+"\n"
+msgstr ""
+
+#: ../src/process/do_process.cpp:838
+#, c-format
+msgid "The estimated remaining time is %i hours, %i minutes\n"
+msgstr ""
+
+#: ../src/process/do_process.cpp:846
+msgid "Summary"
+msgstr ""
+
+#: ../src/process/do_process.cpp:846
+msgid "wakeups/second"
+msgstr ""
+
+#: ../src/process/do_process.cpp:846
+msgid "GPU ops/seconds"
+msgstr ""
+
+#: ../src/process/do_process.cpp:846
+msgid "VFS ops/sec and"
+msgstr ""
+
+#: ../src/process/do_process.cpp:846
+msgid "CPU use"
+msgstr ""
+
+#: ../src/process/do_process.cpp:850
+msgid "Power est."
+msgstr ""
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:1078
+msgid "Events/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:931 ../src/process/do_process.cpp:1079
+msgid "Category"
+msgstr ""
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:932 ../src/process/do_process.cpp:1080
+#: ../src/tuning/tuning.cpp:242 ../src/tuning/tuning.cpp:270
+#: ../src/tuning/tuning.cpp:288 ../src/wakeup/waketab.cpp:155
+msgid "Description"
+msgstr ""
+
+#: ../src/process/do_process.cpp:927
+msgid "Wakeups/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:928
+msgid "GPU ops/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:929
+msgid "Disk IO/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:930
+msgid "GFX Wakeups/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1017
+msgid "Overview of Software Power Consumers"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1057
+msgid "Target:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1058
+msgid "1 units/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1059
+msgid "System: "
+msgstr ""
+
+#: ../src/process/do_process.cpp:1061
+msgid " wakeup/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1062
+msgid "CPU: "
+msgstr ""
+
+#: ../src/process/do_process.cpp:1064
+#, c-format
+msgid "% usage"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1065
+msgid "GPU:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1067 ../src/process/do_process.cpp:1073
+msgid " ops/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1068
+msgid "GFX:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1070
+msgid " wakeups/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1071
+msgid "VFS:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1139
+msgid "Top 10 Power Consumers"
+msgstr ""
+
+#: ../src/report/report.cpp:122
+msgid "PowerTOP Version"
+msgstr ""
+
+#: ../src/report/report.cpp:131
+msgid "Kernel Version"
+msgstr ""
+
+#: ../src/report/report.cpp:135
+msgid "System Name"
+msgstr ""
+
+#: ../src/report/report.cpp:142
+msgid "CPU Information"
+msgstr ""
+
+#: ../src/report/report.cpp:154
+msgid "OS Information"
+msgstr ""
+
+#: ../src/report/report.cpp:161
+msgid "System Information"
+msgstr ""
+
+#: ../src/report/report.cpp:195
+#, c-format
+msgid "Cannot open output file %s (%s)\n"
+msgstr ""
+
+#: ../src/report/report.cpp:211
+#, c-format
+msgid "PowerTOP outputing using base filename %s\n"
+msgstr ""
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:49
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+msgid "Good"
+msgstr ""
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:50
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+msgid "Bad"
+msgstr ""
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:51
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+#: ../src/wakeup/wakeup.cpp:50
+msgid "Unknown"
+msgstr ""
+
+#: ../src/tuning/bluetooth.cpp:48
+#, c-format
+msgid "Bluetooth device interface status"
+msgstr ""
+
+#: ../src/tuning/ethernet.cpp:54 ../src/wakeup/wakeup_ethernet.cpp:51
+#, c-format
+msgid "Wake-on-lan status for device %s"
+msgstr ""
+
+#: ../src/tuning/runtime.cpp:48
+#, c-format
+msgid "Runtime PM for %s device %s"
+msgstr ""
+
+#: ../src/tuning/runtime.cpp:50
+#, c-format
+msgid "%s device %s has no runtime power management"
+msgstr ""
+
+#: ../src/tuning/runtime.cpp:74
+#, c-format
+msgid "PCI Device %s has no runtime power management"
+msgstr ""
+
+#: ../src/tuning/runtime.cpp:76
+#, c-format
+msgid "Runtime PM for PCI Device %s"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:62
+msgid "Enable Audio codec power management"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:63
+msgid "NMI watchdog should be turned off"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:64
+msgid "Power Aware CPU scheduler"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:65
+msgid "VM writeback timeout"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:81
+msgid "Tunables"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:81
+msgid " <ESC> Exit | <Enter> Toggle tunable | <r> Window refresh"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:243 ../src/wakeup/waketab.cpp:156
+msgid "Script"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:257
+msgid "Software Settings in Need of Tuning"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:276
+msgid "Untunable Software Issues"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:300
+msgid "Optimal Tuned Software Settings"
+msgstr ""
+
+#: ../src/tuning/tuningi2c.cpp:57
+#, c-format
+msgid "Runtime PM for I2C %s %s (%s)"
+msgstr ""
+
+#: ../src/tuning/tuningi2c.cpp:59
+#, c-format
+msgid "I2C %s %s has no runtime power management"
+msgstr ""
+
+#: ../src/tuning/tuningsysfs.cpp:123
+#, c-format
+msgid "Enable SATA link power management for %s"
+msgstr ""
+
+#: ../src/tuning/tuningusb.cpp:54
+#, c-format
+msgid "Autosuspend for unknown USB device %s (%s:%s)"
+msgstr ""
+
+#: ../src/tuning/tuningusb.cpp:71 ../src/tuning/tuningusb.cpp:73
+#: ../src/tuning/tuningusb.cpp:75
+#, c-format
+msgid "Autosuspend for USB device %s [%s]"
+msgstr ""
+
+#: ../src/tuning/wifi.cpp:48
+#, c-format
+msgid "Wireless Power Saving for interface %s"
+msgstr ""
+
+#: ../src/wakeup/waketab.cpp:42
+msgid "WakeUp"
+msgstr ""
+
+#: ../src/wakeup/waketab.cpp:42
+msgid " <ESC> Exit | <Enter> Toggle wakeup | <r> Window refresh"
+msgstr ""
+
+#. Report Output
+#: ../src/wakeup/waketab.cpp:170
+msgid "Wake status of the devices"
+msgstr ""
+
+#: ../src/wakeup/wakeup.cpp:48 ../src/wakeup/wakeup_ethernet.cpp:47
+#: ../src/wakeup/wakeup_usb.cpp:47
+msgid "Enable"
+msgstr ""
+
+#: ../src/wakeup/wakeup.cpp:49 ../src/wakeup/wakeup_ethernet.cpp:47
+#: ../src/wakeup/wakeup_usb.cpp:47
+msgid "Disable"
+msgstr ""
+
+#: ../src/wakeup/wakeup_usb.cpp:51
+#, c-format
+msgid "Wake status for USB device %s"
+msgstr ""
diff --git a/po/ko.po b/po/ko.po
new file mode 100644
index 0000000..994ff20
--- /dev/null
+++ b/po/ko.po
@@ -0,0 +1,955 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Intel Corporation
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Patrick McCarty <patrick.mccarty@linux.intel.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: PowerTOP\n"
+"Report-Msgid-Bugs-To: powertop@lists.01.org\n"
+"POT-Creation-Date: 2019-01-04 13:55-0800\n"
+"PO-Revision-Date: 2013-11-05 08:40+0000\n"
+"Last-Translator: Margie Foster <margie@linux.intel.com>\n"
+"Language-Team: Korean (http://www.transifex.com/projects/p/PowerTOP/language/"
+"ko/)\n"
+"Language: ko\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: ../src/calibrate/calibrate.cpp:238
+#, c-format
+msgid "Cannot create temp file\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:258
+#, c-format
+msgid "Calibrating: CPU usage on %i threads\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:273
+#, c-format
+msgid "Calibrating: CPU wakeup power consumption\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:290
+#, c-format
+msgid "Calibrating USB devices\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:292 ../src/calibrate/calibrate.cpp:309
+#: ../src/calibrate/calibrate.cpp:317 ../src/calibrate/calibrate.cpp:334
+#, c-format
+msgid ".... device %s \n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:307
+#, c-format
+msgid "Calibrating radio devices\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:331
+#, c-format
+msgid "Calibrating backlight\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:355 ../src/calibrate/calibrate.cpp:365
+#, c-format
+msgid "Calibrating idle\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:378
+#, c-format
+msgid "Calibrating: disk usage \n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:403
+msgid "Starting PowerTOP power estimate calibration \n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:426
+msgid "Finishing PowerTOP power estimate calibration \n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:430
+#, c-format
+msgid "Parameters after calibration:\n"
+msgstr ""
+
+#: ../src/cpu/abstract_cpu.cpp:74
+msgid "Idle"
+msgstr ""
+
+#: ../src/cpu/abstract_cpu.cpp:76
+msgid "Turbo Mode"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(HW)"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(OS)"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:91 ../src/cpu/intel_cpus.cpp:324
+#, c-format
+msgid " Core"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:85
+#, c-format
+msgid "cpu package %i"
+msgstr "cpu 패키지 %i"
+
+#: ../src/cpu/cpu.cpp:86
+msgid "cpu package"
+msgstr "cpu 패키지"
+
+#: ../src/cpu/cpu.cpp:89 ../src/cpu/cpu.cpp:96
+#, fuzzy, c-format
+msgid "package-%i"
+msgstr "cpu 패키지 %i"
+
+#: ../src/cpu/cpu.cpp:90
+msgid "cpu rapl package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:97
+msgid "dram rapl package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:471
+msgid "Processor Idle State Report"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:535 ../src/cpu/cpu.cpp:753
+msgid "Package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:566 ../src/cpu/cpu.cpp:775
+#, c-format
+msgid "Core %d"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:573
+#, c-format
+msgid "GPU %d"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:594
+msgid "CPU"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:676
+msgid "Processor Frequency Report"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:796
+#, c-format
+msgid "CPU %d"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:997
+#, c-format
+msgid "cpu_idle event returned no state?\n"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:1012
+#, c-format
+msgid "power or cpu_frequency event returned no state?\n"
+msgstr ""
+
+#: ../src/cpu/cpu_linux.cpp:79
+msgid "C0 polling"
+msgstr ""
+
+#: ../src/cpu/cpu_linux.cpp:242
+#, c-format
+msgid " CPU(OS) %i"
+msgstr ""
+
+#: ../src/cpu/cpu_linux.cpp:341 ../src/cpu/intel_cpus.cpp:651
+#, c-format
+msgid " CPU %i"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(HW)"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(OS)"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:104 ../src/cpu/intel_cpus.cpp:412
+#, c-format
+msgid " Package"
+msgstr ""
+
+#: ../src/cpu/intel_cpus.cpp:129
+#, c-format
+msgid "read_msr cpu%d 0x%llx : "
+msgstr ""
+
+#: ../src/cpu/intel_cpus.cpp:574
+msgid "C0 active"
+msgstr ""
+
+#: ../src/cpu/intel_cpus.cpp:632
+#, c-format
+msgid "Average"
+msgstr ""
+
+#: ../src/cpu/intel_gpu.cpp:64
+#, c-format
+msgid " GPU "
+msgstr ""
+
+#: ../src/devices/ahci.cpp:154
+#, c-format
+msgid "SATA link: %s"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:156
+#, c-format
+msgid "SATA disk: %s"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:374
+msgid "AHCI ALPM Residency Statistics - Not supported on this macine"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:389
+msgid "Link"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:390
+msgid "Active"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:391
+msgid "Partial"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:392
+msgid "Slumber"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:393
+msgid "Devslp"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:399
+msgid "AHCI ALPM Residency Statistics"
+msgstr ""
+
+#: ../src/devices/alsa.cpp:77
+#, c-format
+msgid "Audio codec %s: %s (%s)"
+msgstr ""
+
+#: ../src/devices/alsa.cpp:79 ../src/devices/alsa.cpp:81
+#, c-format
+msgid "Audio codec %s: %s"
+msgstr ""
+
+#: ../src/devices/devfreq.cpp:261
+#, fuzzy
+msgid "Device Freq stats"
+msgstr "장치 통계"
+
+#: ../src/devices/devfreq.cpp:279
+msgid " Devfreq is not enabled"
+msgstr ""
+
+#: ../src/devices/devfreq.cpp:284
+msgid " No devfreq devices available"
+msgstr ""
+
+#: ../src/devices/device.cpp:172 ../src/process/do_process.cpp:831
+#, c-format
+msgid "The battery reports a discharge rate of %sW\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:174 ../src/process/do_process.cpp:833
+#, c-format
+msgid "The power consumed was %sJ\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:180
+#, c-format
+msgid "System baseline power is estimated at %sW\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:187
+msgid "Power est. Usage Device name\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:189
+msgid " Usage Device name\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:256
+msgid "The battery reports a discharge rate of: "
+msgstr ""
+
+#: ../src/devices/device.cpp:261
+msgid "The power consumed was : "
+msgstr ""
+
+#: ../src/devices/device.cpp:268
+msgid "The system baseline power is estimated at: "
+msgstr ""
+
+#: ../src/devices/device.cpp:277 ../src/process/do_process.cpp:850
+#: ../src/process/do_process.cpp:852 ../src/process/do_process.cpp:926
+#: ../src/process/do_process.cpp:1077
+msgid "Usage"
+msgstr ""
+
+#: ../src/devices/device.cpp:278
+#, fuzzy
+msgid "Device Name"
+msgstr "장치 통계"
+
+#: ../src/devices/device.cpp:280 ../src/process/do_process.cpp:935
+#: ../src/process/do_process.cpp:1082
+msgid "PW Estimate"
+msgstr ""
+
+#. Report Output
+#: ../src/devices/device.cpp:317
+msgid "Device Power Report"
+msgstr ""
+
+#: ../src/devices/network.cpp:177
+#, c-format
+msgid "Network interface: %s (%s)"
+msgstr ""
+
+#: ../src/devices/rfkill.cpp:65 ../src/devices/rfkill.cpp:69
+#, c-format
+msgid "Radio device: %s"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216
+#, c-format
+msgid "I2C %s (%s): %s"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216 ../src/tuning/tuningi2c.cpp:57
+#: ../src/tuning/tuningi2c.cpp:59
+msgid "Adapter"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216 ../src/devlist.cpp:331
+#: ../src/tuning/tuningi2c.cpp:57 ../src/tuning/tuningi2c.cpp:59
+#, fuzzy
+msgid "Device"
+msgstr "장치 통계"
+
+#: ../src/devices/runtime_pm.cpp:241
+#, c-format
+msgid "PCI Device: %s"
+msgstr ""
+
+#: ../src/devices/usb.cpp:51 ../src/devices/usb.cpp:96
+#: ../src/devices/usb.cpp:98
+#, c-format
+msgid "USB device: %s"
+msgstr ""
+
+#: ../src/devices/usb.cpp:94
+#, c-format
+msgid "USB device: %s (%s)"
+msgstr ""
+
+#: ../src/devlist.cpp:330
+msgid "Process"
+msgstr ""
+
+#. Report Output
+#. No div attribute here inherits from device power report
+#: ../src/devlist.cpp:347
+msgid "Process Device Activity"
+msgstr ""
+
+#: ../src/display.cpp:70
+msgid "Overview"
+msgstr "개요"
+
+#: ../src/display.cpp:71
+msgid "Idle stats"
+msgstr "유휴 통계"
+
+#: ../src/display.cpp:72
+msgid "Frequency stats"
+msgstr "주파수 통계"
+
+#: ../src/display.cpp:73
+msgid "Device stats"
+msgstr "장치 통계"
+
+#: ../src/display.cpp:131
+msgid "Exit"
+msgstr ""
+
+#: ../src/display.cpp:132
+msgid "Navigate"
+msgstr ""
+
+#: ../src/lib.cpp:288
+#, c-format
+msgid "%7sW"
+msgstr ""
+
+#: ../src/lib.cpp:291
+#, c-format
+msgid " 0 mW"
+msgstr ""
+
+#: ../src/lib.cpp:410
+msgid "PS/2 Touchpad / Keyboard / Mouse"
+msgstr ""
+
+#: ../src/lib.cpp:411
+msgid "SATA controller"
+msgstr ""
+
+#: ../src/lib.cpp:412
+msgid "Intel built in USB hub"
+msgstr ""
+
+#: ../src/lib.cpp:467
+#, c-format
+msgid "glob returned GLOB_NOSPACE\n"
+msgstr ""
+
+#: ../src/lib.cpp:471
+#, c-format
+msgid "glob returned GLOB_ABORTED\n"
+msgstr ""
+
+#: ../src/lib.cpp:475
+#, c-format
+msgid "glob returned GLOB_NOMATCH\n"
+msgstr ""
+
+#: ../src/lib.cpp:513 ../src/lib.cpp:549
+#, c-format
+msgid ""
+"Model-specific registers (MSR)\t\t\t not found (try enabling "
+"CONFIG_X86_MSR).\n"
+msgstr ""
+
+#: ../src/main.cpp:103
+#, c-format
+msgid "PowerTOP version "
+msgstr ""
+
+#: ../src/main.cpp:109
+msgid "Set refresh time out"
+msgstr ""
+
+#: ../src/main.cpp:122
+msgid "Usage: powertop [OPTIONS]"
+msgstr ""
+
+#: ../src/main.cpp:123
+msgid "sets all tunable options to their GOOD setting"
+msgstr ""
+
+#: ../src/main.cpp:124
+msgid "runs powertop in calibration mode"
+msgstr ""
+
+#: ../src/main.cpp:125 ../src/main.cpp:128
+msgid "[=filename]"
+msgstr ""
+
+#: ../src/main.cpp:125
+msgid "generate a csv report"
+msgstr ""
+
+#: ../src/main.cpp:126
+msgid "run in \"debug\" mode"
+msgstr ""
+
+#: ../src/main.cpp:127
+msgid "[=devnode]"
+msgstr ""
+
+#: ../src/main.cpp:127
+msgid "uses an Extech Power Analyzer for measurements"
+msgstr ""
+
+#: ../src/main.cpp:128
+msgid "generate a html report"
+msgstr ""
+
+#: ../src/main.cpp:129
+msgid "[=iterations] number of times to run each test"
+msgstr ""
+
+#: ../src/main.cpp:130
+msgid "suppress stderr output"
+msgstr ""
+
+#: ../src/main.cpp:131 ../src/main.cpp:132
+msgid "[=seconds]"
+msgstr ""
+
+#: ../src/main.cpp:131
+msgid "interval for power consumption measurement"
+msgstr ""
+
+#: ../src/main.cpp:132
+msgid "generate a report for 'x' seconds"
+msgstr ""
+
+#: ../src/main.cpp:133
+msgid "[=workload]"
+msgstr ""
+
+#: ../src/main.cpp:133
+msgid "file to execute for workload"
+msgstr ""
+
+#: ../src/main.cpp:134
+msgid "print version information"
+msgstr ""
+
+#: ../src/main.cpp:135
+msgid "print this help menu"
+msgstr ""
+
+#: ../src/main.cpp:137
+msgid "For more help please refer to the 'man 8 powertop'"
+msgstr ""
+
+#: ../src/main.cpp:232
+#, c-format
+msgid "Unknown issue running workload!\n"
+msgstr ""
+
+#: ../src/main.cpp:289
+msgid "PowerTOP is out of memory. PowerTOP is Aborting"
+msgstr ""
+
+#. one to warm up everything
+#: ../src/main.cpp:297
+#, c-format
+msgid "Preparing to take measurements\n"
+msgstr ""
+
+#: ../src/main.cpp:302
+#, c-format
+msgid "Taking %d measurement(s) for a duration of %d second(s) each.\n"
+msgstr ""
+
+#: ../src/main.cpp:304
+#, c-format
+msgid "Measuring workload %s.\n"
+msgstr ""
+
+#: ../src/main.cpp:329
+#, c-format
+msgid "PowerTOP "
+msgstr ""
+
+#: ../src/main.cpp:330 ../src/main.cpp:380
+#, c-format
+msgid "exiting...\n"
+msgstr ""
+
+#: ../src/main.cpp:364
+#, c-format
+msgid "modprobe cpufreq_stats failed"
+msgstr ""
+
+#: ../src/main.cpp:367
+#, c-format
+msgid "modprobe msr failed"
+msgstr ""
+
+#: ../src/main.cpp:379 ../src/main.cpp:383
+#, c-format
+msgid "Failed to mount debugfs!\n"
+msgstr ""
+
+#: ../src/main.cpp:384
+#, c-format
+msgid "Should still be able to auto tune...\n"
+msgstr ""
+
+#: ../src/main.cpp:466
+#, c-format
+msgid "Invalid CSV filename\n"
+msgstr ""
+
+#: ../src/main.cpp:482
+#, c-format
+msgid "Invalid HTML filename\n"
+msgstr ""
+
+#: ../src/main.cpp:491
+#, c-format
+msgid "Quiet mode failed!\n"
+msgstr ""
+
+#: ../src/main.cpp:559
+msgid "Leaving PowerTOP"
+msgstr ""
+
+#: ../src/parameters/persistent.cpp:46 ../src/parameters/persistent.cpp:155
+msgid "Cannot save to file"
+msgstr ""
+
+#: ../src/parameters/persistent.cpp:89 ../src/parameters/persistent.cpp:180
+msgid "Cannot load from file"
+msgstr ""
+
+#. '%i" is for count, do not translate
+#: ../src/parameters/persistent.cpp:138
+#, c-format
+msgid "Loaded %i prior measurements\n"
+msgstr "로드 %i 사전 측정\n"
+
+#: ../src/parameters/persistent.cpp:181
+msgid ""
+"File will be loaded after taking minimum number of measurement(s) with "
+"battery only \n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:115
+#, c-format
+msgid ""
+"Too many open files, please increase the limit of open file descriptors.\n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:117
+#, c-format
+msgid "PowerTOP %s needs the kernel to support the 'perf' subsystem\n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:118
+#, c-format
+msgid "as well as support for trace points in the kernel:\n"
+msgstr ""
+
+#: ../src/process/do_process.cpp:819
+#, c-format
+msgid ""
+"Estimated power: %5.1f Measured power: %5.1f Sum: %5.1f\n"
+"\n"
+msgstr ""
+
+#: ../src/process/do_process.cpp:838
+#, c-format
+msgid "The estimated remaining time is %i hours, %i minutes\n"
+msgstr ""
+
+#: ../src/process/do_process.cpp:846
+msgid "Summary"
+msgstr ""
+
+#: ../src/process/do_process.cpp:846
+msgid "wakeups/second"
+msgstr ""
+
+#: ../src/process/do_process.cpp:846
+msgid "GPU ops/seconds"
+msgstr ""
+
+#: ../src/process/do_process.cpp:846
+msgid "VFS ops/sec and"
+msgstr ""
+
+#: ../src/process/do_process.cpp:846
+msgid "CPU use"
+msgstr ""
+
+#: ../src/process/do_process.cpp:850
+msgid "Power est."
+msgstr ""
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:1078
+msgid "Events/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:931 ../src/process/do_process.cpp:1079
+msgid "Category"
+msgstr ""
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:932 ../src/process/do_process.cpp:1080
+#: ../src/tuning/tuning.cpp:242 ../src/tuning/tuning.cpp:270
+#: ../src/tuning/tuning.cpp:288 ../src/wakeup/waketab.cpp:155
+msgid "Description"
+msgstr ""
+
+#: ../src/process/do_process.cpp:927
+msgid "Wakeups/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:928
+msgid "GPU ops/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:929
+msgid "Disk IO/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:930
+msgid "GFX Wakeups/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1017
+msgid "Overview of Software Power Consumers"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1057
+msgid "Target:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1058
+msgid "1 units/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1059
+msgid "System: "
+msgstr ""
+
+#: ../src/process/do_process.cpp:1061
+msgid " wakeup/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1062
+msgid "CPU: "
+msgstr ""
+
+#: ../src/process/do_process.cpp:1064
+#, c-format
+msgid "% usage"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1065
+msgid "GPU:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1067 ../src/process/do_process.cpp:1073
+msgid " ops/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1068
+msgid "GFX:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1070
+msgid " wakeups/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1071
+msgid "VFS:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1139
+msgid "Top 10 Power Consumers"
+msgstr ""
+
+#: ../src/report/report.cpp:122
+msgid "PowerTOP Version"
+msgstr ""
+
+#: ../src/report/report.cpp:131
+msgid "Kernel Version"
+msgstr ""
+
+#: ../src/report/report.cpp:135
+msgid "System Name"
+msgstr ""
+
+#: ../src/report/report.cpp:142
+msgid "CPU Information"
+msgstr ""
+
+#: ../src/report/report.cpp:154
+msgid "OS Information"
+msgstr ""
+
+#: ../src/report/report.cpp:161
+msgid "System Information"
+msgstr ""
+
+#: ../src/report/report.cpp:195
+#, c-format
+msgid "Cannot open output file %s (%s)\n"
+msgstr ""
+
+#: ../src/report/report.cpp:211
+#, c-format
+msgid "PowerTOP outputing using base filename %s\n"
+msgstr ""
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:49
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+msgid "Good"
+msgstr ""
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:50
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+msgid "Bad"
+msgstr "나쁜"
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:51
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+#: ../src/wakeup/wakeup.cpp:50
+msgid "Unknown"
+msgstr ""
+
+#: ../src/tuning/bluetooth.cpp:48
+#, c-format
+msgid "Bluetooth device interface status"
+msgstr ""
+
+#: ../src/tuning/ethernet.cpp:54 ../src/wakeup/wakeup_ethernet.cpp:51
+#, c-format
+msgid "Wake-on-lan status for device %s"
+msgstr ""
+
+#: ../src/tuning/runtime.cpp:48
+#, c-format
+msgid "Runtime PM for %s device %s"
+msgstr ""
+
+#: ../src/tuning/runtime.cpp:50
+#, c-format
+msgid "%s device %s has no runtime power management"
+msgstr ""
+
+#: ../src/tuning/runtime.cpp:74
+#, c-format
+msgid "PCI Device %s has no runtime power management"
+msgstr ""
+
+#: ../src/tuning/runtime.cpp:76
+#, c-format
+msgid "Runtime PM for PCI Device %s"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:62
+msgid "Enable Audio codec power management"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:63
+msgid "NMI watchdog should be turned off"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:64
+msgid "Power Aware CPU scheduler"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:65
+msgid "VM writeback timeout"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:81
+msgid "Tunables"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:81
+msgid " <ESC> Exit | <Enter> Toggle tunable | <r> Window refresh"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:243 ../src/wakeup/waketab.cpp:156
+msgid "Script"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:257
+msgid "Software Settings in Need of Tuning"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:276
+msgid "Untunable Software Issues"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:300
+msgid "Optimal Tuned Software Settings"
+msgstr ""
+
+#: ../src/tuning/tuningi2c.cpp:57
+#, c-format
+msgid "Runtime PM for I2C %s %s (%s)"
+msgstr ""
+
+#: ../src/tuning/tuningi2c.cpp:59
+#, c-format
+msgid "I2C %s %s has no runtime power management"
+msgstr ""
+
+#: ../src/tuning/tuningsysfs.cpp:123
+#, c-format
+msgid "Enable SATA link power management for %s"
+msgstr ""
+
+#: ../src/tuning/tuningusb.cpp:54
+#, c-format
+msgid "Autosuspend for unknown USB device %s (%s:%s)"
+msgstr ""
+
+#: ../src/tuning/tuningusb.cpp:71 ../src/tuning/tuningusb.cpp:73
+#: ../src/tuning/tuningusb.cpp:75
+#, c-format
+msgid "Autosuspend for USB device %s [%s]"
+msgstr ""
+
+#: ../src/tuning/wifi.cpp:48
+#, c-format
+msgid "Wireless Power Saving for interface %s"
+msgstr ""
+
+#: ../src/wakeup/waketab.cpp:42
+msgid "WakeUp"
+msgstr ""
+
+#: ../src/wakeup/waketab.cpp:42
+msgid " <ESC> Exit | <Enter> Toggle wakeup | <r> Window refresh"
+msgstr ""
+
+#. Report Output
+#: ../src/wakeup/waketab.cpp:170
+msgid "Wake status of the devices"
+msgstr ""
+
+#: ../src/wakeup/wakeup.cpp:48 ../src/wakeup/wakeup_ethernet.cpp:47
+#: ../src/wakeup/wakeup_usb.cpp:47
+msgid "Enable"
+msgstr ""
+
+#: ../src/wakeup/wakeup.cpp:49 ../src/wakeup/wakeup_ethernet.cpp:47
+#: ../src/wakeup/wakeup_usb.cpp:47
+msgid "Disable"
+msgstr ""
+
+#: ../src/wakeup/wakeup_usb.cpp:51
+#, c-format
+msgid "Wake status for USB device %s"
+msgstr ""
diff --git a/po/lt.po b/po/lt.po
new file mode 100644
index 0000000..c1debf2
--- /dev/null
+++ b/po/lt.po
@@ -0,0 +1,993 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Intel Corporation
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Simonas Kazlauskas <simonas@kazlauskas.me>, 2012-2013
+msgid ""
+msgstr ""
+"Project-Id-Version: PowerTOP\n"
+"Report-Msgid-Bugs-To: powertop@lists.01.org\n"
+"POT-Creation-Date: 2019-01-04 13:55-0800\n"
+"PO-Revision-Date: 2013-11-05 08:40+0000\n"
+"Last-Translator: Margie Foster <margie@linux.intel.com>\n"
+"Language-Team: Lithuanian (http://www.transifex.com/projects/p/PowerTOP/"
+"language/lt/)\n"
+"Language: lt\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n"
+"%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#: ../src/calibrate/calibrate.cpp:238
+#, c-format
+msgid "Cannot create temp file\n"
+msgstr "Negalima sukurti laikino failo\\n"
+
+#: ../src/calibrate/calibrate.cpp:258
+#, c-format
+msgid "Calibrating: CPU usage on %i threads\n"
+msgstr "Kalibruojama: procesoriaus sąnaudos veikiant %i gijoms\\n"
+
+#: ../src/calibrate/calibrate.cpp:273
+#, c-format
+msgid "Calibrating: CPU wakeup power consumption\n"
+msgstr "Kalibruojama: procesoriaus pabudimų energijos sąnaudos\\n"
+
+#: ../src/calibrate/calibrate.cpp:290
+#, c-format
+msgid "Calibrating USB devices\n"
+msgstr "Kalibruojami USB įrenginiai\\n"
+
+#: ../src/calibrate/calibrate.cpp:292 ../src/calibrate/calibrate.cpp:309
+#: ../src/calibrate/calibrate.cpp:317 ../src/calibrate/calibrate.cpp:334
+#, c-format
+msgid ".... device %s \n"
+msgstr "… įrenginys %s\\n"
+
+#: ../src/calibrate/calibrate.cpp:307
+#, c-format
+msgid "Calibrating radio devices\n"
+msgstr "Kalibruojami radijo imtuvai\\n"
+
+#: ../src/calibrate/calibrate.cpp:331
+#, c-format
+msgid "Calibrating backlight\n"
+msgstr "Kalibruojamas apšvietimas\\n"
+
+#: ../src/calibrate/calibrate.cpp:355 ../src/calibrate/calibrate.cpp:365
+#, c-format
+msgid "Calibrating idle\n"
+msgstr "Kalibruojama neveika\\n"
+
+#: ../src/calibrate/calibrate.cpp:378
+#, c-format
+msgid "Calibrating: disk usage \n"
+msgstr "Kalibruojama: disko naudojimas\\n"
+
+#: ../src/calibrate/calibrate.cpp:403
+msgid "Starting PowerTOP power estimate calibration \n"
+msgstr "Pradedama PowerTop energijos vertinimo kalibracija\\n"
+
+#: ../src/calibrate/calibrate.cpp:426
+msgid "Finishing PowerTOP power estimate calibration \n"
+msgstr "Užbaigiama PowerTOP energijos vertinimo kalibracija\\n"
+
+#: ../src/calibrate/calibrate.cpp:430
+#, c-format
+msgid "Parameters after calibration:\n"
+msgstr "Parametrai po kalibracijos:\\n"
+
+#: ../src/cpu/abstract_cpu.cpp:74
+msgid "Idle"
+msgstr ""
+
+#: ../src/cpu/abstract_cpu.cpp:76
+msgid "Turbo Mode"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:37
+#, fuzzy, c-format
+msgid " Core(HW)"
+msgstr "Branduolys"
+
+#: ../src/cpu/cpu_core.cpp:37
+#, fuzzy, c-format
+msgid " Core(OS)"
+msgstr "Branduolys"
+
+#: ../src/cpu/cpu_core.cpp:91 ../src/cpu/intel_cpus.cpp:324
+#, c-format
+msgid " Core"
+msgstr "Branduolys"
+
+#: ../src/cpu/cpu.cpp:85
+#, c-format
+msgid "cpu package %i"
+msgstr "%i procesorių paketas"
+
+#: ../src/cpu/cpu.cpp:86
+msgid "cpu package"
+msgstr "procesorių paketas"
+
+#: ../src/cpu/cpu.cpp:89 ../src/cpu/cpu.cpp:96
+#, fuzzy, c-format
+msgid "package-%i"
+msgstr "%i paketas"
+
+#: ../src/cpu/cpu.cpp:90
+msgid "cpu rapl package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:97
+msgid "dram rapl package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:471
+msgid "Processor Idle State Report"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:535 ../src/cpu/cpu.cpp:753
+msgid "Package"
+msgstr "Paketas"
+
+#: ../src/cpu/cpu.cpp:566 ../src/cpu/cpu.cpp:775
+#, fuzzy, c-format
+msgid "Core %d"
+msgstr "%i branduolys"
+
+#: ../src/cpu/cpu.cpp:573
+#, fuzzy, c-format
+msgid "GPU %d"
+msgstr "%i vaizdo plokštė"
+
+#: ../src/cpu/cpu.cpp:594
+#, fuzzy
+msgid "CPU"
+msgstr "%i procesorius"
+
+#: ../src/cpu/cpu.cpp:676
+msgid "Processor Frequency Report"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:796
+#, fuzzy, c-format
+msgid "CPU %d"
+msgstr "%i procesorius"
+
+#: ../src/cpu/cpu.cpp:997
+#, c-format
+msgid "cpu_idle event returned no state?\n"
+msgstr "cpu_idle įvykis negrąžino būsenos?\\n"
+
+#: ../src/cpu/cpu.cpp:1012
+#, c-format
+msgid "power or cpu_frequency event returned no state?\n"
+msgstr "power arba cpu_frequency įvykis negrąžino būsenos?\\n"
+
+#: ../src/cpu/cpu_linux.cpp:79
+msgid "C0 polling"
+msgstr "C0 laukia"
+
+#: ../src/cpu/cpu_linux.cpp:242
+#, fuzzy, c-format
+msgid " CPU(OS) %i"
+msgstr "%i procesorius"
+
+#: ../src/cpu/cpu_linux.cpp:341 ../src/cpu/intel_cpus.cpp:651
+#, c-format
+msgid " CPU %i"
+msgstr "%i procesorius"
+
+#: ../src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(HW)"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(OS)"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:104 ../src/cpu/intel_cpus.cpp:412
+#, c-format
+msgid " Package"
+msgstr "Paketas"
+
+#: ../src/cpu/intel_cpus.cpp:129
+#, c-format
+msgid "read_msr cpu%d 0x%llx : "
+msgstr ""
+
+#: ../src/cpu/intel_cpus.cpp:574
+msgid "C0 active"
+msgstr "C0 aktyvus"
+
+#: ../src/cpu/intel_cpus.cpp:632
+#, c-format
+msgid "Average"
+msgstr ""
+
+#: ../src/cpu/intel_gpu.cpp:64
+#, fuzzy, c-format
+msgid " GPU "
+msgstr "%i vaizdo plokštė"
+
+#: ../src/devices/ahci.cpp:154
+#, c-format
+msgid "SATA link: %s"
+msgstr "SATA sąsaja: %s"
+
+#: ../src/devices/ahci.cpp:156
+#, c-format
+msgid "SATA disk: %s"
+msgstr "SATA diskas: %s"
+
+#: ../src/devices/ahci.cpp:374
+msgid "AHCI ALPM Residency Statistics - Not supported on this macine"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:389
+msgid "Link"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:390
+#, fuzzy
+msgid "Active"
+msgstr "C0 aktyvus"
+
+#: ../src/devices/ahci.cpp:391
+msgid "Partial"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:392
+msgid "Slumber"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:393
+msgid "Devslp"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:399
+msgid "AHCI ALPM Residency Statistics"
+msgstr ""
+
+#: ../src/devices/alsa.cpp:77
+#, c-format
+msgid "Audio codec %s: %s (%s)"
+msgstr "Garso kodekas %s: %s (%s)"
+
+#: ../src/devices/alsa.cpp:79 ../src/devices/alsa.cpp:81
+#, c-format
+msgid "Audio codec %s: %s"
+msgstr "Garso kodekas %s: %s"
+
+#: ../src/devices/devfreq.cpp:261
+#, fuzzy
+msgid "Device Freq stats"
+msgstr "Įrenginių statistika"
+
+#: ../src/devices/devfreq.cpp:279
+msgid " Devfreq is not enabled"
+msgstr ""
+
+#: ../src/devices/devfreq.cpp:284
+msgid " No devfreq devices available"
+msgstr ""
+
+#: ../src/devices/device.cpp:172 ../src/process/do_process.cpp:831
+#, c-format
+msgid "The battery reports a discharge rate of %sW\n"
+msgstr "Akumuliatorius praneša %sW išsikrovimo greitį\\n"
+
+#: ../src/devices/device.cpp:174 ../src/process/do_process.cpp:833
+#, c-format
+msgid "The power consumed was %sJ\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:180
+#, c-format
+msgid "System baseline power is estimated at %sW\n"
+msgstr "Apytikrė Sistemos bazinė energija yra %sW\\n"
+
+#: ../src/devices/device.cpp:187
+msgid "Power est. Usage Device name\n"
+msgstr "Apytikrė energija Naudojimas Įrenginio vardas\\n"
+
+#: ../src/devices/device.cpp:189
+msgid " Usage Device name\n"
+msgstr "Sąnaudos Įrenginio pavadinimas\\n"
+
+#: ../src/devices/device.cpp:256
+#, fuzzy
+msgid "The battery reports a discharge rate of: "
+msgstr "Akumuliatorius praneša %sW išsikrovimo greitį\\n"
+
+#: ../src/devices/device.cpp:261
+msgid "The power consumed was : "
+msgstr ""
+
+#: ../src/devices/device.cpp:268
+#, fuzzy
+msgid "The system baseline power is estimated at: "
+msgstr "Apytikrė Sistemos bazinė energija yra %sW\\n"
+
+#: ../src/devices/device.cpp:277 ../src/process/do_process.cpp:850
+#: ../src/process/do_process.cpp:852 ../src/process/do_process.cpp:926
+#: ../src/process/do_process.cpp:1077
+msgid "Usage"
+msgstr "Naudojimas"
+
+#: ../src/devices/device.cpp:278
+#, fuzzy
+msgid "Device Name"
+msgstr "Įrenginių statistika"
+
+#: ../src/devices/device.cpp:280 ../src/process/do_process.cpp:935
+#: ../src/process/do_process.cpp:1082
+msgid "PW Estimate"
+msgstr ""
+
+#. Report Output
+#: ../src/devices/device.cpp:317
+msgid "Device Power Report"
+msgstr ""
+
+#: ../src/devices/network.cpp:177
+#, c-format
+msgid "Network interface: %s (%s)"
+msgstr "Tinklo sąsaja: %s (%s)"
+
+#: ../src/devices/rfkill.cpp:65 ../src/devices/rfkill.cpp:69
+#, c-format
+msgid "Radio device: %s"
+msgstr "Radijo imtuvas: %s"
+
+#: ../src/devices/runtime_pm.cpp:216
+#, c-format
+msgid "I2C %s (%s): %s"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216 ../src/tuning/tuningi2c.cpp:57
+#: ../src/tuning/tuningi2c.cpp:59
+msgid "Adapter"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216 ../src/devlist.cpp:331
+#: ../src/tuning/tuningi2c.cpp:57 ../src/tuning/tuningi2c.cpp:59
+#, fuzzy
+msgid "Device"
+msgstr "Įrenginių statistika"
+
+#: ../src/devices/runtime_pm.cpp:241
+#, c-format
+msgid "PCI Device: %s"
+msgstr "PCI įrenginys: %s"
+
+#: ../src/devices/usb.cpp:51 ../src/devices/usb.cpp:96
+#: ../src/devices/usb.cpp:98
+#, c-format
+msgid "USB device: %s"
+msgstr "USB įrenginys: %s"
+
+#: ../src/devices/usb.cpp:94
+#, c-format
+msgid "USB device: %s (%s)"
+msgstr "USB įrenginys: %s (%s)"
+
+#: ../src/devlist.cpp:330
+msgid "Process"
+msgstr ""
+
+#. Report Output
+#. No div attribute here inherits from device power report
+#: ../src/devlist.cpp:347
+msgid "Process Device Activity"
+msgstr ""
+
+#: ../src/display.cpp:70
+msgid "Overview"
+msgstr "Apžvalga"
+
+#: ../src/display.cpp:71
+msgid "Idle stats"
+msgstr "Neveikos statistika"
+
+#: ../src/display.cpp:72
+msgid "Frequency stats"
+msgstr "Dažnių statistika"
+
+#: ../src/display.cpp:73
+msgid "Device stats"
+msgstr "Įrenginių statistika"
+
+#: ../src/display.cpp:131
+msgid "Exit"
+msgstr "Išeiti"
+
+#: ../src/display.cpp:132
+msgid "Navigate"
+msgstr ""
+
+#: ../src/lib.cpp:288
+#, c-format
+msgid "%7sW"
+msgstr "%7sW"
+
+#: ../src/lib.cpp:291
+#, c-format
+msgid " 0 mW"
+msgstr "0 mW"
+
+#: ../src/lib.cpp:410
+msgid "PS/2 Touchpad / Keyboard / Mouse"
+msgstr "PS/2 Jutiklinis kilimėlis / Klaviatūra / Pėlė"
+
+#: ../src/lib.cpp:411
+msgid "SATA controller"
+msgstr "SATA kontroleris"
+
+#: ../src/lib.cpp:412
+msgid "Intel built in USB hub"
+msgstr "Integruotas Intel USB centras"
+
+#: ../src/lib.cpp:467
+#, c-format
+msgid "glob returned GLOB_NOSPACE\n"
+msgstr ""
+
+#: ../src/lib.cpp:471
+#, c-format
+msgid "glob returned GLOB_ABORTED\n"
+msgstr ""
+
+#: ../src/lib.cpp:475
+#, c-format
+msgid "glob returned GLOB_NOMATCH\n"
+msgstr ""
+
+#: ../src/lib.cpp:513 ../src/lib.cpp:549
+#, c-format
+msgid ""
+"Model-specific registers (MSR)\t\t\t not found (try enabling "
+"CONFIG_X86_MSR).\n"
+msgstr ""
+
+#: ../src/main.cpp:103
+#, fuzzy, c-format
+msgid "PowerTOP version "
+msgstr "PowerTOP versija"
+
+#: ../src/main.cpp:109
+msgid "Set refresh time out"
+msgstr "Nustatyti atnaujimui skirtą laiką"
+
+#: ../src/main.cpp:122
+msgid "Usage: powertop [OPTIONS]"
+msgstr "Naudojimas: powertop [NUOSTATOS]"
+
+#: ../src/main.cpp:123
+msgid "sets all tunable options to their GOOD setting"
+msgstr ""
+
+#: ../src/main.cpp:124
+msgid "runs powertop in calibration mode"
+msgstr "leidžia powertop kalibravimo režimu"
+
+#: ../src/main.cpp:125 ../src/main.cpp:128
+msgid "[=filename]"
+msgstr ""
+
+#: ../src/main.cpp:125
+msgid "generate a csv report"
+msgstr "generuoti raportą csv formatu"
+
+#: ../src/main.cpp:126
+msgid "run in \"debug\" mode"
+msgstr "paleisti derinimo režimu"
+
+#: ../src/main.cpp:127
+msgid "[=devnode]"
+msgstr "[=įrenginio mazgas]"
+
+#: ../src/main.cpp:127
+msgid "uses an Extech Power Analyzer for measurements"
+msgstr "Matavimams naudojamas Extech energijos analizatorius"
+
+#: ../src/main.cpp:128
+msgid "generate a html report"
+msgstr "generuoti raportą html formatu"
+
+#: ../src/main.cpp:129
+msgid "[=iterations] number of times to run each test"
+msgstr "[=iteracijos] kiekvieno testo atlikimų skaičius"
+
+#: ../src/main.cpp:130
+msgid "suppress stderr output"
+msgstr "Užtildyti stderr išvestį"
+
+#: ../src/main.cpp:131 ../src/main.cpp:132
+msgid "[=seconds]"
+msgstr "[=sekundės]"
+
+#: ../src/main.cpp:131
+msgid "interval for power consumption measurement"
+msgstr ""
+
+#: ../src/main.cpp:132
+msgid "generate a report for 'x' seconds"
+msgstr "generuoti x sekundžių raportą"
+
+#: ../src/main.cpp:133
+msgid "[=workload]"
+msgstr "[=apkrova]"
+
+#: ../src/main.cpp:133
+msgid "file to execute for workload"
+msgstr "Failas kurį vykdyti apkrovai"
+
+#: ../src/main.cpp:134
+msgid "print version information"
+msgstr "spausdinti informaciją apie versiją"
+
+#: ../src/main.cpp:135
+msgid "print this help menu"
+msgstr "spausdina šį pagalbos pranešimą"
+
+#: ../src/main.cpp:137
+#, fuzzy
+msgid "For more help please refer to the 'man 8 powertop'"
+msgstr "Daugiau pagalbos ieškokite README faile"
+
+#: ../src/main.cpp:232
+#, c-format
+msgid "Unknown issue running workload!\n"
+msgstr "Nežinoma klaida vykdant apkrovą!\\n"
+
+#: ../src/main.cpp:289
+msgid "PowerTOP is out of memory. PowerTOP is Aborting"
+msgstr "PowerTOP neužtenka atminties. PowerTOP išjungiamas"
+
+#. one to warm up everything
+#: ../src/main.cpp:297
+#, c-format
+msgid "Preparing to take measurements\n"
+msgstr "Ruošiamasi matavimams\\n"
+
+#: ../src/main.cpp:302
+#, c-format
+msgid "Taking %d measurement(s) for a duration of %d second(s) each.\n"
+msgstr "Imami %d matavimas(–ai) kas %d sekundę(–es).\\n"
+
+#: ../src/main.cpp:304
+#, c-format
+msgid "Measuring workload %s.\n"
+msgstr "Skaičiuojama apkrova %s.\\n"
+
+#: ../src/main.cpp:329
+#, c-format
+msgid "PowerTOP "
+msgstr "PowerTOP"
+
+#: ../src/main.cpp:330 ../src/main.cpp:380
+#, c-format
+msgid "exiting...\n"
+msgstr "išjungiama...\\n"
+
+#: ../src/main.cpp:364
+#, c-format
+msgid "modprobe cpufreq_stats failed"
+msgstr ""
+
+#: ../src/main.cpp:367
+#, c-format
+msgid "modprobe msr failed"
+msgstr ""
+
+#: ../src/main.cpp:379 ../src/main.cpp:383
+#, c-format
+msgid "Failed to mount debugfs!\n"
+msgstr "Nepavyko prijungti debugfs!\\n"
+
+#: ../src/main.cpp:384
+#, c-format
+msgid "Should still be able to auto tune...\n"
+msgstr ""
+
+#: ../src/main.cpp:466
+#, c-format
+msgid "Invalid CSV filename\n"
+msgstr ""
+
+#: ../src/main.cpp:482
+#, c-format
+msgid "Invalid HTML filename\n"
+msgstr ""
+
+#: ../src/main.cpp:491
+#, fuzzy, c-format
+msgid "Quiet mode failed!\n"
+msgstr "Tylusis režimas nepavyko!\\n"
+
+#: ../src/main.cpp:559
+msgid "Leaving PowerTOP"
+msgstr "PowerTOP išjungiamas"
+
+#: ../src/parameters/persistent.cpp:46 ../src/parameters/persistent.cpp:155
+msgid "Cannot save to file"
+msgstr "Nepavyko išsaugoti į failą"
+
+#: ../src/parameters/persistent.cpp:89 ../src/parameters/persistent.cpp:180
+msgid "Cannot load from file"
+msgstr "Nepavyko įkelti iš failo"
+
+#. '%i" is for count, do not translate
+#: ../src/parameters/persistent.cpp:138
+#, c-format
+msgid "Loaded %i prior measurements\n"
+msgstr "Įkelti %i ankstesni matavimai\\n"
+
+#: ../src/parameters/persistent.cpp:181
+msgid ""
+"File will be loaded after taking minimum number of measurement(s) with "
+"battery only \n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:115
+#, c-format
+msgid ""
+"Too many open files, please increase the limit of open file descriptors.\n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:117
+#, c-format
+msgid "PowerTOP %s needs the kernel to support the 'perf' subsystem\n"
+msgstr "PowerTOP %s reikalingas 'perf' posistemės\\n"
+
+#: ../src/perf/perf.cpp:118
+#, c-format
+msgid "as well as support for trace points in the kernel:\n"
+msgstr "ir sekimo taškų palaikymas branduolyje:\\n"
+
+#: ../src/process/do_process.cpp:819
+#, c-format
+msgid ""
+"Estimated power: %5.1f Measured power: %5.1f Sum: %5.1f\n"
+"\n"
+msgstr "Apytikrė energija: %5.1f Pamatuota energija: %5.1f Suma: %5.1f\\n\\n"
+
+#: ../src/process/do_process.cpp:838
+#, c-format
+msgid "The estimated remaining time is %i hours, %i minutes\n"
+msgstr "Apskaičiuotas likęs laikas – %i valandos ir %i minutės\\n"
+
+#: ../src/process/do_process.cpp:846
+msgid "Summary"
+msgstr "Santrauka"
+
+#: ../src/process/do_process.cpp:846
+msgid "wakeups/second"
+msgstr "pabudimai/sekundę"
+
+#: ../src/process/do_process.cpp:846
+msgid "GPU ops/seconds"
+msgstr "Grafikos posistemės operacijos/sekundes"
+
+#: ../src/process/do_process.cpp:846
+msgid "VFS ops/sec and"
+msgstr "Virtualios failų sistemos operacijos/sek ir"
+
+#: ../src/process/do_process.cpp:846
+msgid "CPU use"
+msgstr "Procesoriaus naudojimas"
+
+#: ../src/process/do_process.cpp:850
+msgid "Power est."
+msgstr "Energijos įvertis"
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:1078
+msgid "Events/s"
+msgstr "Įvykiai/s"
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:931 ../src/process/do_process.cpp:1079
+msgid "Category"
+msgstr "Kategorija"
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:932 ../src/process/do_process.cpp:1080
+#: ../src/tuning/tuning.cpp:242 ../src/tuning/tuning.cpp:270
+#: ../src/tuning/tuning.cpp:288 ../src/wakeup/waketab.cpp:155
+msgid "Description"
+msgstr "Aprašymas"
+
+#: ../src/process/do_process.cpp:927
+msgid "Wakeups/s"
+msgstr "Pabudimai/s"
+
+#: ../src/process/do_process.cpp:928
+msgid "GPU ops/s"
+msgstr "Grafikos posistemės operacijos/s"
+
+#: ../src/process/do_process.cpp:929
+msgid "Disk IO/s"
+msgstr "Disko operacijos/s"
+
+#: ../src/process/do_process.cpp:930
+msgid "GFX Wakeups/s"
+msgstr "GFX pabudimai/s"
+
+#: ../src/process/do_process.cpp:1017
+msgid "Overview of Software Power Consumers"
+msgstr "Programinės įrangos energijos naudojimo apžvalga"
+
+#: ../src/process/do_process.cpp:1057
+msgid "Target:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1058
+msgid "1 units/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1059
+msgid "System: "
+msgstr ""
+
+#: ../src/process/do_process.cpp:1061
+#, fuzzy
+msgid " wakeup/s"
+msgstr "Pabudimai/s"
+
+#: ../src/process/do_process.cpp:1062
+msgid "CPU: "
+msgstr ""
+
+#: ../src/process/do_process.cpp:1064
+#, fuzzy, c-format
+msgid "% usage"
+msgstr "Naudojimas"
+
+#: ../src/process/do_process.cpp:1065
+msgid "GPU:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1067 ../src/process/do_process.cpp:1073
+#, fuzzy
+msgid " ops/s"
+msgstr "Grafikos posistemės operacijos/s"
+
+#: ../src/process/do_process.cpp:1068
+msgid "GFX:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1070
+#, fuzzy
+msgid " wakeups/s"
+msgstr "Pabudimai/s"
+
+#: ../src/process/do_process.cpp:1071
+msgid "VFS:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1139
+#, fuzzy
+msgid "Top 10 Power Consumers"
+msgstr "Programinės įrangos energijos naudojimo apžvalga"
+
+#: ../src/report/report.cpp:122
+#, fuzzy
+msgid "PowerTOP Version"
+msgstr "PowerTOP versija"
+
+#: ../src/report/report.cpp:131
+#, fuzzy
+msgid "Kernel Version"
+msgstr "PowerTOP versija"
+
+#: ../src/report/report.cpp:135
+msgid "System Name"
+msgstr ""
+
+#: ../src/report/report.cpp:142
+msgid "CPU Information"
+msgstr ""
+
+#: ../src/report/report.cpp:154
+msgid "OS Information"
+msgstr ""
+
+#: ../src/report/report.cpp:161
+#, fuzzy
+msgid "System Information"
+msgstr "spausdinti informaciją apie versiją"
+
+#: ../src/report/report.cpp:195
+#, fuzzy, c-format
+msgid "Cannot open output file %s (%s)\n"
+msgstr "Negalima sukurti laikino failo\\n"
+
+#: ../src/report/report.cpp:211
+#, c-format
+msgid "PowerTOP outputing using base filename %s\n"
+msgstr ""
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:49
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+msgid "Good"
+msgstr "Gerai"
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:50
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+msgid "Bad"
+msgstr "Blogai"
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:51
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+#: ../src/wakeup/wakeup.cpp:50
+msgid "Unknown"
+msgstr "Nežinoma"
+
+#: ../src/tuning/bluetooth.cpp:48
+#, c-format
+msgid "Bluetooth device interface status"
+msgstr "Bluetooth įrenginio sąsajos būsena"
+
+#: ../src/tuning/ethernet.cpp:54 ../src/wakeup/wakeup_ethernet.cpp:51
+#, c-format
+msgid "Wake-on-lan status for device %s"
+msgstr "Wake-on-lan būsena įrenginiui %s"
+
+#: ../src/tuning/runtime.cpp:48
+#, c-format
+msgid "Runtime PM for %s device %s"
+msgstr "%s įrengnio %s energijos valdymas jo veikimo metu"
+
+#: ../src/tuning/runtime.cpp:50
+#, c-format
+msgid "%s device %s has no runtime power management"
+msgstr "%s įrenginys %s neturi energijos valdymo veikimo metu"
+
+#: ../src/tuning/runtime.cpp:74
+#, c-format
+msgid "PCI Device %s has no runtime power management"
+msgstr "PCI įrenginys %s neturi energijos valdymo veikimo metu"
+
+#: ../src/tuning/runtime.cpp:76
+#, c-format
+msgid "Runtime PM for PCI Device %s"
+msgstr "PCI įrenginio %s energijos valdymas jo veikimo metu"
+
+#: ../src/tuning/tuning.cpp:62
+msgid "Enable Audio codec power management"
+msgstr "Įjungti garso kodekų energijos valdymą"
+
+#: ../src/tuning/tuning.cpp:63
+msgid "NMI watchdog should be turned off"
+msgstr "NMI kontrolierius turėtų būti išjungtas"
+
+#: ../src/tuning/tuning.cpp:64
+msgid "Power Aware CPU scheduler"
+msgstr "Energijos sąnaudas suprantantis procesoriaus valdytojas"
+
+#: ../src/tuning/tuning.cpp:65
+msgid "VM writeback timeout"
+msgstr "Laikas iki virtualiosios mašinos kešo išrašymo"
+
+#: ../src/tuning/tuning.cpp:81
+msgid "Tunables"
+msgstr "Deriniai"
+
+#: ../src/tuning/tuning.cpp:81
+msgid " <ESC> Exit | <Enter> Toggle tunable | <r> Window refresh"
+msgstr "<ESC> Išeiti | <Enter> Perjungti derinį | <r> Perkrauti langą"
+
+#: ../src/tuning/tuning.cpp:243 ../src/wakeup/waketab.cpp:156
+msgid "Script"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:257
+msgid "Software Settings in Need of Tuning"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:276
+msgid "Untunable Software Issues"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:300
+msgid "Optimal Tuned Software Settings"
+msgstr ""
+
+#: ../src/tuning/tuningi2c.cpp:57
+#, fuzzy, c-format
+msgid "Runtime PM for I2C %s %s (%s)"
+msgstr "%s įrengnio %s energijos valdymas jo veikimo metu"
+
+#: ../src/tuning/tuningi2c.cpp:59
+#, fuzzy, c-format
+msgid "I2C %s %s has no runtime power management"
+msgstr "%s įrenginys %s neturi energijos valdymo veikimo metu"
+
+#: ../src/tuning/tuningsysfs.cpp:123
+#, fuzzy, c-format
+msgid "Enable SATA link power management for %s"
+msgstr "Įjungti SATA sąsajos energijos valdymą %s"
+
+#: ../src/tuning/tuningusb.cpp:54
+#, c-format
+msgid "Autosuspend for unknown USB device %s (%s:%s)"
+msgstr "Automatinis nežinomo USB įrenginio %s (%s:%s) užmigdymas"
+
+#: ../src/tuning/tuningusb.cpp:71 ../src/tuning/tuningusb.cpp:73
+#: ../src/tuning/tuningusb.cpp:75
+#, c-format
+msgid "Autosuspend for USB device %s [%s]"
+msgstr "Automatinis USB įrenginio %s [%s] užmigdymas"
+
+#: ../src/tuning/wifi.cpp:48
+#, c-format
+msgid "Wireless Power Saving for interface %s"
+msgstr "Energijos saugojimas bevielio ryšio įrenginiui %s"
+
+#: ../src/wakeup/waketab.cpp:42
+#, fuzzy
+msgid "WakeUp"
+msgstr "Pabudimai/s"
+
+#: ../src/wakeup/waketab.cpp:42
+#, fuzzy
+msgid " <ESC> Exit | <Enter> Toggle wakeup | <r> Window refresh"
+msgstr "<ESC> Išeiti | <Enter> Perjungti derinį | <r> Perkrauti langą"
+
+#. Report Output
+#: ../src/wakeup/waketab.cpp:170
+#, fuzzy
+msgid "Wake status of the devices"
+msgstr "Wake-on-lan būsena įrenginiui %s"
+
+#: ../src/wakeup/wakeup.cpp:48 ../src/wakeup/wakeup_ethernet.cpp:47
+#: ../src/wakeup/wakeup_usb.cpp:47
+#, fuzzy
+msgid "Enable"
+msgstr "Deriniai"
+
+#: ../src/wakeup/wakeup.cpp:49 ../src/wakeup/wakeup_ethernet.cpp:47
+#: ../src/wakeup/wakeup_usb.cpp:47
+msgid "Disable"
+msgstr ""
+
+#: ../src/wakeup/wakeup_usb.cpp:51
+#, fuzzy, c-format
+msgid "Wake status for USB device %s"
+msgstr "Wake-on-lan būsena įrenginiui %s"
+
+#~ msgid "Actual"
+#~ msgstr "Tikrasis"
+
+#~ msgid "Power Consumption Summary"
+#~ msgstr "Energijos sąnaudų aprašymas"
+
+#~ msgid "GPU ops/second"
+#~ msgstr "Grafikos posistemės operacijos/sekundę"
+
+#~ msgid "VFS ops/sec"
+#~ msgstr "Virtualios failų sistemos operacijos/sek"
+
+#~ msgid "GFX wakes/sec and"
+#~ msgstr "GFX pabudimai/sek ir"
+
+#~ msgid "Using 'ondemand' cpufreq governor"
+#~ msgstr "Naudojamas 'ondemand' cpufreq valdytojas"
+
+#~ msgid "[=FILENAME]"
+#~ msgstr "[=FAILO VARDAS]"
diff --git a/po/nl_NL.po b/po/nl_NL.po
new file mode 100644
index 0000000..d333e20
--- /dev/null
+++ b/po/nl_NL.po
@@ -0,0 +1,967 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Intel Corporation
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# auke <auke-jan.h.kok@intel.com>, 2012
+# JanCeuleers <jan.ceuleers@computer.org>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: PowerTOP\n"
+"Report-Msgid-Bugs-To: \"powertop@lists.01.org\"\n"
+"POT-Creation-Date: 2022-09-29 04:45-0700\n"
+"PO-Revision-Date: 2013-11-05 08:40+0000\n"
+"Last-Translator: Margie Foster <margie@linux.intel.com>\n"
+"Language-Team: Dutch (Netherlands) (http://www.transifex.com/projects/p/"
+"PowerTOP/language/nl_NL/)\n"
+"Language: nl_NL\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/calibrate/calibrate.cpp:238
+#, c-format
+msgid "Cannot create temp file\n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:258
+#, c-format
+msgid "Calibrating: CPU usage on %i threads\n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:273
+#, c-format
+msgid "Calibrating: CPU wakeup power consumption\n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:290
+#, c-format
+msgid "Calibrating USB devices\n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:292 src/calibrate/calibrate.cpp:309
+#: src/calibrate/calibrate.cpp:317 src/calibrate/calibrate.cpp:334
+#, c-format
+msgid ".... device %s \n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:307
+#, c-format
+msgid "Calibrating radio devices\n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:331
+#, c-format
+msgid "Calibrating backlight\n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:355 src/calibrate/calibrate.cpp:365
+#, c-format
+msgid "Calibrating idle\n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:378
+#, c-format
+msgid "Calibrating: disk usage \n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:403
+msgid "Starting PowerTOP power estimate calibration \n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:426
+msgid "Finishing PowerTOP power estimate calibration \n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:430
+#, c-format
+msgid "Parameters after calibration:\n"
+msgstr "Parameters na calibratie:\n"
+
+#: src/cpu/abstract_cpu.cpp:74
+msgid "Idle"
+msgstr ""
+
+#: src/cpu/abstract_cpu.cpp:76
+msgid "Turbo Mode"
+msgstr ""
+
+#: src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(HW)"
+msgstr ""
+
+#: src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(OS)"
+msgstr ""
+
+#: src/cpu/cpu_core.cpp:91 src/cpu/intel_cpus.cpp:367
+#, c-format
+msgid " Core"
+msgstr ""
+
+#: src/cpu/cpu.cpp:85
+#, c-format
+msgid "cpu package %i"
+msgstr "cpu package %i"
+
+#: src/cpu/cpu.cpp:86
+msgid "cpu package"
+msgstr "cpu package"
+
+#: src/cpu/cpu.cpp:89 src/cpu/cpu.cpp:96
+#, fuzzy, c-format
+msgid "package-%i"
+msgstr "cpu package %i"
+
+#: src/cpu/cpu.cpp:90
+msgid "cpu rapl package"
+msgstr ""
+
+#: src/cpu/cpu.cpp:97
+msgid "dram rapl package"
+msgstr ""
+
+#: src/cpu/cpu.cpp:471
+msgid "Processor Idle State Report"
+msgstr ""
+
+#: src/cpu/cpu.cpp:535 src/cpu/cpu.cpp:761
+msgid "Package"
+msgstr ""
+
+#: src/cpu/cpu.cpp:572 src/cpu/cpu.cpp:783
+#, c-format
+msgid "Core %d"
+msgstr ""
+
+#: src/cpu/cpu.cpp:579
+#, c-format
+msgid "GPU %d"
+msgstr ""
+
+#: src/cpu/cpu.cpp:602
+msgid "CPU"
+msgstr ""
+
+#: src/cpu/cpu.cpp:684
+msgid "Processor Frequency Report"
+msgstr ""
+
+#: src/cpu/cpu.cpp:804
+#, c-format
+msgid "CPU %d"
+msgstr ""
+
+#: src/cpu/cpu.cpp:1005
+#, c-format
+msgid "cpu_idle event returned no state?\n"
+msgstr ""
+
+#: src/cpu/cpu.cpp:1020
+#, c-format
+msgid "power or cpu_frequency event returned no state?\n"
+msgstr ""
+
+#: src/cpu/cpu_linux.cpp:79
+msgid "C0 polling"
+msgstr "C0 polling"
+
+#: src/cpu/cpu_linux.cpp:242
+#, c-format
+msgid " CPU(OS) %i"
+msgstr ""
+
+#: src/cpu/cpu_linux.cpp:341 src/cpu/intel_cpus.cpp:733
+#, c-format
+msgid " CPU %i"
+msgstr ""
+
+#: src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(HW)"
+msgstr ""
+
+#: src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(OS)"
+msgstr ""
+
+#: src/cpu/cpu_package.cpp:104 src/cpu/intel_cpus.cpp:498
+#, c-format
+msgid " Package"
+msgstr ""
+
+#: src/cpu/intel_cpus.cpp:152
+#, c-format
+msgid "read_msr cpu%d 0x%llx : "
+msgstr ""
+
+#: src/cpu/intel_cpus.cpp:656
+msgid "C0 active"
+msgstr "C0 active"
+
+#: src/cpu/intel_cpus.cpp:714
+#, c-format
+msgid "Average"
+msgstr ""
+
+#: src/cpu/intel_gpu.cpp:64
+#, c-format
+msgid " GPU "
+msgstr ""
+
+#: src/devices/ahci.cpp:154
+#, c-format
+msgid "SATA link: %s"
+msgstr ""
+
+#: src/devices/ahci.cpp:156
+#, c-format
+msgid "SATA disk: %s"
+msgstr ""
+
+#: src/devices/ahci.cpp:374
+msgid "AHCI ALPM Residency Statistics - Not supported on this macine"
+msgstr ""
+
+#: src/devices/ahci.cpp:389
+msgid "Link"
+msgstr ""
+
+#: src/devices/ahci.cpp:390
+#, fuzzy
+msgid "Active"
+msgstr "C0 active"
+
+#: src/devices/ahci.cpp:391
+msgid "Partial"
+msgstr ""
+
+#: src/devices/ahci.cpp:392
+msgid "Slumber"
+msgstr ""
+
+#: src/devices/ahci.cpp:393
+msgid "Devslp"
+msgstr ""
+
+#: src/devices/ahci.cpp:399
+msgid "AHCI ALPM Residency Statistics"
+msgstr ""
+
+#: src/devices/alsa.cpp:77
+#, c-format
+msgid "Audio codec %s: %s (%s)"
+msgstr ""
+
+#: src/devices/alsa.cpp:79 src/devices/alsa.cpp:81
+#, c-format
+msgid "Audio codec %s: %s"
+msgstr ""
+
+#: src/devices/devfreq.cpp:260
+#, fuzzy
+msgid "Device Freq stats"
+msgstr "Apparaat stats"
+
+#: src/devices/devfreq.cpp:278
+msgid " Devfreq is not enabled"
+msgstr ""
+
+#: src/devices/devfreq.cpp:283
+msgid " No devfreq devices available"
+msgstr ""
+
+#: src/devices/device.cpp:172 src/process/do_process.cpp:831
+#, c-format
+msgid "The battery reports a discharge rate of %sW\n"
+msgstr ""
+
+#: src/devices/device.cpp:174 src/process/do_process.cpp:833
+#, c-format
+msgid "The energy consumed was %sJ\n"
+msgstr ""
+
+#: src/devices/device.cpp:180
+#, c-format
+msgid "System baseline power is estimated at %sW\n"
+msgstr ""
+
+#: src/devices/device.cpp:187
+msgid "Power est. Usage Device name\n"
+msgstr ""
+
+#: src/devices/device.cpp:189
+msgid " Usage Device name\n"
+msgstr ""
+
+#: src/devices/device.cpp:256
+msgid "The battery reports a discharge rate of: "
+msgstr ""
+
+#: src/devices/device.cpp:261
+msgid "The energy consumed was : "
+msgstr ""
+
+#: src/devices/device.cpp:268
+msgid "The system baseline power is estimated at: "
+msgstr ""
+
+#: src/devices/device.cpp:277 src/process/do_process.cpp:850
+#: src/process/do_process.cpp:852 src/process/do_process.cpp:926
+#: src/process/do_process.cpp:1077
+msgid "Usage"
+msgstr ""
+
+#: src/devices/device.cpp:278
+#, fuzzy
+msgid "Device Name"
+msgstr "Apparaat stats"
+
+#: src/devices/device.cpp:280 src/process/do_process.cpp:935
+#: src/process/do_process.cpp:1082
+msgid "PW Estimate"
+msgstr ""
+
+#: src/devices/device.cpp:317
+msgid "Device Power Report"
+msgstr ""
+
+#: src/devices/network.cpp:177
+#, c-format
+msgid "Network interface: %s (%s)"
+msgstr ""
+
+#: src/devices/rfkill.cpp:65 src/devices/rfkill.cpp:69
+#, c-format
+msgid "Radio device: %s"
+msgstr ""
+
+#: src/devices/runtime_pm.cpp:216
+#, c-format
+msgid "I2C %s (%s): %s"
+msgstr ""
+
+#: src/devices/runtime_pm.cpp:216 src/tuning/tuningi2c.cpp:57
+#: src/tuning/tuningi2c.cpp:59
+msgid "Adapter"
+msgstr ""
+
+#: src/devices/runtime_pm.cpp:216 src/devlist.cpp:331
+#: src/tuning/tuningi2c.cpp:57 src/tuning/tuningi2c.cpp:59
+#, fuzzy
+msgid "Device"
+msgstr "Apparaat stats"
+
+#: src/devices/runtime_pm.cpp:241
+#, c-format
+msgid "PCI Device: %s"
+msgstr ""
+
+#: src/devices/usb.cpp:51 src/devices/usb.cpp:96 src/devices/usb.cpp:98
+#, c-format
+msgid "USB device: %s"
+msgstr ""
+
+#: src/devices/usb.cpp:94
+#, c-format
+msgid "USB device: %s (%s)"
+msgstr ""
+
+#: src/devlist.cpp:330
+msgid "Process"
+msgstr ""
+
+#: src/devlist.cpp:347
+msgid "Process Device Activity"
+msgstr ""
+
+#: src/display.cpp:70
+msgid "Overview"
+msgstr "Overzicht"
+
+#: src/display.cpp:71
+msgid "Idle stats"
+msgstr "Rust stats"
+
+#: src/display.cpp:72
+msgid "Frequency stats"
+msgstr "Frekwentie stats"
+
+#: src/display.cpp:73
+msgid "Device stats"
+msgstr "Apparaat stats"
+
+#: src/display.cpp:131
+msgid "Exit"
+msgstr ""
+
+#: src/display.cpp:132
+msgid "Navigate"
+msgstr ""
+
+#: src/lib.cpp:288
+#, c-format
+msgid "%7sW"
+msgstr "%7sW"
+
+#: src/lib.cpp:291
+#, c-format
+msgid " 0 mW"
+msgstr " 0 mW"
+
+#: src/lib.cpp:410
+msgid "PS/2 Touchpad / Keyboard / Mouse"
+msgstr ""
+
+#: src/lib.cpp:411
+msgid "SATA controller"
+msgstr ""
+
+#: src/lib.cpp:412
+msgid "Intel built in USB hub"
+msgstr ""
+
+#: src/lib.cpp:467
+#, c-format
+msgid "glob returned GLOB_NOSPACE\n"
+msgstr ""
+
+#: src/lib.cpp:471
+#, c-format
+msgid "glob returned GLOB_ABORTED\n"
+msgstr ""
+
+#: src/lib.cpp:475
+#, c-format
+msgid "glob returned GLOB_NOMATCH\n"
+msgstr ""
+
+#: src/lib.cpp:513 src/lib.cpp:549
+#, c-format
+msgid ""
+"Model-specific registers (MSR)\t\t\t not found (try enabling "
+"CONFIG_X86_MSR).\n"
+msgstr ""
+
+#: src/main.cpp:104
+#, fuzzy, c-format
+msgid "PowerTOP version "
+msgstr "PowerTOP"
+
+#: src/main.cpp:110
+msgid "Set refresh time out"
+msgstr "Stel verversingstijd in"
+
+#: src/main.cpp:123
+msgid "Usage: powertop [OPTIONS]"
+msgstr ""
+
+#: src/main.cpp:124
+msgid "sets all tunable options to their GOOD setting"
+msgstr ""
+
+#: src/main.cpp:125
+msgid "runs powertop in calibration mode"
+msgstr ""
+
+#: src/main.cpp:126 src/main.cpp:129
+msgid "[=filename]"
+msgstr ""
+
+#: src/main.cpp:126
+msgid "generate a csv report"
+msgstr ""
+
+#: src/main.cpp:127
+msgid "run in \"debug\" mode"
+msgstr ""
+
+#: src/main.cpp:128
+msgid "[=devnode]"
+msgstr ""
+
+#: src/main.cpp:128
+msgid "uses an Extech Power Analyzer for measurements"
+msgstr ""
+
+#: src/main.cpp:129
+msgid "generate a html report"
+msgstr ""
+
+#: src/main.cpp:130
+msgid "[=iterations] number of times to run each test"
+msgstr ""
+
+#: src/main.cpp:131
+msgid "suppress stderr output"
+msgstr ""
+
+#: src/main.cpp:132 src/main.cpp:133
+msgid "[=seconds]"
+msgstr ""
+
+#: src/main.cpp:132
+msgid "interval for power consumption measurement"
+msgstr ""
+
+#: src/main.cpp:133
+msgid "generate a report for 'x' seconds"
+msgstr ""
+
+#: src/main.cpp:134
+msgid "[=workload]"
+msgstr ""
+
+#: src/main.cpp:134
+msgid "file to execute for workload"
+msgstr ""
+
+#: src/main.cpp:135
+msgid "print version information"
+msgstr ""
+
+#: src/main.cpp:136
+msgid "print this help menu"
+msgstr ""
+
+#: src/main.cpp:138
+msgid "For more help please refer to the 'man 8 powertop'"
+msgstr ""
+
+#: src/main.cpp:233
+#, c-format
+msgid "Unknown issue running workload!\n"
+msgstr ""
+
+#: src/main.cpp:290
+msgid "PowerTOP is out of memory. PowerTOP is Aborting"
+msgstr ""
+
+#: src/main.cpp:298
+#, c-format
+msgid "Preparing to take measurements\n"
+msgstr "Voorbereiding om metingen te nemen\n"
+
+#: src/main.cpp:303
+#, c-format
+msgid "Taking %d measurement(s) for a duration of %d second(s) each.\n"
+msgstr ""
+
+#: src/main.cpp:305
+#, c-format
+msgid "Measuring workload %s.\n"
+msgstr ""
+
+#: src/main.cpp:330
+#, c-format
+msgid "PowerTOP "
+msgstr "PowerTOP"
+
+#: src/main.cpp:331 src/main.cpp:381
+#, c-format
+msgid "exiting...\n"
+msgstr "afsluiten...\n"
+
+#: src/main.cpp:365
+#, c-format
+msgid "modprobe cpufreq_stats failed\n"
+msgstr ""
+
+#: src/main.cpp:368
+#, c-format
+msgid "modprobe msr failed\n"
+msgstr ""
+
+#: src/main.cpp:380 src/main.cpp:384
+#, c-format
+msgid "Failed to mount debugfs!\n"
+msgstr "Kan debugfs niet aankoppelen!\n"
+
+#: src/main.cpp:385
+#, c-format
+msgid "Should still be able to auto tune...\n"
+msgstr ""
+
+#: src/main.cpp:467
+#, c-format
+msgid "Invalid CSV filename\n"
+msgstr ""
+
+#: src/main.cpp:483
+#, c-format
+msgid "Invalid HTML filename\n"
+msgstr ""
+
+#: src/main.cpp:492
+#, c-format
+msgid "Quiet mode failed!\n"
+msgstr ""
+
+#: src/main.cpp:560
+msgid "Leaving PowerTOP"
+msgstr ""
+
+#: src/parameters/persistent.cpp:46 src/parameters/persistent.cpp:155
+msgid "Cannot save to file"
+msgstr ""
+
+#: src/parameters/persistent.cpp:89 src/parameters/persistent.cpp:180
+msgid "Cannot load from file"
+msgstr ""
+
+#: src/parameters/persistent.cpp:138
+#, c-format
+msgid "Loaded %i prior measurements\n"
+msgstr "%i eerdere metingen ingeladen\n"
+
+#: src/parameters/persistent.cpp:181
+msgid ""
+"File will be loaded after taking minimum number of measurement(s) with "
+"battery only \n"
+msgstr ""
+
+#: src/perf/perf.cpp:115
+#, c-format
+msgid ""
+"Too many open files, please increase the limit of open file descriptors.\n"
+msgstr ""
+
+#: src/perf/perf.cpp:117
+#, c-format
+msgid "PowerTOP %s needs the kernel to support the 'perf' subsystem\n"
+msgstr ""
+
+#: src/perf/perf.cpp:118
+#, c-format
+msgid "as well as support for trace points in the kernel:\n"
+msgstr ""
+
+#: src/process/do_process.cpp:819
+#, c-format
+msgid ""
+"Estimated power: %5.1f Measured power: %5.1f Sum: %5.1f\n"
+"\n"
+msgstr ""
+
+#: src/process/do_process.cpp:838
+#, c-format
+msgid "The estimated remaining time is %i hours, %i minutes\n"
+msgstr ""
+
+#: src/process/do_process.cpp:846
+msgid "Summary"
+msgstr ""
+
+#: src/process/do_process.cpp:846
+msgid "wakeups/second"
+msgstr ""
+
+#: src/process/do_process.cpp:846
+msgid "GPU ops/seconds"
+msgstr ""
+
+#: src/process/do_process.cpp:846
+msgid "VFS ops/sec and"
+msgstr ""
+
+#: src/process/do_process.cpp:846
+msgid "CPU use"
+msgstr ""
+
+#: src/process/do_process.cpp:850
+msgid "Power est."
+msgstr ""
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:1078
+msgid "Events/s"
+msgstr ""
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:931 src/process/do_process.cpp:1079
+msgid "Category"
+msgstr ""
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:932 src/process/do_process.cpp:1080
+#: src/tuning/tuning.cpp:242 src/tuning/tuning.cpp:270
+#: src/tuning/tuning.cpp:295 src/wakeup/waketab.cpp:155
+msgid "Description"
+msgstr ""
+
+#: src/process/do_process.cpp:927
+msgid "Wakeups/s"
+msgstr ""
+
+#: src/process/do_process.cpp:928
+msgid "GPU ops/s"
+msgstr ""
+
+#: src/process/do_process.cpp:929
+msgid "Disk IO/s"
+msgstr ""
+
+#: src/process/do_process.cpp:930
+msgid "GFX Wakeups/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1017
+msgid "Overview of Software Power Consumers"
+msgstr ""
+
+#: src/process/do_process.cpp:1057
+msgid "Target:"
+msgstr ""
+
+#: src/process/do_process.cpp:1058
+msgid "1 units/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1059
+msgid "System: "
+msgstr ""
+
+#: src/process/do_process.cpp:1061
+msgid " wakeup/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1062
+msgid "CPU: "
+msgstr ""
+
+#: src/process/do_process.cpp:1064
+#, c-format
+msgid "% usage"
+msgstr ""
+
+#: src/process/do_process.cpp:1065
+msgid "GPU:"
+msgstr ""
+
+#: src/process/do_process.cpp:1067 src/process/do_process.cpp:1073
+msgid " ops/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1068
+msgid "GFX:"
+msgstr ""
+
+#: src/process/do_process.cpp:1070
+msgid " wakeups/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1071
+msgid "VFS:"
+msgstr ""
+
+#: src/process/do_process.cpp:1139
+msgid "Top 10 Power Consumers"
+msgstr ""
+
+#: src/report/report.cpp:122
+#, fuzzy
+msgid "PowerTOP Version"
+msgstr "PowerTOP"
+
+#: src/report/report.cpp:131
+msgid "Kernel Version"
+msgstr ""
+
+#: src/report/report.cpp:135
+msgid "System Name"
+msgstr ""
+
+#: src/report/report.cpp:142
+msgid "CPU Information"
+msgstr ""
+
+#: src/report/report.cpp:154
+msgid "OS Information"
+msgstr ""
+
+#: src/report/report.cpp:161
+msgid "System Information"
+msgstr ""
+
+#: src/report/report.cpp:195
+#, c-format
+msgid "Cannot open output file %s (%s)\n"
+msgstr ""
+
+#: src/report/report.cpp:211
+#, c-format
+msgid "PowerTOP outputting using base filename %s\n"
+msgstr ""
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:49
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45
+msgid "Good"
+msgstr "Goed"
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:50
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45
+msgid "Bad"
+msgstr "Slecht"
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:51
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45 src/wakeup/wakeup.cpp:50
+msgid "Unknown"
+msgstr "Onbekend"
+
+#: src/tuning/bluetooth.cpp:48
+#, c-format
+msgid "Bluetooth device interface status"
+msgstr ""
+
+#: src/tuning/ethernet.cpp:54 src/wakeup/wakeup_ethernet.cpp:51
+#, c-format
+msgid "Wake-on-lan status for device %s"
+msgstr ""
+
+#: src/tuning/runtime.cpp:48
+#, c-format
+msgid "Runtime PM for %s device %s"
+msgstr ""
+
+#: src/tuning/runtime.cpp:50
+#, c-format
+msgid "%s device %s has no runtime power management"
+msgstr ""
+
+#: src/tuning/runtime.cpp:74
+#, c-format
+msgid "PCI Device %s has no runtime power management"
+msgstr ""
+
+#: src/tuning/runtime.cpp:76
+#, c-format
+msgid "Runtime PM for PCI Device %s"
+msgstr ""
+
+#: src/tuning/runtime.cpp:80
+#, c-format
+msgid "Runtime PM for port %s of PCI device: %s"
+msgstr ""
+
+#: src/tuning/runtime.cpp:83
+#, c-format
+msgid "Runtime PM for disk %s"
+msgstr ""
+
+#: src/tuning/tuning.cpp:62
+msgid "Enable Audio codec power management"
+msgstr "Audio codec energiebeheer inschakelen"
+
+#: src/tuning/tuning.cpp:63
+msgid "NMI watchdog should be turned off"
+msgstr "NMI watchdog is beter uitgeschakeld"
+
+#: src/tuning/tuning.cpp:64
+msgid "Power Aware CPU scheduler"
+msgstr ""
+
+#: src/tuning/tuning.cpp:65
+msgid "VM writeback timeout"
+msgstr ""
+
+#: src/tuning/tuning.cpp:81
+msgid "Tunables"
+msgstr ""
+
+#: src/tuning/tuning.cpp:81
+msgid " <ESC> Exit | <Enter> Toggle tunable | <r> Window refresh"
+msgstr ""
+
+#: src/tuning/tuning.cpp:243 src/wakeup/waketab.cpp:156
+msgid "Script"
+msgstr ""
+
+#: src/tuning/tuning.cpp:257
+msgid "Software Settings in Need of Tuning"
+msgstr ""
+
+#: src/tuning/tuning.cpp:276
+msgid "Untunable Software Issues"
+msgstr ""
+
+#: src/tuning/tuning.cpp:307
+msgid "Optimal Tuned Software Settings"
+msgstr ""
+
+#: src/tuning/tuningi2c.cpp:57
+#, c-format
+msgid "Runtime PM for I2C %s %s (%s)"
+msgstr ""
+
+#: src/tuning/tuningi2c.cpp:59
+#, c-format
+msgid "I2C %s %s has no runtime power management"
+msgstr ""
+
+#: src/tuning/tuningsysfs.cpp:123
+#, fuzzy, c-format
+msgid "Enable SATA link power management for %s"
+msgstr "Audio codec energiebeheer inschakelen"
+
+#: src/tuning/tuningusb.cpp:54
+#, c-format
+msgid "Autosuspend for unknown USB device %s (%s:%s)"
+msgstr ""
+
+#: src/tuning/tuningusb.cpp:71 src/tuning/tuningusb.cpp:73
+#: src/tuning/tuningusb.cpp:75
+#, c-format
+msgid "Autosuspend for USB device %s [%s]"
+msgstr ""
+
+#: src/tuning/wifi.cpp:48
+#, c-format
+msgid "Wireless Power Saving for interface %s"
+msgstr ""
+
+#: src/wakeup/waketab.cpp:42
+msgid "WakeUp"
+msgstr ""
+
+#: src/wakeup/waketab.cpp:42
+msgid " <ESC> Exit | <Enter> Toggle wakeup | <r> Window refresh"
+msgstr ""
+
+#: src/wakeup/waketab.cpp:170
+msgid "Wake status of the devices"
+msgstr ""
+
+#: src/wakeup/wakeup.cpp:48 src/wakeup/wakeup_ethernet.cpp:47
+#: src/wakeup/wakeup_usb.cpp:47
+msgid "Enabled"
+msgstr ""
+
+#: src/wakeup/wakeup.cpp:49 src/wakeup/wakeup_ethernet.cpp:47
+#: src/wakeup/wakeup_usb.cpp:47
+msgid "Disabled"
+msgstr ""
+
+#: src/wakeup/wakeup_usb.cpp:51
+#, c-format
+msgid "Wake status for USB device %s"
+msgstr ""
+
+#~ msgid "Actual"
+#~ msgstr "Huidig"
+
+#, fuzzy
+#~ msgid "I2C Device: %s"
+#~ msgstr "Apparaat stats"
+
+#~ msgid "Using 'ondemand' cpufreq governor"
+#~ msgstr "'ondemand' cpufreq governor in gebruik"
diff --git a/po/pl_PL.po b/po/pl_PL.po
new file mode 100644
index 0000000..38e76ab
--- /dev/null
+++ b/po/pl_PL.po
@@ -0,0 +1,991 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Intel Corporation
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Michal Plichta <mplichta@gmail.com>, 2013
+# kostur86 <m.kosturek@gmail.com>, 2013
+# kostur86 <m.kosturek@gmail.com>, 2012
+# Michal Plichta <mplichta@gmail.com>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: PowerTOP\n"
+"Report-Msgid-Bugs-To: powertop@lists.01.org\n"
+"POT-Creation-Date: 2019-01-04 13:55-0800\n"
+"PO-Revision-Date: 2013-11-05 08:40+0000\n"
+"Last-Translator: Margie Foster <margie@linux.intel.com>\n"
+"Language-Team: Polish (Poland) (http://www.transifex.com/projects/p/PowerTOP/"
+"language/pl_PL/)\n"
+"Language: pl_PL\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
+"|| n%100>=20) ? 1 : 2);\n"
+
+#: ../src/calibrate/calibrate.cpp:238
+#, c-format
+msgid "Cannot create temp file\n"
+msgstr "Nie można utworzyć pliku tymczasowego\\n"
+
+#: ../src/calibrate/calibrate.cpp:258
+#, c-format
+msgid "Calibrating: CPU usage on %i threads\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:273
+#, c-format
+msgid "Calibrating: CPU wakeup power consumption\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:290
+#, c-format
+msgid "Calibrating USB devices\n"
+msgstr "Kalibracja urządzeń USB\\n"
+
+#: ../src/calibrate/calibrate.cpp:292 ../src/calibrate/calibrate.cpp:309
+#: ../src/calibrate/calibrate.cpp:317 ../src/calibrate/calibrate.cpp:334
+#, c-format
+msgid ".... device %s \n"
+msgstr "... urządzenie %s \\n"
+
+#: ../src/calibrate/calibrate.cpp:307
+#, c-format
+msgid "Calibrating radio devices\n"
+msgstr "Kalibracja urządzeń radiowych\\n"
+
+#: ../src/calibrate/calibrate.cpp:331
+#, c-format
+msgid "Calibrating backlight\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:355 ../src/calibrate/calibrate.cpp:365
+#, c-format
+msgid "Calibrating idle\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:378
+#, c-format
+msgid "Calibrating: disk usage \n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:403
+msgid "Starting PowerTOP power estimate calibration \n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:426
+msgid "Finishing PowerTOP power estimate calibration \n"
+msgstr "Zakończenie PowerTOP po zebraniu estymaty mocy\\n"
+
+#: ../src/calibrate/calibrate.cpp:430
+#, c-format
+msgid "Parameters after calibration:\n"
+msgstr "Parametry po kalibracji:\\n"
+
+#: ../src/cpu/abstract_cpu.cpp:74
+msgid "Idle"
+msgstr ""
+
+#: ../src/cpu/abstract_cpu.cpp:76
+msgid "Turbo Mode"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:37
+#, fuzzy, c-format
+msgid " Core(HW)"
+msgstr "Rdzeń"
+
+#: ../src/cpu/cpu_core.cpp:37
+#, fuzzy, c-format
+msgid " Core(OS)"
+msgstr "Rdzeń"
+
+#: ../src/cpu/cpu_core.cpp:91 ../src/cpu/intel_cpus.cpp:324
+#, c-format
+msgid " Core"
+msgstr "Rdzeń"
+
+#: ../src/cpu/cpu.cpp:85
+#, c-format
+msgid "cpu package %i"
+msgstr "pakiet cpu %i"
+
+#: ../src/cpu/cpu.cpp:86
+msgid "cpu package"
+msgstr "pakiet cpu"
+
+#: ../src/cpu/cpu.cpp:89 ../src/cpu/cpu.cpp:96
+#, fuzzy, c-format
+msgid "package-%i"
+msgstr "Pakiet %i"
+
+#: ../src/cpu/cpu.cpp:90
+msgid "cpu rapl package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:97
+msgid "dram rapl package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:471
+msgid "Processor Idle State Report"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:535 ../src/cpu/cpu.cpp:753
+msgid "Package"
+msgstr "Paczka"
+
+#: ../src/cpu/cpu.cpp:566 ../src/cpu/cpu.cpp:775
+#, fuzzy, c-format
+msgid "Core %d"
+msgstr "Jądro %i"
+
+#: ../src/cpu/cpu.cpp:573
+#, fuzzy, c-format
+msgid "GPU %d"
+msgstr "GPU %i"
+
+#: ../src/cpu/cpu.cpp:594
+#, fuzzy
+msgid "CPU"
+msgstr "CPU %i"
+
+#: ../src/cpu/cpu.cpp:676
+msgid "Processor Frequency Report"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:796
+#, fuzzy, c-format
+msgid "CPU %d"
+msgstr "CPU %i"
+
+#: ../src/cpu/cpu.cpp:997
+#, c-format
+msgid "cpu_idle event returned no state?\n"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:1012
+#, c-format
+msgid "power or cpu_frequency event returned no state?\n"
+msgstr ""
+
+#: ../src/cpu/cpu_linux.cpp:79
+msgid "C0 polling"
+msgstr "C0 polling"
+
+#: ../src/cpu/cpu_linux.cpp:242
+#, fuzzy, c-format
+msgid " CPU(OS) %i"
+msgstr "CPU %i"
+
+#: ../src/cpu/cpu_linux.cpp:341 ../src/cpu/intel_cpus.cpp:651
+#, c-format
+msgid " CPU %i"
+msgstr "CPU %i"
+
+#: ../src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(HW)"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(OS)"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:104 ../src/cpu/intel_cpus.cpp:412
+#, c-format
+msgid " Package"
+msgstr "Paczka"
+
+#: ../src/cpu/intel_cpus.cpp:129
+#, c-format
+msgid "read_msr cpu%d 0x%llx : "
+msgstr ""
+
+#: ../src/cpu/intel_cpus.cpp:574
+msgid "C0 active"
+msgstr "C0 aktywny"
+
+#: ../src/cpu/intel_cpus.cpp:632
+#, c-format
+msgid "Average"
+msgstr ""
+
+#: ../src/cpu/intel_gpu.cpp:64
+#, fuzzy, c-format
+msgid " GPU "
+msgstr "GPU %i"
+
+#: ../src/devices/ahci.cpp:154
+#, c-format
+msgid "SATA link: %s"
+msgstr "Łącze SATA: %s"
+
+#: ../src/devices/ahci.cpp:156
+#, c-format
+msgid "SATA disk: %s"
+msgstr "Dysk SATA: %s"
+
+#: ../src/devices/ahci.cpp:374
+msgid "AHCI ALPM Residency Statistics - Not supported on this macine"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:389
+msgid "Link"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:390
+#, fuzzy
+msgid "Active"
+msgstr "C0 aktywny"
+
+#: ../src/devices/ahci.cpp:391
+msgid "Partial"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:392
+msgid "Slumber"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:393
+msgid "Devslp"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:399
+msgid "AHCI ALPM Residency Statistics"
+msgstr ""
+
+#: ../src/devices/alsa.cpp:77
+#, c-format
+msgid "Audio codec %s: %s (%s)"
+msgstr "Kodek audio %s: %s (%s)"
+
+#: ../src/devices/alsa.cpp:79 ../src/devices/alsa.cpp:81
+#, c-format
+msgid "Audio codec %s: %s"
+msgstr "Kodek audio %s: %s"
+
+#: ../src/devices/devfreq.cpp:261
+#, fuzzy
+msgid "Device Freq stats"
+msgstr "Statystyki urządzeń"
+
+#: ../src/devices/devfreq.cpp:279
+msgid " Devfreq is not enabled"
+msgstr ""
+
+#: ../src/devices/devfreq.cpp:284
+msgid " No devfreq devices available"
+msgstr ""
+
+#: ../src/devices/device.cpp:172 ../src/process/do_process.cpp:831
+#, c-format
+msgid "The battery reports a discharge rate of %sW\n"
+msgstr "Tempo rozładowywania baterii: %sW \\n"
+
+#: ../src/devices/device.cpp:174 ../src/process/do_process.cpp:833
+#, c-format
+msgid "The power consumed was %sJ\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:180
+#, c-format
+msgid "System baseline power is estimated at %sW\n"
+msgstr "Bazową moc systemu oszacowano na %sW \\n"
+
+#: ../src/devices/device.cpp:187
+msgid "Power est. Usage Device name\n"
+msgstr "Szac. moc Użycie Nazwa urządzenia \\n"
+
+#: ../src/devices/device.cpp:189
+msgid " Usage Device name\n"
+msgstr " Użycie Nazwa urządzenia \\n"
+
+#: ../src/devices/device.cpp:256
+#, fuzzy
+msgid "The battery reports a discharge rate of: "
+msgstr "Tempo rozładowywania baterii: %sW \\n"
+
+#: ../src/devices/device.cpp:261
+msgid "The power consumed was : "
+msgstr ""
+
+#: ../src/devices/device.cpp:268
+#, fuzzy
+msgid "The system baseline power is estimated at: "
+msgstr "Bazową moc systemu oszacowano na %sW \\n"
+
+#: ../src/devices/device.cpp:277 ../src/process/do_process.cpp:850
+#: ../src/process/do_process.cpp:852 ../src/process/do_process.cpp:926
+#: ../src/process/do_process.cpp:1077
+msgid "Usage"
+msgstr "Użycie"
+
+#: ../src/devices/device.cpp:278
+#, fuzzy
+msgid "Device Name"
+msgstr "Statystyki urządzeń"
+
+#: ../src/devices/device.cpp:280 ../src/process/do_process.cpp:935
+#: ../src/process/do_process.cpp:1082
+msgid "PW Estimate"
+msgstr ""
+
+#. Report Output
+#: ../src/devices/device.cpp:317
+msgid "Device Power Report"
+msgstr ""
+
+#: ../src/devices/network.cpp:177
+#, c-format
+msgid "Network interface: %s (%s)"
+msgstr "Interfejs sieciowy: %s (%s)"
+
+#: ../src/devices/rfkill.cpp:65 ../src/devices/rfkill.cpp:69
+#, c-format
+msgid "Radio device: %s"
+msgstr "Urządzenie radiowe: %s"
+
+#: ../src/devices/runtime_pm.cpp:216
+#, c-format
+msgid "I2C %s (%s): %s"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216 ../src/tuning/tuningi2c.cpp:57
+#: ../src/tuning/tuningi2c.cpp:59
+msgid "Adapter"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216 ../src/devlist.cpp:331
+#: ../src/tuning/tuningi2c.cpp:57 ../src/tuning/tuningi2c.cpp:59
+#, fuzzy
+msgid "Device"
+msgstr "Statystyki urządzeń"
+
+#: ../src/devices/runtime_pm.cpp:241
+#, c-format
+msgid "PCI Device: %s"
+msgstr "Urządzenie PCI: %s"
+
+#: ../src/devices/usb.cpp:51 ../src/devices/usb.cpp:96
+#: ../src/devices/usb.cpp:98
+#, c-format
+msgid "USB device: %s"
+msgstr "Urządzenie USB: %s"
+
+#: ../src/devices/usb.cpp:94
+#, c-format
+msgid "USB device: %s (%s)"
+msgstr "Urządzenie USB: %s (%s)"
+
+#: ../src/devlist.cpp:330
+msgid "Process"
+msgstr ""
+
+#. Report Output
+#. No div attribute here inherits from device power report
+#: ../src/devlist.cpp:347
+msgid "Process Device Activity"
+msgstr ""
+
+#: ../src/display.cpp:70
+msgid "Overview"
+msgstr "Przegląd"
+
+#: ../src/display.cpp:71
+msgid "Idle stats"
+msgstr "Stan jałowy"
+
+#: ../src/display.cpp:72
+msgid "Frequency stats"
+msgstr "Statystyki częstotliwości"
+
+#: ../src/display.cpp:73
+msgid "Device stats"
+msgstr "Statystyki urządzeń"
+
+#: ../src/display.cpp:131
+msgid "Exit"
+msgstr "Wyjście"
+
+#: ../src/display.cpp:132
+msgid "Navigate"
+msgstr ""
+
+#: ../src/lib.cpp:288
+#, c-format
+msgid "%7sW"
+msgstr "%7sW"
+
+#: ../src/lib.cpp:291
+#, c-format
+msgid " 0 mW"
+msgstr "0 mW"
+
+#: ../src/lib.cpp:410
+msgid "PS/2 Touchpad / Keyboard / Mouse"
+msgstr "PS/2 Touchpad / Klawiatura / Mysz"
+
+#: ../src/lib.cpp:411
+msgid "SATA controller"
+msgstr "kontroler SATA"
+
+#: ../src/lib.cpp:412
+msgid "Intel built in USB hub"
+msgstr "Intel wbudowany w hub USB"
+
+#: ../src/lib.cpp:467
+#, c-format
+msgid "glob returned GLOB_NOSPACE\n"
+msgstr ""
+
+#: ../src/lib.cpp:471
+#, c-format
+msgid "glob returned GLOB_ABORTED\n"
+msgstr ""
+
+#: ../src/lib.cpp:475
+#, c-format
+msgid "glob returned GLOB_NOMATCH\n"
+msgstr ""
+
+#: ../src/lib.cpp:513 ../src/lib.cpp:549
+#, c-format
+msgid ""
+"Model-specific registers (MSR)\t\t\t not found (try enabling "
+"CONFIG_X86_MSR).\n"
+msgstr ""
+
+#: ../src/main.cpp:103
+#, fuzzy, c-format
+msgid "PowerTOP version "
+msgstr "Wersja PowerTOP"
+
+#: ../src/main.cpp:109
+msgid "Set refresh time out"
+msgstr "Ustaw czas odświerzania"
+
+#: ../src/main.cpp:122
+msgid "Usage: powertop [OPTIONS]"
+msgstr "Użycie: powertop [OPTIONS]"
+
+#: ../src/main.cpp:123
+msgid "sets all tunable options to their GOOD setting"
+msgstr ""
+
+#: ../src/main.cpp:124
+msgid "runs powertop in calibration mode"
+msgstr "uruchom powertop w trybie kalibracji"
+
+#: ../src/main.cpp:125 ../src/main.cpp:128
+msgid "[=filename]"
+msgstr ""
+
+#: ../src/main.cpp:125
+msgid "generate a csv report"
+msgstr "generuje raport csv"
+
+#: ../src/main.cpp:126
+msgid "run in \"debug\" mode"
+msgstr "uruchom w trybie \"debug\""
+
+#: ../src/main.cpp:127
+msgid "[=devnode]"
+msgstr "[=devnode]"
+
+#: ../src/main.cpp:127
+msgid "uses an Extech Power Analyzer for measurements"
+msgstr "do pomiarów użyj Extech Power Analyzer"
+
+#: ../src/main.cpp:128
+msgid "generate a html report"
+msgstr "generuje raport html"
+
+#: ../src/main.cpp:129
+msgid "[=iterations] number of times to run each test"
+msgstr " [=iteracji] liczba powtórzeń każdego testu"
+
+#: ../src/main.cpp:130
+msgid "suppress stderr output"
+msgstr ""
+
+#: ../src/main.cpp:131 ../src/main.cpp:132
+msgid "[=seconds]"
+msgstr "[=sekund]"
+
+#: ../src/main.cpp:131
+msgid "interval for power consumption measurement"
+msgstr ""
+
+#: ../src/main.cpp:132
+msgid "generate a report for 'x' seconds"
+msgstr "generuje raport dla 'x' sekund"
+
+#: ../src/main.cpp:133
+msgid "[=workload]"
+msgstr "[=obciążenie]"
+
+#: ../src/main.cpp:133
+msgid "file to execute for workload"
+msgstr ""
+
+#: ../src/main.cpp:134
+msgid "print version information"
+msgstr "wypisz informacje o wersji"
+
+#: ../src/main.cpp:135
+msgid "print this help menu"
+msgstr "wypisuje tę informację "
+
+#: ../src/main.cpp:137
+#, fuzzy
+msgid "For more help please refer to the 'man 8 powertop'"
+msgstr "Więcej pomocy znajduje się w pliku README"
+
+#: ../src/main.cpp:232
+#, c-format
+msgid "Unknown issue running workload!\n"
+msgstr ""
+
+#: ../src/main.cpp:289
+msgid "PowerTOP is out of memory. PowerTOP is Aborting"
+msgstr "Brak pamięci. PowerTop kończy działanie"
+
+#. one to warm up everything
+#: ../src/main.cpp:297
+#, c-format
+msgid "Preparing to take measurements\n"
+msgstr "Przygotowywanie to pomiarów\\n"
+
+#: ../src/main.cpp:302
+#, c-format
+msgid "Taking %d measurement(s) for a duration of %d second(s) each.\n"
+msgstr "Wykonywanie %d pomiaru(ów) o długości %d sekund(y) każdy \\n"
+
+#: ../src/main.cpp:304
+#, c-format
+msgid "Measuring workload %s.\n"
+msgstr ""
+
+#: ../src/main.cpp:329
+#, c-format
+msgid "PowerTOP "
+msgstr "PowerTOP"
+
+#: ../src/main.cpp:330 ../src/main.cpp:380
+#, c-format
+msgid "exiting...\n"
+msgstr "wychodzenie...\\n"
+
+#: ../src/main.cpp:364
+#, c-format
+msgid "modprobe cpufreq_stats failed"
+msgstr ""
+
+#: ../src/main.cpp:367
+#, c-format
+msgid "modprobe msr failed"
+msgstr ""
+
+#: ../src/main.cpp:379 ../src/main.cpp:383
+#, c-format
+msgid "Failed to mount debugfs!\n"
+msgstr "Błąd montowania debugfs!\\n"
+
+#: ../src/main.cpp:384
+#, c-format
+msgid "Should still be able to auto tune...\n"
+msgstr ""
+
+#: ../src/main.cpp:466
+#, c-format
+msgid "Invalid CSV filename\n"
+msgstr ""
+
+#: ../src/main.cpp:482
+#, c-format
+msgid "Invalid HTML filename\n"
+msgstr ""
+
+#: ../src/main.cpp:491
+#, c-format
+msgid "Quiet mode failed!\n"
+msgstr ""
+
+#: ../src/main.cpp:559
+msgid "Leaving PowerTOP"
+msgstr "Zamykanie PowerTop"
+
+#: ../src/parameters/persistent.cpp:46 ../src/parameters/persistent.cpp:155
+msgid "Cannot save to file"
+msgstr "Nie można zapisać do pliku"
+
+#: ../src/parameters/persistent.cpp:89 ../src/parameters/persistent.cpp:180
+msgid "Cannot load from file"
+msgstr "Nie można załadować z pliku"
+
+#. '%i" is for count, do not translate
+#: ../src/parameters/persistent.cpp:138
+#, c-format
+msgid "Loaded %i prior measurements\n"
+msgstr "Wczytano %i poprzednich pomiarów \\n"
+
+#: ../src/parameters/persistent.cpp:181
+msgid ""
+"File will be loaded after taking minimum number of measurement(s) with "
+"battery only \n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:115
+#, c-format
+msgid ""
+"Too many open files, please increase the limit of open file descriptors.\n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:117
+#, c-format
+msgid "PowerTOP %s needs the kernel to support the 'perf' subsystem\n"
+msgstr "PowerTOP %s wymaga aby kernel wspierał narzędzie 'perf' \\n"
+
+#: ../src/perf/perf.cpp:118
+#, c-format
+msgid "as well as support for trace points in the kernel:\n"
+msgstr "tak jak wsparcie kernela dla tracepoit-ów: \\n"
+
+#: ../src/process/do_process.cpp:819
+#, c-format
+msgid ""
+"Estimated power: %5.1f Measured power: %5.1f Sum: %5.1f\n"
+"\n"
+msgstr "Moc szacunkowa: %5.1f Moc zmierzona: %5.1f Suma: %5.1f\\n\\n"
+
+#: ../src/process/do_process.cpp:838
+#, c-format
+msgid "The estimated remaining time is %i hours, %i minutes\n"
+msgstr ""
+
+#: ../src/process/do_process.cpp:846
+msgid "Summary"
+msgstr "Podsumowanie"
+
+#: ../src/process/do_process.cpp:846
+msgid "wakeups/second"
+msgstr "Pobudki/sekunda"
+
+#: ../src/process/do_process.cpp:846
+msgid "GPU ops/seconds"
+msgstr "GPU operacji/sekunde"
+
+#: ../src/process/do_process.cpp:846
+msgid "VFS ops/sec and"
+msgstr "VFS operacji/sek i"
+
+#: ../src/process/do_process.cpp:846
+msgid "CPU use"
+msgstr "Zużywanie CPU"
+
+#: ../src/process/do_process.cpp:850
+msgid "Power est."
+msgstr "Estymacja mocy"
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:1078
+msgid "Events/s"
+msgstr "Zdarzenie/nia"
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:931 ../src/process/do_process.cpp:1079
+msgid "Category"
+msgstr "Kategoria"
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:932 ../src/process/do_process.cpp:1080
+#: ../src/tuning/tuning.cpp:242 ../src/tuning/tuning.cpp:270
+#: ../src/tuning/tuning.cpp:288 ../src/wakeup/waketab.cpp:155
+msgid "Description"
+msgstr "Opis"
+
+#: ../src/process/do_process.cpp:927
+msgid "Wakeups/s"
+msgstr "Pobutka/i"
+
+#: ../src/process/do_process.cpp:928
+msgid "GPU ops/s"
+msgstr "GUP opercji/s"
+
+#: ../src/process/do_process.cpp:929
+msgid "Disk IO/s"
+msgstr "Wejścia/Wyjścia dysku"
+
+#: ../src/process/do_process.cpp:930
+msgid "GFX Wakeups/s"
+msgstr "GFX Wakeups/s"
+
+#: ../src/process/do_process.cpp:1017
+msgid "Overview of Software Power Consumers"
+msgstr "Przedląd programowych odbiorników energii"
+
+#: ../src/process/do_process.cpp:1057
+msgid "Target:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1058
+msgid "1 units/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1059
+msgid "System: "
+msgstr ""
+
+#: ../src/process/do_process.cpp:1061
+#, fuzzy
+msgid " wakeup/s"
+msgstr "Pobutka/i"
+
+#: ../src/process/do_process.cpp:1062
+msgid "CPU: "
+msgstr ""
+
+#: ../src/process/do_process.cpp:1064
+#, fuzzy, c-format
+msgid "% usage"
+msgstr "Użycie"
+
+#: ../src/process/do_process.cpp:1065
+msgid "GPU:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1067 ../src/process/do_process.cpp:1073
+#, fuzzy
+msgid " ops/s"
+msgstr "GUP opercji/s"
+
+#: ../src/process/do_process.cpp:1068
+msgid "GFX:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1070
+#, fuzzy
+msgid " wakeups/s"
+msgstr "Pobutka/i"
+
+#: ../src/process/do_process.cpp:1071
+msgid "VFS:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1139
+#, fuzzy
+msgid "Top 10 Power Consumers"
+msgstr "Przedląd programowych odbiorników energii"
+
+#: ../src/report/report.cpp:122
+#, fuzzy
+msgid "PowerTOP Version"
+msgstr "Wersja PowerTOP"
+
+#: ../src/report/report.cpp:131
+#, fuzzy
+msgid "Kernel Version"
+msgstr "Wersja PowerTOP"
+
+#: ../src/report/report.cpp:135
+msgid "System Name"
+msgstr ""
+
+#: ../src/report/report.cpp:142
+msgid "CPU Information"
+msgstr ""
+
+#: ../src/report/report.cpp:154
+msgid "OS Information"
+msgstr ""
+
+#: ../src/report/report.cpp:161
+#, fuzzy
+msgid "System Information"
+msgstr "wypisz informacje o wersji"
+
+#: ../src/report/report.cpp:195
+#, fuzzy, c-format
+msgid "Cannot open output file %s (%s)\n"
+msgstr "Nie można utworzyć pliku tymczasowego\\n"
+
+#: ../src/report/report.cpp:211
+#, c-format
+msgid "PowerTOP outputing using base filename %s\n"
+msgstr ""
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:49
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+msgid "Good"
+msgstr "Dobrze"
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:50
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+msgid "Bad"
+msgstr "Źle"
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:51
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+#: ../src/wakeup/wakeup.cpp:50
+msgid "Unknown"
+msgstr "Nieznany"
+
+#: ../src/tuning/bluetooth.cpp:48
+#, c-format
+msgid "Bluetooth device interface status"
+msgstr "Status interfejsu urządzenia Bluetooth"
+
+#: ../src/tuning/ethernet.cpp:54 ../src/wakeup/wakeup_ethernet.cpp:51
+#, c-format
+msgid "Wake-on-lan status for device %s"
+msgstr "Status Wake-on-lan dla urządzenia %s"
+
+#: ../src/tuning/runtime.cpp:48
+#, c-format
+msgid "Runtime PM for %s device %s"
+msgstr ""
+
+#: ../src/tuning/runtime.cpp:50
+#, c-format
+msgid "%s device %s has no runtime power management"
+msgstr ""
+
+#: ../src/tuning/runtime.cpp:74
+#, c-format
+msgid "PCI Device %s has no runtime power management"
+msgstr ""
+
+#: ../src/tuning/runtime.cpp:76
+#, c-format
+msgid "Runtime PM for PCI Device %s"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:62
+msgid "Enable Audio codec power management"
+msgstr "Zarządzanie zasilaniem kodeka audio włączone"
+
+#: ../src/tuning/tuning.cpp:63
+msgid "NMI watchdog should be turned off"
+msgstr "Watchdog NMI powinien być wyłączony"
+
+#: ../src/tuning/tuning.cpp:64
+msgid "Power Aware CPU scheduler"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:65
+msgid "VM writeback timeout"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:81
+msgid "Tunables"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:81
+msgid " <ESC> Exit | <Enter> Toggle tunable | <r> Window refresh"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:243 ../src/wakeup/waketab.cpp:156
+msgid "Script"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:257
+msgid "Software Settings in Need of Tuning"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:276
+msgid "Untunable Software Issues"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:300
+msgid "Optimal Tuned Software Settings"
+msgstr ""
+
+#: ../src/tuning/tuningi2c.cpp:57
+#, c-format
+msgid "Runtime PM for I2C %s %s (%s)"
+msgstr ""
+
+#: ../src/tuning/tuningi2c.cpp:59
+#, c-format
+msgid "I2C %s %s has no runtime power management"
+msgstr ""
+
+#: ../src/tuning/tuningsysfs.cpp:123
+#, fuzzy, c-format
+msgid "Enable SATA link power management for %s"
+msgstr "Zarządzanie zasilaniem kodeka audio włączone"
+
+#: ../src/tuning/tuningusb.cpp:54
+#, c-format
+msgid "Autosuspend for unknown USB device %s (%s:%s)"
+msgstr ""
+
+#: ../src/tuning/tuningusb.cpp:71 ../src/tuning/tuningusb.cpp:73
+#: ../src/tuning/tuningusb.cpp:75
+#, c-format
+msgid "Autosuspend for USB device %s [%s]"
+msgstr ""
+
+#: ../src/tuning/wifi.cpp:48
+#, c-format
+msgid "Wireless Power Saving for interface %s"
+msgstr "Bezprzewodowe oszczędzanie energii dla interfejsu %s"
+
+#: ../src/wakeup/waketab.cpp:42
+#, fuzzy
+msgid "WakeUp"
+msgstr "Pobutka/i"
+
+#: ../src/wakeup/waketab.cpp:42
+msgid " <ESC> Exit | <Enter> Toggle wakeup | <r> Window refresh"
+msgstr ""
+
+#. Report Output
+#: ../src/wakeup/waketab.cpp:170
+#, fuzzy
+msgid "Wake status of the devices"
+msgstr "Status Wake-on-lan dla urządzenia %s"
+
+#: ../src/wakeup/wakeup.cpp:48 ../src/wakeup/wakeup_ethernet.cpp:47
+#: ../src/wakeup/wakeup_usb.cpp:47
+msgid "Enable"
+msgstr ""
+
+#: ../src/wakeup/wakeup.cpp:49 ../src/wakeup/wakeup_ethernet.cpp:47
+#: ../src/wakeup/wakeup_usb.cpp:47
+msgid "Disable"
+msgstr ""
+
+#: ../src/wakeup/wakeup_usb.cpp:51
+#, fuzzy, c-format
+msgid "Wake status for USB device %s"
+msgstr "Status Wake-on-lan dla urządzenia %s"
+
+#~ msgid "Actual"
+#~ msgstr "rzeczywisty"
+
+#~ msgid "Power Consumption Summary"
+#~ msgstr "Podsumowanie poboru mocy"
+
+#~ msgid "GPU ops/second"
+#~ msgstr "GPU ops/sekundę"
+
+#~ msgid "VFS ops/sec"
+#~ msgstr "VFS ops/sec"
+
+#~ msgid "GFX wakes/sec and"
+#~ msgstr "GFX wakes/sec i"
+
+#~ msgid "[=FILENAME]"
+#~ msgstr "[=NAZWAPLIKU]"
diff --git a/po/powertop.pot b/po/powertop.pot
new file mode 100644
index 0000000..a708e67
--- /dev/null
+++ b/po/powertop.pot
@@ -0,0 +1,949 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Intel Corporation
+# This file is distributed under the same license as the powertop package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: powertop 2.15\n"
+"Report-Msgid-Bugs-To: \"powertop@lists.01.org\"\n"
+"POT-Creation-Date: 2022-09-29 04:45-0700\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: src/calibrate/calibrate.cpp:238
+#, c-format
+msgid "Cannot create temp file\n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:258
+#, c-format
+msgid "Calibrating: CPU usage on %i threads\n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:273
+#, c-format
+msgid "Calibrating: CPU wakeup power consumption\n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:290
+#, c-format
+msgid "Calibrating USB devices\n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:292 src/calibrate/calibrate.cpp:309
+#: src/calibrate/calibrate.cpp:317 src/calibrate/calibrate.cpp:334
+#, c-format
+msgid ".... device %s \n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:307
+#, c-format
+msgid "Calibrating radio devices\n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:331
+#, c-format
+msgid "Calibrating backlight\n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:355 src/calibrate/calibrate.cpp:365
+#, c-format
+msgid "Calibrating idle\n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:378
+#, c-format
+msgid "Calibrating: disk usage \n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:403
+msgid "Starting PowerTOP power estimate calibration \n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:426
+msgid "Finishing PowerTOP power estimate calibration \n"
+msgstr ""
+
+#: src/calibrate/calibrate.cpp:430
+#, c-format
+msgid "Parameters after calibration:\n"
+msgstr ""
+
+#: src/cpu/abstract_cpu.cpp:74
+msgid "Idle"
+msgstr ""
+
+#: src/cpu/abstract_cpu.cpp:76
+msgid "Turbo Mode"
+msgstr ""
+
+#: src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(HW)"
+msgstr ""
+
+#: src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(OS)"
+msgstr ""
+
+#: src/cpu/cpu_core.cpp:91 src/cpu/intel_cpus.cpp:367
+#, c-format
+msgid " Core"
+msgstr ""
+
+#: src/cpu/cpu.cpp:85
+#, c-format
+msgid "cpu package %i"
+msgstr ""
+
+#: src/cpu/cpu.cpp:86
+msgid "cpu package"
+msgstr ""
+
+#: src/cpu/cpu.cpp:89 src/cpu/cpu.cpp:96
+#, c-format
+msgid "package-%i"
+msgstr ""
+
+#: src/cpu/cpu.cpp:90
+msgid "cpu rapl package"
+msgstr ""
+
+#: src/cpu/cpu.cpp:97
+msgid "dram rapl package"
+msgstr ""
+
+#: src/cpu/cpu.cpp:471
+msgid "Processor Idle State Report"
+msgstr ""
+
+#: src/cpu/cpu.cpp:535 src/cpu/cpu.cpp:761
+msgid "Package"
+msgstr ""
+
+#: src/cpu/cpu.cpp:572 src/cpu/cpu.cpp:783
+#, c-format
+msgid "Core %d"
+msgstr ""
+
+#: src/cpu/cpu.cpp:579
+#, c-format
+msgid "GPU %d"
+msgstr ""
+
+#: src/cpu/cpu.cpp:602
+msgid "CPU"
+msgstr ""
+
+#: src/cpu/cpu.cpp:684
+msgid "Processor Frequency Report"
+msgstr ""
+
+#: src/cpu/cpu.cpp:804
+#, c-format
+msgid "CPU %d"
+msgstr ""
+
+#: src/cpu/cpu.cpp:1005
+#, c-format
+msgid "cpu_idle event returned no state?\n"
+msgstr ""
+
+#: src/cpu/cpu.cpp:1020
+#, c-format
+msgid "power or cpu_frequency event returned no state?\n"
+msgstr ""
+
+#: src/cpu/cpu_linux.cpp:79
+msgid "C0 polling"
+msgstr ""
+
+#: src/cpu/cpu_linux.cpp:242
+#, c-format
+msgid " CPU(OS) %i"
+msgstr ""
+
+#: src/cpu/cpu_linux.cpp:341 src/cpu/intel_cpus.cpp:733
+#, c-format
+msgid " CPU %i"
+msgstr ""
+
+#: src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(HW)"
+msgstr ""
+
+#: src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(OS)"
+msgstr ""
+
+#: src/cpu/cpu_package.cpp:104 src/cpu/intel_cpus.cpp:498
+#, c-format
+msgid " Package"
+msgstr ""
+
+#: src/cpu/intel_cpus.cpp:152
+#, c-format
+msgid "read_msr cpu%d 0x%llx : "
+msgstr ""
+
+#: src/cpu/intel_cpus.cpp:656
+msgid "C0 active"
+msgstr ""
+
+#: src/cpu/intel_cpus.cpp:714
+#, c-format
+msgid "Average"
+msgstr ""
+
+#: src/cpu/intel_gpu.cpp:64
+#, c-format
+msgid " GPU "
+msgstr ""
+
+#: src/devices/ahci.cpp:154
+#, c-format
+msgid "SATA link: %s"
+msgstr ""
+
+#: src/devices/ahci.cpp:156
+#, c-format
+msgid "SATA disk: %s"
+msgstr ""
+
+#: src/devices/ahci.cpp:374
+msgid "AHCI ALPM Residency Statistics - Not supported on this macine"
+msgstr ""
+
+#: src/devices/ahci.cpp:389
+msgid "Link"
+msgstr ""
+
+#: src/devices/ahci.cpp:390
+msgid "Active"
+msgstr ""
+
+#: src/devices/ahci.cpp:391
+msgid "Partial"
+msgstr ""
+
+#: src/devices/ahci.cpp:392
+msgid "Slumber"
+msgstr ""
+
+#: src/devices/ahci.cpp:393
+msgid "Devslp"
+msgstr ""
+
+#: src/devices/ahci.cpp:399
+msgid "AHCI ALPM Residency Statistics"
+msgstr ""
+
+#: src/devices/alsa.cpp:77
+#, c-format
+msgid "Audio codec %s: %s (%s)"
+msgstr ""
+
+#: src/devices/alsa.cpp:79 src/devices/alsa.cpp:81
+#, c-format
+msgid "Audio codec %s: %s"
+msgstr ""
+
+#: src/devices/devfreq.cpp:260
+msgid "Device Freq stats"
+msgstr ""
+
+#: src/devices/devfreq.cpp:278
+msgid " Devfreq is not enabled"
+msgstr ""
+
+#: src/devices/devfreq.cpp:283
+msgid " No devfreq devices available"
+msgstr ""
+
+#: src/devices/device.cpp:172 src/process/do_process.cpp:831
+#, c-format
+msgid "The battery reports a discharge rate of %sW\n"
+msgstr ""
+
+#: src/devices/device.cpp:174 src/process/do_process.cpp:833
+#, c-format
+msgid "The energy consumed was %sJ\n"
+msgstr ""
+
+#: src/devices/device.cpp:180
+#, c-format
+msgid "System baseline power is estimated at %sW\n"
+msgstr ""
+
+#: src/devices/device.cpp:187
+msgid "Power est. Usage Device name\n"
+msgstr ""
+
+#: src/devices/device.cpp:189
+msgid " Usage Device name\n"
+msgstr ""
+
+#: src/devices/device.cpp:256
+msgid "The battery reports a discharge rate of: "
+msgstr ""
+
+#: src/devices/device.cpp:261
+msgid "The energy consumed was : "
+msgstr ""
+
+#: src/devices/device.cpp:268
+msgid "The system baseline power is estimated at: "
+msgstr ""
+
+#: src/devices/device.cpp:277 src/process/do_process.cpp:850
+#: src/process/do_process.cpp:852 src/process/do_process.cpp:926
+#: src/process/do_process.cpp:1077
+msgid "Usage"
+msgstr ""
+
+#: src/devices/device.cpp:278
+msgid "Device Name"
+msgstr ""
+
+#: src/devices/device.cpp:280 src/process/do_process.cpp:935
+#: src/process/do_process.cpp:1082
+msgid "PW Estimate"
+msgstr ""
+
+#: src/devices/device.cpp:317
+msgid "Device Power Report"
+msgstr ""
+
+#: src/devices/network.cpp:177
+#, c-format
+msgid "Network interface: %s (%s)"
+msgstr ""
+
+#: src/devices/rfkill.cpp:65 src/devices/rfkill.cpp:69
+#, c-format
+msgid "Radio device: %s"
+msgstr ""
+
+#: src/devices/runtime_pm.cpp:216
+#, c-format
+msgid "I2C %s (%s): %s"
+msgstr ""
+
+#: src/devices/runtime_pm.cpp:216 src/tuning/tuningi2c.cpp:57
+#: src/tuning/tuningi2c.cpp:59
+msgid "Adapter"
+msgstr ""
+
+#: src/devices/runtime_pm.cpp:216 src/devlist.cpp:331
+#: src/tuning/tuningi2c.cpp:57 src/tuning/tuningi2c.cpp:59
+msgid "Device"
+msgstr ""
+
+#: src/devices/runtime_pm.cpp:241
+#, c-format
+msgid "PCI Device: %s"
+msgstr ""
+
+#: src/devices/usb.cpp:51 src/devices/usb.cpp:96 src/devices/usb.cpp:98
+#, c-format
+msgid "USB device: %s"
+msgstr ""
+
+#: src/devices/usb.cpp:94
+#, c-format
+msgid "USB device: %s (%s)"
+msgstr ""
+
+#: src/devlist.cpp:330
+msgid "Process"
+msgstr ""
+
+#: src/devlist.cpp:347
+msgid "Process Device Activity"
+msgstr ""
+
+#: src/display.cpp:70
+msgid "Overview"
+msgstr ""
+
+#: src/display.cpp:71
+msgid "Idle stats"
+msgstr ""
+
+#: src/display.cpp:72
+msgid "Frequency stats"
+msgstr ""
+
+#: src/display.cpp:73
+msgid "Device stats"
+msgstr ""
+
+#: src/display.cpp:131
+msgid "Exit"
+msgstr ""
+
+#: src/display.cpp:132
+msgid "Navigate"
+msgstr ""
+
+#: src/lib.cpp:288
+#, c-format
+msgid "%7sW"
+msgstr ""
+
+#: src/lib.cpp:291
+#, c-format
+msgid " 0 mW"
+msgstr ""
+
+#: src/lib.cpp:410
+msgid "PS/2 Touchpad / Keyboard / Mouse"
+msgstr ""
+
+#: src/lib.cpp:411
+msgid "SATA controller"
+msgstr ""
+
+#: src/lib.cpp:412
+msgid "Intel built in USB hub"
+msgstr ""
+
+#: src/lib.cpp:467
+#, c-format
+msgid "glob returned GLOB_NOSPACE\n"
+msgstr ""
+
+#: src/lib.cpp:471
+#, c-format
+msgid "glob returned GLOB_ABORTED\n"
+msgstr ""
+
+#: src/lib.cpp:475
+#, c-format
+msgid "glob returned GLOB_NOMATCH\n"
+msgstr ""
+
+#: src/lib.cpp:513 src/lib.cpp:549
+#, c-format
+msgid ""
+"Model-specific registers (MSR)\t\t\t not found (try enabling "
+"CONFIG_X86_MSR).\n"
+msgstr ""
+
+#: src/main.cpp:104
+#, c-format
+msgid "PowerTOP version "
+msgstr ""
+
+#: src/main.cpp:110
+msgid "Set refresh time out"
+msgstr ""
+
+#: src/main.cpp:123
+msgid "Usage: powertop [OPTIONS]"
+msgstr ""
+
+#: src/main.cpp:124
+msgid "sets all tunable options to their GOOD setting"
+msgstr ""
+
+#: src/main.cpp:125
+msgid "runs powertop in calibration mode"
+msgstr ""
+
+#: src/main.cpp:126 src/main.cpp:129
+msgid "[=filename]"
+msgstr ""
+
+#: src/main.cpp:126
+msgid "generate a csv report"
+msgstr ""
+
+#: src/main.cpp:127
+msgid "run in \"debug\" mode"
+msgstr ""
+
+#: src/main.cpp:128
+msgid "[=devnode]"
+msgstr ""
+
+#: src/main.cpp:128
+msgid "uses an Extech Power Analyzer for measurements"
+msgstr ""
+
+#: src/main.cpp:129
+msgid "generate a html report"
+msgstr ""
+
+#: src/main.cpp:130
+msgid "[=iterations] number of times to run each test"
+msgstr ""
+
+#: src/main.cpp:131
+msgid "suppress stderr output"
+msgstr ""
+
+#: src/main.cpp:132 src/main.cpp:133
+msgid "[=seconds]"
+msgstr ""
+
+#: src/main.cpp:132
+msgid "interval for power consumption measurement"
+msgstr ""
+
+#: src/main.cpp:133
+msgid "generate a report for 'x' seconds"
+msgstr ""
+
+#: src/main.cpp:134
+msgid "[=workload]"
+msgstr ""
+
+#: src/main.cpp:134
+msgid "file to execute for workload"
+msgstr ""
+
+#: src/main.cpp:135
+msgid "print version information"
+msgstr ""
+
+#: src/main.cpp:136
+msgid "print this help menu"
+msgstr ""
+
+#: src/main.cpp:138
+msgid "For more help please refer to the 'man 8 powertop'"
+msgstr ""
+
+#: src/main.cpp:233
+#, c-format
+msgid "Unknown issue running workload!\n"
+msgstr ""
+
+#: src/main.cpp:290
+msgid "PowerTOP is out of memory. PowerTOP is Aborting"
+msgstr ""
+
+#: src/main.cpp:298
+#, c-format
+msgid "Preparing to take measurements\n"
+msgstr ""
+
+#: src/main.cpp:303
+#, c-format
+msgid "Taking %d measurement(s) for a duration of %d second(s) each.\n"
+msgstr ""
+
+#: src/main.cpp:305
+#, c-format
+msgid "Measuring workload %s.\n"
+msgstr ""
+
+#: src/main.cpp:330
+#, c-format
+msgid "PowerTOP "
+msgstr ""
+
+#: src/main.cpp:331 src/main.cpp:381
+#, c-format
+msgid "exiting...\n"
+msgstr ""
+
+#: src/main.cpp:365
+#, c-format
+msgid "modprobe cpufreq_stats failed\n"
+msgstr ""
+
+#: src/main.cpp:368
+#, c-format
+msgid "modprobe msr failed\n"
+msgstr ""
+
+#: src/main.cpp:380 src/main.cpp:384
+#, c-format
+msgid "Failed to mount debugfs!\n"
+msgstr ""
+
+#: src/main.cpp:385
+#, c-format
+msgid "Should still be able to auto tune...\n"
+msgstr ""
+
+#: src/main.cpp:467
+#, c-format
+msgid "Invalid CSV filename\n"
+msgstr ""
+
+#: src/main.cpp:483
+#, c-format
+msgid "Invalid HTML filename\n"
+msgstr ""
+
+#: src/main.cpp:492
+#, c-format
+msgid "Quiet mode failed!\n"
+msgstr ""
+
+#: src/main.cpp:560
+msgid "Leaving PowerTOP"
+msgstr ""
+
+#: src/parameters/persistent.cpp:46 src/parameters/persistent.cpp:155
+msgid "Cannot save to file"
+msgstr ""
+
+#: src/parameters/persistent.cpp:89 src/parameters/persistent.cpp:180
+msgid "Cannot load from file"
+msgstr ""
+
+#: src/parameters/persistent.cpp:138
+#, c-format
+msgid "Loaded %i prior measurements\n"
+msgstr ""
+
+#: src/parameters/persistent.cpp:181
+msgid ""
+"File will be loaded after taking minimum number of measurement(s) with "
+"battery only \n"
+msgstr ""
+
+#: src/perf/perf.cpp:115
+#, c-format
+msgid ""
+"Too many open files, please increase the limit of open file descriptors.\n"
+msgstr ""
+
+#: src/perf/perf.cpp:117
+#, c-format
+msgid "PowerTOP %s needs the kernel to support the 'perf' subsystem\n"
+msgstr ""
+
+#: src/perf/perf.cpp:118
+#, c-format
+msgid "as well as support for trace points in the kernel:\n"
+msgstr ""
+
+#: src/process/do_process.cpp:819
+#, c-format
+msgid ""
+"Estimated power: %5.1f Measured power: %5.1f Sum: %5.1f\n"
+"\n"
+msgstr ""
+
+#: src/process/do_process.cpp:838
+#, c-format
+msgid "The estimated remaining time is %i hours, %i minutes\n"
+msgstr ""
+
+#: src/process/do_process.cpp:846
+msgid "Summary"
+msgstr ""
+
+#: src/process/do_process.cpp:846
+msgid "wakeups/second"
+msgstr ""
+
+#: src/process/do_process.cpp:846
+msgid "GPU ops/seconds"
+msgstr ""
+
+#: src/process/do_process.cpp:846
+msgid "VFS ops/sec and"
+msgstr ""
+
+#: src/process/do_process.cpp:846
+msgid "CPU use"
+msgstr ""
+
+#: src/process/do_process.cpp:850
+msgid "Power est."
+msgstr ""
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:1078
+msgid "Events/s"
+msgstr ""
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:931 src/process/do_process.cpp:1079
+msgid "Category"
+msgstr ""
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:932 src/process/do_process.cpp:1080
+#: src/tuning/tuning.cpp:242 src/tuning/tuning.cpp:270
+#: src/tuning/tuning.cpp:295 src/wakeup/waketab.cpp:155
+msgid "Description"
+msgstr ""
+
+#: src/process/do_process.cpp:927
+msgid "Wakeups/s"
+msgstr ""
+
+#: src/process/do_process.cpp:928
+msgid "GPU ops/s"
+msgstr ""
+
+#: src/process/do_process.cpp:929
+msgid "Disk IO/s"
+msgstr ""
+
+#: src/process/do_process.cpp:930
+msgid "GFX Wakeups/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1017
+msgid "Overview of Software Power Consumers"
+msgstr ""
+
+#: src/process/do_process.cpp:1057
+msgid "Target:"
+msgstr ""
+
+#: src/process/do_process.cpp:1058
+msgid "1 units/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1059
+msgid "System: "
+msgstr ""
+
+#: src/process/do_process.cpp:1061
+msgid " wakeup/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1062
+msgid "CPU: "
+msgstr ""
+
+#: src/process/do_process.cpp:1064
+#, c-format
+msgid "% usage"
+msgstr ""
+
+#: src/process/do_process.cpp:1065
+msgid "GPU:"
+msgstr ""
+
+#: src/process/do_process.cpp:1067 src/process/do_process.cpp:1073
+msgid " ops/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1068
+msgid "GFX:"
+msgstr ""
+
+#: src/process/do_process.cpp:1070
+msgid " wakeups/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1071
+msgid "VFS:"
+msgstr ""
+
+#: src/process/do_process.cpp:1139
+msgid "Top 10 Power Consumers"
+msgstr ""
+
+#: src/report/report.cpp:122
+msgid "PowerTOP Version"
+msgstr ""
+
+#: src/report/report.cpp:131
+msgid "Kernel Version"
+msgstr ""
+
+#: src/report/report.cpp:135
+msgid "System Name"
+msgstr ""
+
+#: src/report/report.cpp:142
+msgid "CPU Information"
+msgstr ""
+
+#: src/report/report.cpp:154
+msgid "OS Information"
+msgstr ""
+
+#: src/report/report.cpp:161
+msgid "System Information"
+msgstr ""
+
+#: src/report/report.cpp:195
+#, c-format
+msgid "Cannot open output file %s (%s)\n"
+msgstr ""
+
+#: src/report/report.cpp:211
+#, c-format
+msgid "PowerTOP outputting using base filename %s\n"
+msgstr ""
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:49
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45
+msgid "Good"
+msgstr ""
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:50
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45
+msgid "Bad"
+msgstr ""
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:51
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45 src/wakeup/wakeup.cpp:50
+msgid "Unknown"
+msgstr ""
+
+#: src/tuning/bluetooth.cpp:48
+#, c-format
+msgid "Bluetooth device interface status"
+msgstr ""
+
+#: src/tuning/ethernet.cpp:54 src/wakeup/wakeup_ethernet.cpp:51
+#, c-format
+msgid "Wake-on-lan status for device %s"
+msgstr ""
+
+#: src/tuning/runtime.cpp:48
+#, c-format
+msgid "Runtime PM for %s device %s"
+msgstr ""
+
+#: src/tuning/runtime.cpp:50
+#, c-format
+msgid "%s device %s has no runtime power management"
+msgstr ""
+
+#: src/tuning/runtime.cpp:74
+#, c-format
+msgid "PCI Device %s has no runtime power management"
+msgstr ""
+
+#: src/tuning/runtime.cpp:76
+#, c-format
+msgid "Runtime PM for PCI Device %s"
+msgstr ""
+
+#: src/tuning/runtime.cpp:80
+#, c-format
+msgid "Runtime PM for port %s of PCI device: %s"
+msgstr ""
+
+#: src/tuning/runtime.cpp:83
+#, c-format
+msgid "Runtime PM for disk %s"
+msgstr ""
+
+#: src/tuning/tuning.cpp:62
+msgid "Enable Audio codec power management"
+msgstr ""
+
+#: src/tuning/tuning.cpp:63
+msgid "NMI watchdog should be turned off"
+msgstr ""
+
+#: src/tuning/tuning.cpp:64
+msgid "Power Aware CPU scheduler"
+msgstr ""
+
+#: src/tuning/tuning.cpp:65
+msgid "VM writeback timeout"
+msgstr ""
+
+#: src/tuning/tuning.cpp:81
+msgid "Tunables"
+msgstr ""
+
+#: src/tuning/tuning.cpp:81
+msgid " <ESC> Exit | <Enter> Toggle tunable | <r> Window refresh"
+msgstr ""
+
+#: src/tuning/tuning.cpp:243 src/wakeup/waketab.cpp:156
+msgid "Script"
+msgstr ""
+
+#: src/tuning/tuning.cpp:257
+msgid "Software Settings in Need of Tuning"
+msgstr ""
+
+#: src/tuning/tuning.cpp:276
+msgid "Untunable Software Issues"
+msgstr ""
+
+#: src/tuning/tuning.cpp:307
+msgid "Optimal Tuned Software Settings"
+msgstr ""
+
+#: src/tuning/tuningi2c.cpp:57
+#, c-format
+msgid "Runtime PM for I2C %s %s (%s)"
+msgstr ""
+
+#: src/tuning/tuningi2c.cpp:59
+#, c-format
+msgid "I2C %s %s has no runtime power management"
+msgstr ""
+
+#: src/tuning/tuningsysfs.cpp:123
+#, c-format
+msgid "Enable SATA link power management for %s"
+msgstr ""
+
+#: src/tuning/tuningusb.cpp:54
+#, c-format
+msgid "Autosuspend for unknown USB device %s (%s:%s)"
+msgstr ""
+
+#: src/tuning/tuningusb.cpp:71 src/tuning/tuningusb.cpp:73
+#: src/tuning/tuningusb.cpp:75
+#, c-format
+msgid "Autosuspend for USB device %s [%s]"
+msgstr ""
+
+#: src/tuning/wifi.cpp:48
+#, c-format
+msgid "Wireless Power Saving for interface %s"
+msgstr ""
+
+#: src/wakeup/waketab.cpp:42
+msgid "WakeUp"
+msgstr ""
+
+#: src/wakeup/waketab.cpp:42
+msgid " <ESC> Exit | <Enter> Toggle wakeup | <r> Window refresh"
+msgstr ""
+
+#: src/wakeup/waketab.cpp:170
+msgid "Wake status of the devices"
+msgstr ""
+
+#: src/wakeup/wakeup.cpp:48 src/wakeup/wakeup_ethernet.cpp:47
+#: src/wakeup/wakeup_usb.cpp:47
+msgid "Enabled"
+msgstr ""
+
+#: src/wakeup/wakeup.cpp:49 src/wakeup/wakeup_ethernet.cpp:47
+#: src/wakeup/wakeup_usb.cpp:47
+msgid "Disabled"
+msgstr ""
+
+#: src/wakeup/wakeup_usb.cpp:51
+#, c-format
+msgid "Wake status for USB device %s"
+msgstr ""
diff --git a/po/pt_BR.po b/po/pt_BR.po
new file mode 100644
index 0000000..16a7425
--- /dev/null
+++ b/po/pt_BR.po
@@ -0,0 +1,999 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Intel Corporation
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Nelson A. de Oliveira <naoliv@debian.org>, 2013
+# Nelson A. de Oliveira <naoliv@gmail.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: PowerTOP\n"
+"Report-Msgid-Bugs-To: powertop@lists.01.org\n"
+"POT-Creation-Date: 2019-01-04 13:55-0800\n"
+"PO-Revision-Date: 2013-11-05 08:40+0000\n"
+"Last-Translator: Margie Foster <margie@linux.intel.com>\n"
+"Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/"
+"PowerTOP/language/pt_BR/)\n"
+"Language: pt_BR\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+#: ../src/calibrate/calibrate.cpp:238
+#, c-format
+msgid "Cannot create temp file\n"
+msgstr "Impossível criar arquivo temporário\n"
+
+#: ../src/calibrate/calibrate.cpp:258
+#, c-format
+msgid "Calibrating: CPU usage on %i threads\n"
+msgstr "Calibrando: uso de CPU em %i threads\n"
+
+#: ../src/calibrate/calibrate.cpp:273
+#, c-format
+msgid "Calibrating: CPU wakeup power consumption\n"
+msgstr "Calibrando: consumo de energia de ativação da CPU\n"
+
+#: ../src/calibrate/calibrate.cpp:290
+#, c-format
+msgid "Calibrating USB devices\n"
+msgstr "Calibrando dispositivos USB\n"
+
+#: ../src/calibrate/calibrate.cpp:292 ../src/calibrate/calibrate.cpp:309
+#: ../src/calibrate/calibrate.cpp:317 ../src/calibrate/calibrate.cpp:334
+#, c-format
+msgid ".... device %s \n"
+msgstr ".... dispositivo %s \n"
+
+#: ../src/calibrate/calibrate.cpp:307
+#, c-format
+msgid "Calibrating radio devices\n"
+msgstr "Calibrando dispositivos de rádio\n"
+
+#: ../src/calibrate/calibrate.cpp:331
+#, c-format
+msgid "Calibrating backlight\n"
+msgstr "Calibrando luz de fundo\n"
+
+#: ../src/calibrate/calibrate.cpp:355 ../src/calibrate/calibrate.cpp:365
+#, c-format
+msgid "Calibrating idle\n"
+msgstr "Calibrando inatividade\n"
+
+#: ../src/calibrate/calibrate.cpp:378
+#, c-format
+msgid "Calibrating: disk usage \n"
+msgstr "Calibrando: uso de disco \n"
+
+#: ../src/calibrate/calibrate.cpp:403
+msgid "Starting PowerTOP power estimate calibration \n"
+msgstr "Iniciando calibração de estimativa de consumo \n"
+
+#: ../src/calibrate/calibrate.cpp:426
+msgid "Finishing PowerTOP power estimate calibration \n"
+msgstr "Finalizando calibração de estimativa de consumo \n"
+
+#: ../src/calibrate/calibrate.cpp:430
+#, c-format
+msgid "Parameters after calibration:\n"
+msgstr "Parâmetros após calibração:\n"
+
+#: ../src/cpu/abstract_cpu.cpp:74
+msgid "Idle"
+msgstr ""
+
+#: ../src/cpu/abstract_cpu.cpp:76
+msgid "Turbo Mode"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(HW)"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(OS)"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:91 ../src/cpu/intel_cpus.cpp:324
+#, c-format
+msgid " Core"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:85
+#, c-format
+msgid "cpu package %i"
+msgstr "pacote cpu %i"
+
+#: ../src/cpu/cpu.cpp:86
+msgid "cpu package"
+msgstr "pacote cpu"
+
+#: ../src/cpu/cpu.cpp:89 ../src/cpu/cpu.cpp:96
+#, fuzzy, c-format
+msgid "package-%i"
+msgstr "Pacote %i"
+
+#: ../src/cpu/cpu.cpp:90
+msgid "cpu rapl package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:97
+msgid "dram rapl package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:471
+msgid "Processor Idle State Report"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:535 ../src/cpu/cpu.cpp:753
+msgid "Package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:566 ../src/cpu/cpu.cpp:775
+#, fuzzy, c-format
+msgid "Core %d"
+msgstr "Núcleo %i"
+
+#: ../src/cpu/cpu.cpp:573
+#, fuzzy, c-format
+msgid "GPU %d"
+msgstr "GPU %i"
+
+#: ../src/cpu/cpu.cpp:594
+#, fuzzy
+msgid "CPU"
+msgstr "CPU %i"
+
+#: ../src/cpu/cpu.cpp:676
+msgid "Processor Frequency Report"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:796
+#, fuzzy, c-format
+msgid "CPU %d"
+msgstr "CPU %i"
+
+#: ../src/cpu/cpu.cpp:997
+#, c-format
+msgid "cpu_idle event returned no state?\n"
+msgstr "evento cpu_idle não retornou estado?\n"
+
+#: ../src/cpu/cpu.cpp:1012
+#, c-format
+msgid "power or cpu_frequency event returned no state?\n"
+msgstr ""
+
+#: ../src/cpu/cpu_linux.cpp:79
+msgid "C0 polling"
+msgstr "C0 ativo"
+
+#: ../src/cpu/cpu_linux.cpp:242
+#, c-format
+msgid " CPU(OS) %i"
+msgstr ""
+
+#: ../src/cpu/cpu_linux.cpp:341 ../src/cpu/intel_cpus.cpp:651
+#, c-format
+msgid " CPU %i"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(HW)"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(OS)"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:104 ../src/cpu/intel_cpus.cpp:412
+#, c-format
+msgid " Package"
+msgstr ""
+
+#: ../src/cpu/intel_cpus.cpp:129
+#, c-format
+msgid "read_msr cpu%d 0x%llx : "
+msgstr ""
+
+#: ../src/cpu/intel_cpus.cpp:574
+msgid "C0 active"
+msgstr "C0 ativo"
+
+#: ../src/cpu/intel_cpus.cpp:632
+#, c-format
+msgid "Average"
+msgstr ""
+
+#: ../src/cpu/intel_gpu.cpp:64
+#, fuzzy, c-format
+msgid " GPU "
+msgstr "GPU %i"
+
+#: ../src/devices/ahci.cpp:154
+#, c-format
+msgid "SATA link: %s"
+msgstr "Link SATA: %s"
+
+#: ../src/devices/ahci.cpp:156
+#, c-format
+msgid "SATA disk: %s"
+msgstr "Disco SATA: %s"
+
+#: ../src/devices/ahci.cpp:374
+msgid "AHCI ALPM Residency Statistics - Not supported on this macine"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:389
+msgid "Link"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:390
+#, fuzzy
+msgid "Active"
+msgstr "C0 ativo"
+
+#: ../src/devices/ahci.cpp:391
+msgid "Partial"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:392
+msgid "Slumber"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:393
+msgid "Devslp"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:399
+msgid "AHCI ALPM Residency Statistics"
+msgstr ""
+
+#: ../src/devices/alsa.cpp:77
+#, c-format
+msgid "Audio codec %s: %s (%s)"
+msgstr "Coded de áudio %s: %s (%s)"
+
+#: ../src/devices/alsa.cpp:79 ../src/devices/alsa.cpp:81
+#, c-format
+msgid "Audio codec %s: %s"
+msgstr "Codec de áudio %s: %s"
+
+#: ../src/devices/devfreq.cpp:261
+#, fuzzy
+msgid "Device Freq stats"
+msgstr "Dispositivos"
+
+#: ../src/devices/devfreq.cpp:279
+msgid " Devfreq is not enabled"
+msgstr ""
+
+#: ../src/devices/devfreq.cpp:284
+msgid " No devfreq devices available"
+msgstr ""
+
+#: ../src/devices/device.cpp:172 ../src/process/do_process.cpp:831
+#, c-format
+msgid "The battery reports a discharge rate of %sW\n"
+msgstr "A bateria relata uma taxa de descarga de %sW\n"
+
+#: ../src/devices/device.cpp:174 ../src/process/do_process.cpp:833
+#, c-format
+msgid "The power consumed was %sJ\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:180
+#, c-format
+msgid "System baseline power is estimated at %sW\n"
+msgstr "Consumo básico do sistema estimado em %sW\n"
+
+#: ../src/devices/device.cpp:187
+msgid "Power est. Usage Device name\n"
+msgstr "Consumo Uso Dispositivo\n"
+
+#: ../src/devices/device.cpp:189
+msgid " Usage Device name\n"
+msgstr " Uso Dispositivo\n"
+
+#: ../src/devices/device.cpp:256
+#, fuzzy
+msgid "The battery reports a discharge rate of: "
+msgstr "A bateria relata uma taxa de descarga de %sW\n"
+
+#: ../src/devices/device.cpp:261
+msgid "The power consumed was : "
+msgstr ""
+
+#: ../src/devices/device.cpp:268
+#, fuzzy
+msgid "The system baseline power is estimated at: "
+msgstr "Consumo básico do sistema estimado em %sW\n"
+
+#: ../src/devices/device.cpp:277 ../src/process/do_process.cpp:850
+#: ../src/process/do_process.cpp:852 ../src/process/do_process.cpp:926
+#: ../src/process/do_process.cpp:1077
+msgid "Usage"
+msgstr "Uso"
+
+#: ../src/devices/device.cpp:278
+#, fuzzy
+msgid "Device Name"
+msgstr "Dispositivos"
+
+#: ../src/devices/device.cpp:280 ../src/process/do_process.cpp:935
+#: ../src/process/do_process.cpp:1082
+msgid "PW Estimate"
+msgstr ""
+
+#. Report Output
+#: ../src/devices/device.cpp:317
+msgid "Device Power Report"
+msgstr ""
+
+#: ../src/devices/network.cpp:177
+#, c-format
+msgid "Network interface: %s (%s)"
+msgstr "Interface de rede: %s (%s)"
+
+#: ../src/devices/rfkill.cpp:65 ../src/devices/rfkill.cpp:69
+#, c-format
+msgid "Radio device: %s"
+msgstr "Dispositivo de rádio: %s"
+
+#: ../src/devices/runtime_pm.cpp:216
+#, c-format
+msgid "I2C %s (%s): %s"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216 ../src/tuning/tuningi2c.cpp:57
+#: ../src/tuning/tuningi2c.cpp:59
+msgid "Adapter"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216 ../src/devlist.cpp:331
+#: ../src/tuning/tuningi2c.cpp:57 ../src/tuning/tuningi2c.cpp:59
+#, fuzzy
+msgid "Device"
+msgstr "Dispositivos"
+
+#: ../src/devices/runtime_pm.cpp:241
+#, c-format
+msgid "PCI Device: %s"
+msgstr "Dispositivo PCI: %s"
+
+#: ../src/devices/usb.cpp:51 ../src/devices/usb.cpp:96
+#: ../src/devices/usb.cpp:98
+#, c-format
+msgid "USB device: %s"
+msgstr "Dispositivo USB: %s"
+
+#: ../src/devices/usb.cpp:94
+#, c-format
+msgid "USB device: %s (%s)"
+msgstr "Dispositivo USB: %s (%s)"
+
+#: ../src/devlist.cpp:330
+msgid "Process"
+msgstr ""
+
+#. Report Output
+#. No div attribute here inherits from device power report
+#: ../src/devlist.cpp:347
+msgid "Process Device Activity"
+msgstr ""
+
+#: ../src/display.cpp:70
+msgid "Overview"
+msgstr "Geral"
+
+#: ../src/display.cpp:71
+msgid "Idle stats"
+msgstr "Estados"
+
+#: ../src/display.cpp:72
+msgid "Frequency stats"
+msgstr "Frequências"
+
+#: ../src/display.cpp:73
+msgid "Device stats"
+msgstr "Dispositivos"
+
+#: ../src/display.cpp:131
+msgid "Exit"
+msgstr "Sair"
+
+#: ../src/display.cpp:132
+msgid "Navigate"
+msgstr ""
+
+#: ../src/lib.cpp:288
+#, c-format
+msgid "%7sW"
+msgstr "%7sW"
+
+#: ../src/lib.cpp:291
+#, c-format
+msgid " 0 mW"
+msgstr " 0 mW"
+
+#: ../src/lib.cpp:410
+msgid "PS/2 Touchpad / Keyboard / Mouse"
+msgstr "Touchpad PS/2 / Teclado / Mouse"
+
+#: ../src/lib.cpp:411
+msgid "SATA controller"
+msgstr "Controlador SATA"
+
+#: ../src/lib.cpp:412
+msgid "Intel built in USB hub"
+msgstr "Hub USB interno Intel"
+
+#: ../src/lib.cpp:467
+#, c-format
+msgid "glob returned GLOB_NOSPACE\n"
+msgstr ""
+
+#: ../src/lib.cpp:471
+#, c-format
+msgid "glob returned GLOB_ABORTED\n"
+msgstr ""
+
+#: ../src/lib.cpp:475
+#, c-format
+msgid "glob returned GLOB_NOMATCH\n"
+msgstr ""
+
+#: ../src/lib.cpp:513 ../src/lib.cpp:549
+#, c-format
+msgid ""
+"Model-specific registers (MSR)\t\t\t not found (try enabling "
+"CONFIG_X86_MSR).\n"
+msgstr ""
+
+#: ../src/main.cpp:103
+#, fuzzy, c-format
+msgid "PowerTOP version "
+msgstr "PowerTOP versão"
+
+#: ../src/main.cpp:109
+msgid "Set refresh time out"
+msgstr "Definir timeout de atualização"
+
+#: ../src/main.cpp:122
+msgid "Usage: powertop [OPTIONS]"
+msgstr "Uso: powertop [OPÇÕES]"
+
+#: ../src/main.cpp:123
+msgid "sets all tunable options to their GOOD setting"
+msgstr ""
+
+#: ../src/main.cpp:124
+msgid "runs powertop in calibration mode"
+msgstr "executa o powertop em modo de calibração"
+
+#: ../src/main.cpp:125 ../src/main.cpp:128
+msgid "[=filename]"
+msgstr ""
+
+#: ../src/main.cpp:125
+msgid "generate a csv report"
+msgstr "gera um relatório CSV"
+
+#: ../src/main.cpp:126
+msgid "run in \"debug\" mode"
+msgstr "executar em modo \"debug\""
+
+#: ../src/main.cpp:127
+msgid "[=devnode]"
+msgstr "[=dispositivo]"
+
+#: ../src/main.cpp:127
+msgid "uses an Extech Power Analyzer for measurements"
+msgstr "utiliza um analisador Extech para as medições"
+
+#: ../src/main.cpp:128
+msgid "generate a html report"
+msgstr "gera um relatório HTML"
+
+#: ../src/main.cpp:129
+msgid "[=iterations] number of times to run each test"
+msgstr "[=iterações] número de vezes para executar cada teste"
+
+#: ../src/main.cpp:130
+msgid "suppress stderr output"
+msgstr "suprime saída stderr"
+
+#: ../src/main.cpp:131 ../src/main.cpp:132
+msgid "[=seconds]"
+msgstr "[=segundos]"
+
+#: ../src/main.cpp:131
+msgid "interval for power consumption measurement"
+msgstr ""
+
+#: ../src/main.cpp:132
+msgid "generate a report for 'x' seconds"
+msgstr "gera um relatório para 'x' segundos"
+
+#: ../src/main.cpp:133
+msgid "[=workload]"
+msgstr "[=carga]"
+
+#: ../src/main.cpp:133
+msgid "file to execute for workload"
+msgstr "arquivo a ser executado para a carga de trabalho"
+
+#: ../src/main.cpp:134
+msgid "print version information"
+msgstr "exibe informação da versão"
+
+#: ../src/main.cpp:135
+msgid "print this help menu"
+msgstr "exibe este menu de ajuda"
+
+#: ../src/main.cpp:137
+#, fuzzy
+msgid "For more help please refer to the 'man 8 powertop'"
+msgstr "Para obter mais ajuda consulte o README, por favor"
+
+#: ../src/main.cpp:232
+#, c-format
+msgid "Unknown issue running workload!\n"
+msgstr ""
+
+#: ../src/main.cpp:289
+msgid "PowerTOP is out of memory. PowerTOP is Aborting"
+msgstr "PowerTOP está sem memória. PowerTOP está abortando"
+
+#. one to warm up everything
+#: ../src/main.cpp:297
+#, c-format
+msgid "Preparing to take measurements\n"
+msgstr "Preparando para medições\n"
+
+#: ../src/main.cpp:302
+#, c-format
+msgid "Taking %d measurement(s) for a duration of %d second(s) each.\n"
+msgstr "Obtendo %d medição(ões) com duração de %d segundo(s) cada.\n"
+
+#: ../src/main.cpp:304
+#, c-format
+msgid "Measuring workload %s.\n"
+msgstr "Medindo carga %s.\n"
+
+#: ../src/main.cpp:329
+#, c-format
+msgid "PowerTOP "
+msgstr "PowerTOP"
+
+#: ../src/main.cpp:330 ../src/main.cpp:380
+#, c-format
+msgid "exiting...\n"
+msgstr "saindo...\n"
+
+#: ../src/main.cpp:364
+#, c-format
+msgid "modprobe cpufreq_stats failed"
+msgstr ""
+
+#: ../src/main.cpp:367
+#, c-format
+msgid "modprobe msr failed"
+msgstr ""
+
+#: ../src/main.cpp:379 ../src/main.cpp:383
+#, c-format
+msgid "Failed to mount debugfs!\n"
+msgstr "Falha ao montar debugfs!\n"
+
+#: ../src/main.cpp:384
+#, c-format
+msgid "Should still be able to auto tune...\n"
+msgstr ""
+
+#: ../src/main.cpp:466
+#, c-format
+msgid "Invalid CSV filename\n"
+msgstr ""
+
+#: ../src/main.cpp:482
+#, c-format
+msgid "Invalid HTML filename\n"
+msgstr ""
+
+#: ../src/main.cpp:491
+#, c-format
+msgid "Quiet mode failed!\n"
+msgstr ""
+
+#: ../src/main.cpp:559
+msgid "Leaving PowerTOP"
+msgstr "Saindo do PowerTOP"
+
+#: ../src/parameters/persistent.cpp:46 ../src/parameters/persistent.cpp:155
+msgid "Cannot save to file"
+msgstr "Impossível salvar no arquivo"
+
+#: ../src/parameters/persistent.cpp:89 ../src/parameters/persistent.cpp:180
+msgid "Cannot load from file"
+msgstr "Impossível carregar o arquivo"
+
+#. '%i" is for count, do not translate
+#: ../src/parameters/persistent.cpp:138
+#, c-format
+msgid "Loaded %i prior measurements\n"
+msgstr "Carregadas %i medições anteriores\n"
+
+#: ../src/parameters/persistent.cpp:181
+msgid ""
+"File will be loaded after taking minimum number of measurement(s) with "
+"battery only \n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:115
+#, c-format
+msgid ""
+"Too many open files, please increase the limit of open file descriptors.\n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:117
+#, c-format
+msgid "PowerTOP %s needs the kernel to support the 'perf' subsystem\n"
+msgstr "PowerTOP %s necessita que o kernel suporte o subsistema 'perf'\n"
+
+#: ../src/perf/perf.cpp:118
+#, c-format
+msgid "as well as support for trace points in the kernel:\n"
+msgstr "assim como suporte para 'tracepoints' no kernel:\n"
+
+#: ../src/process/do_process.cpp:819
+#, c-format
+msgid ""
+"Estimated power: %5.1f Measured power: %5.1f Sum: %5.1f\n"
+"\n"
+msgstr ""
+"Energia estimada: %5.1f Energia medida: %5.1f Soma: %5.1f\n"
+"\n"
+
+#: ../src/process/do_process.cpp:838
+#, c-format
+msgid "The estimated remaining time is %i hours, %i minutes\n"
+msgstr "O tempo estimado restante é de %i horas, %i minutos\n"
+
+#: ../src/process/do_process.cpp:846
+msgid "Summary"
+msgstr "Sumário"
+
+#: ../src/process/do_process.cpp:846
+msgid "wakeups/second"
+msgstr "ativações/s"
+
+#: ../src/process/do_process.cpp:846
+msgid "GPU ops/seconds"
+msgstr "ops/s GPU"
+
+#: ../src/process/do_process.cpp:846
+msgid "VFS ops/sec and"
+msgstr "ops/s VFS e"
+
+#: ../src/process/do_process.cpp:846
+msgid "CPU use"
+msgstr "de uso de CPU"
+
+#: ../src/process/do_process.cpp:850
+msgid "Power est."
+msgstr "Est. energia"
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:1078
+msgid "Events/s"
+msgstr "Eventos/s"
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:931 ../src/process/do_process.cpp:1079
+msgid "Category"
+msgstr "Categoria"
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:932 ../src/process/do_process.cpp:1080
+#: ../src/tuning/tuning.cpp:242 ../src/tuning/tuning.cpp:270
+#: ../src/tuning/tuning.cpp:288 ../src/wakeup/waketab.cpp:155
+msgid "Description"
+msgstr "Descrição"
+
+#: ../src/process/do_process.cpp:927
+msgid "Wakeups/s"
+msgstr "Ativações/s"
+
+#: ../src/process/do_process.cpp:928
+msgid "GPU ops/s"
+msgstr "GPU ops/s"
+
+#: ../src/process/do_process.cpp:929
+msgid "Disk IO/s"
+msgstr "Disco ES/s"
+
+#: ../src/process/do_process.cpp:930
+msgid "GFX Wakeups/s"
+msgstr "Ativações/s GFX"
+
+#: ../src/process/do_process.cpp:1017
+msgid "Overview of Software Power Consumers"
+msgstr "Visão geral de software consumidores de energia"
+
+#: ../src/process/do_process.cpp:1057
+msgid "Target:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1058
+msgid "1 units/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1059
+msgid "System: "
+msgstr ""
+
+#: ../src/process/do_process.cpp:1061
+#, fuzzy
+msgid " wakeup/s"
+msgstr "Ativações/s"
+
+#: ../src/process/do_process.cpp:1062
+msgid "CPU: "
+msgstr ""
+
+#: ../src/process/do_process.cpp:1064
+#, fuzzy, c-format
+msgid "% usage"
+msgstr "Uso"
+
+#: ../src/process/do_process.cpp:1065
+msgid "GPU:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1067 ../src/process/do_process.cpp:1073
+#, fuzzy
+msgid " ops/s"
+msgstr "GPU ops/s"
+
+#: ../src/process/do_process.cpp:1068
+msgid "GFX:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1070
+#, fuzzy
+msgid " wakeups/s"
+msgstr "Ativações/s"
+
+#: ../src/process/do_process.cpp:1071
+msgid "VFS:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1139
+#, fuzzy
+msgid "Top 10 Power Consumers"
+msgstr "Visão geral de software consumidores de energia"
+
+#: ../src/report/report.cpp:122
+#, fuzzy
+msgid "PowerTOP Version"
+msgstr "PowerTOP versão"
+
+#: ../src/report/report.cpp:131
+#, fuzzy
+msgid "Kernel Version"
+msgstr "PowerTOP versão"
+
+#: ../src/report/report.cpp:135
+msgid "System Name"
+msgstr ""
+
+#: ../src/report/report.cpp:142
+msgid "CPU Information"
+msgstr ""
+
+#: ../src/report/report.cpp:154
+msgid "OS Information"
+msgstr ""
+
+#: ../src/report/report.cpp:161
+#, fuzzy
+msgid "System Information"
+msgstr "exibe informação da versão"
+
+#: ../src/report/report.cpp:195
+#, fuzzy, c-format
+msgid "Cannot open output file %s (%s)\n"
+msgstr "Impossível criar arquivo temporário\n"
+
+#: ../src/report/report.cpp:211
+#, c-format
+msgid "PowerTOP outputing using base filename %s\n"
+msgstr ""
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:49
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+msgid "Good"
+msgstr "Bom"
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:50
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+msgid "Bad"
+msgstr "Ruim"
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:51
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+#: ../src/wakeup/wakeup.cpp:50
+msgid "Unknown"
+msgstr "Desconhecido"
+
+#: ../src/tuning/bluetooth.cpp:48
+#, c-format
+msgid "Bluetooth device interface status"
+msgstr "Status da interface do dispositivo bluetooth"
+
+#: ../src/tuning/ethernet.cpp:54 ../src/wakeup/wakeup_ethernet.cpp:51
+#, c-format
+msgid "Wake-on-lan status for device %s"
+msgstr "Status do wake-on-lan para o dispositivo %s"
+
+#: ../src/tuning/runtime.cpp:48
+#, c-format
+msgid "Runtime PM for %s device %s"
+msgstr "Gerenciamento de energia em tempo de execução para %s dispositivo %s"
+
+#: ../src/tuning/runtime.cpp:50
+#, c-format
+msgid "%s device %s has no runtime power management"
+msgstr ""
+"%s dispositivo %s não possui gerenciamento de energia em tempo de execução"
+
+#: ../src/tuning/runtime.cpp:74
+#, c-format
+msgid "PCI Device %s has no runtime power management"
+msgstr ""
+"Dispositivo PCI %s não possui gerenciamento de energia em tempo de execução"
+
+#: ../src/tuning/runtime.cpp:76
+#, c-format
+msgid "Runtime PM for PCI Device %s"
+msgstr ""
+"Gerenciamento de energia em tempo de execução para o dispositivo PCI %s"
+
+#: ../src/tuning/tuning.cpp:62
+msgid "Enable Audio codec power management"
+msgstr "Habilitar gerenciamento de energia do codec de áudio"
+
+#: ../src/tuning/tuning.cpp:63
+msgid "NMI watchdog should be turned off"
+msgstr "O watchdog NMI deve ser desligado"
+
+#: ../src/tuning/tuning.cpp:64
+msgid "Power Aware CPU scheduler"
+msgstr "Escalonador de CPU voltado à economia de energia"
+
+#: ../src/tuning/tuning.cpp:65
+msgid "VM writeback timeout"
+msgstr "Timeout de escrita da VM"
+
+#: ../src/tuning/tuning.cpp:81
+msgid "Tunables"
+msgstr "Ajustes"
+
+#: ../src/tuning/tuning.cpp:81
+msgid " <ESC> Exit | <Enter> Toggle tunable | <r> Window refresh"
+msgstr "<ESC> Sair | <Enter> Alternar ajuste | <r> Atualizar janela"
+
+#: ../src/tuning/tuning.cpp:243 ../src/wakeup/waketab.cpp:156
+msgid "Script"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:257
+msgid "Software Settings in Need of Tuning"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:276
+msgid "Untunable Software Issues"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:300
+msgid "Optimal Tuned Software Settings"
+msgstr ""
+
+#: ../src/tuning/tuningi2c.cpp:57
+#, fuzzy, c-format
+msgid "Runtime PM for I2C %s %s (%s)"
+msgstr "Gerenciamento de energia em tempo de execução para %s dispositivo %s"
+
+#: ../src/tuning/tuningi2c.cpp:59
+#, fuzzy, c-format
+msgid "I2C %s %s has no runtime power management"
+msgstr ""
+"%s dispositivo %s não possui gerenciamento de energia em tempo de execução"
+
+#: ../src/tuning/tuningsysfs.cpp:123
+#, fuzzy, c-format
+msgid "Enable SATA link power management for %s"
+msgstr "Habilitar gerenciamento de energia da conexão SATA para %s"
+
+#: ../src/tuning/tuningusb.cpp:54
+#, c-format
+msgid "Autosuspend for unknown USB device %s (%s:%s)"
+msgstr "Suspensão automática para dispositivo USB desconhecido %s (%s:%s)"
+
+#: ../src/tuning/tuningusb.cpp:71 ../src/tuning/tuningusb.cpp:73
+#: ../src/tuning/tuningusb.cpp:75
+#, c-format
+msgid "Autosuspend for USB device %s [%s]"
+msgstr "Suspensão automática para dispositivo USB %s [%s]"
+
+#: ../src/tuning/wifi.cpp:48
+#, c-format
+msgid "Wireless Power Saving for interface %s"
+msgstr "Economia de energia para interface wireless %s"
+
+#: ../src/wakeup/waketab.cpp:42
+#, fuzzy
+msgid "WakeUp"
+msgstr "Ativações/s"
+
+#: ../src/wakeup/waketab.cpp:42
+#, fuzzy
+msgid " <ESC> Exit | <Enter> Toggle wakeup | <r> Window refresh"
+msgstr "<ESC> Sair | <Enter> Alternar ajuste | <r> Atualizar janela"
+
+#. Report Output
+#: ../src/wakeup/waketab.cpp:170
+#, fuzzy
+msgid "Wake status of the devices"
+msgstr "Status do wake-on-lan para o dispositivo %s"
+
+#: ../src/wakeup/wakeup.cpp:48 ../src/wakeup/wakeup_ethernet.cpp:47
+#: ../src/wakeup/wakeup_usb.cpp:47
+#, fuzzy
+msgid "Enable"
+msgstr "Ajustes"
+
+#: ../src/wakeup/wakeup.cpp:49 ../src/wakeup/wakeup_ethernet.cpp:47
+#: ../src/wakeup/wakeup_usb.cpp:47
+msgid "Disable"
+msgstr ""
+
+#: ../src/wakeup/wakeup_usb.cpp:51
+#, fuzzy, c-format
+msgid "Wake status for USB device %s"
+msgstr "Status do wake-on-lan para o dispositivo %s"
+
+#~ msgid "Actual"
+#~ msgstr "Atual"
+
+#~ msgid "Power Consumption Summary"
+#~ msgstr "Sumário de Consumo de Energia"
+
+#~ msgid "GPU ops/second"
+#~ msgstr "GPU ops/s"
+
+#~ msgid "VFS ops/sec"
+#~ msgstr "VFS ops/s"
+
+#~ msgid "GFX wakes/sec and"
+#~ msgstr "ativações/s GFX e"
+
+#~ msgid "Using 'ondemand' cpufreq governor"
+#~ msgstr "Usando o regulador de frequência 'ondemand'"
+
+#~ msgid "[=FILENAME]"
+#~ msgstr "[=ARQUIVO]"
diff --git a/po/ru_RU.po b/po/ru_RU.po
new file mode 100644
index 0000000..d19d464
--- /dev/null
+++ b/po/ru_RU.po
@@ -0,0 +1,996 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Intel Corporation
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# JIghtuse <jightuse@gmail.com>, 2013
+# JIghtuse <jightuse@gmail.com>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: PowerTOP\n"
+"Report-Msgid-Bugs-To: powertop@lists.01.org\n"
+"POT-Creation-Date: 2019-01-04 13:55-0800\n"
+"PO-Revision-Date: 2013-11-05 08:40+0000\n"
+"Last-Translator: Margie Foster <margie@linux.intel.com>\n"
+"Language-Team: Russian (Russia) (http://www.transifex.com/projects/p/"
+"PowerTOP/language/ru_RU/)\n"
+"Language: ru_RU\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#: ../src/calibrate/calibrate.cpp:238
+#, c-format
+msgid "Cannot create temp file\n"
+msgstr "Невозможно создать временный файл\\n"
+
+#: ../src/calibrate/calibrate.cpp:258
+#, c-format
+msgid "Calibrating: CPU usage on %i threads\n"
+msgstr "Калибровка: использование CPU на %i потоках\\n"
+
+#: ../src/calibrate/calibrate.cpp:273
+#, c-format
+msgid "Calibrating: CPU wakeup power consumption\n"
+msgstr "Калибровка: потребление энергии пробуждения CPU\\n"
+
+#: ../src/calibrate/calibrate.cpp:290
+#, c-format
+msgid "Calibrating USB devices\n"
+msgstr "Калибровка USB-устройств\\n"
+
+#: ../src/calibrate/calibrate.cpp:292 ../src/calibrate/calibrate.cpp:309
+#: ../src/calibrate/calibrate.cpp:317 ../src/calibrate/calibrate.cpp:334
+#, c-format
+msgid ".... device %s \n"
+msgstr ".... устройство %s\\n"
+
+#: ../src/calibrate/calibrate.cpp:307
+#, c-format
+msgid "Calibrating radio devices\n"
+msgstr "Калибровка радиоустройств\\n"
+
+#: ../src/calibrate/calibrate.cpp:331
+#, c-format
+msgid "Calibrating backlight\n"
+msgstr "Калибровка подсветки монитора\\n"
+
+#: ../src/calibrate/calibrate.cpp:355 ../src/calibrate/calibrate.cpp:365
+#, c-format
+msgid "Calibrating idle\n"
+msgstr "Калибровка простоя\\n"
+
+#: ../src/calibrate/calibrate.cpp:378
+#, c-format
+msgid "Calibrating: disk usage \n"
+msgstr "Калибровка: использование диска\\n"
+
+#: ../src/calibrate/calibrate.cpp:403
+msgid "Starting PowerTOP power estimate calibration \n"
+msgstr "Запущена калибровка оценочного потребления энергии PowerTOP\\n"
+
+#: ../src/calibrate/calibrate.cpp:426
+msgid "Finishing PowerTOP power estimate calibration \n"
+msgstr "Завершена калибровка оценочного потребления энергии PowerTOP\\n"
+
+#: ../src/calibrate/calibrate.cpp:430
+#, c-format
+msgid "Parameters after calibration:\n"
+msgstr "Параметры после калибровки:\\n"
+
+#: ../src/cpu/abstract_cpu.cpp:74
+msgid "Idle"
+msgstr ""
+
+#: ../src/cpu/abstract_cpu.cpp:76
+msgid "Turbo Mode"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:37
+#, fuzzy, c-format
+msgid " Core(HW)"
+msgstr "Ядро"
+
+#: ../src/cpu/cpu_core.cpp:37
+#, fuzzy, c-format
+msgid " Core(OS)"
+msgstr "Ядро"
+
+#: ../src/cpu/cpu_core.cpp:91 ../src/cpu/intel_cpus.cpp:324
+#, c-format
+msgid " Core"
+msgstr "Ядро"
+
+#: ../src/cpu/cpu.cpp:85
+#, c-format
+msgid "cpu package %i"
+msgstr "упаковка процессора %i"
+
+#: ../src/cpu/cpu.cpp:86
+msgid "cpu package"
+msgstr "упаковка процессора"
+
+#: ../src/cpu/cpu.cpp:89 ../src/cpu/cpu.cpp:96
+#, fuzzy, c-format
+msgid "package-%i"
+msgstr "Упаковка %i"
+
+#: ../src/cpu/cpu.cpp:90
+msgid "cpu rapl package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:97
+msgid "dram rapl package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:471
+msgid "Processor Idle State Report"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:535 ../src/cpu/cpu.cpp:753
+msgid "Package"
+msgstr "Упаковка"
+
+#: ../src/cpu/cpu.cpp:566 ../src/cpu/cpu.cpp:775
+#, fuzzy, c-format
+msgid "Core %d"
+msgstr "Ядро %i"
+
+#: ../src/cpu/cpu.cpp:573
+#, fuzzy, c-format
+msgid "GPU %d"
+msgstr "GPU %i"
+
+#: ../src/cpu/cpu.cpp:594
+#, fuzzy
+msgid "CPU"
+msgstr "CPU %i"
+
+#: ../src/cpu/cpu.cpp:676
+msgid "Processor Frequency Report"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:796
+#, fuzzy, c-format
+msgid "CPU %d"
+msgstr "CPU %i"
+
+#: ../src/cpu/cpu.cpp:997
+#, c-format
+msgid "cpu_idle event returned no state?\n"
+msgstr "событие cpu_idle не вернуло состояния?\\n"
+
+#: ../src/cpu/cpu.cpp:1012
+#, c-format
+msgid "power or cpu_frequency event returned no state?\n"
+msgstr "события power или cpu_frequency не вернули состояния?\\n"
+
+#: ../src/cpu/cpu_linux.cpp:79
+msgid "C0 polling"
+msgstr "опрос C0"
+
+#: ../src/cpu/cpu_linux.cpp:242
+#, fuzzy, c-format
+msgid " CPU(OS) %i"
+msgstr "CPU %i"
+
+#: ../src/cpu/cpu_linux.cpp:341 ../src/cpu/intel_cpus.cpp:651
+#, c-format
+msgid " CPU %i"
+msgstr "CPU %i"
+
+#: ../src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(HW)"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(OS)"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:104 ../src/cpu/intel_cpus.cpp:412
+#, c-format
+msgid " Package"
+msgstr "Упаковка"
+
+#: ../src/cpu/intel_cpus.cpp:129
+#, c-format
+msgid "read_msr cpu%d 0x%llx : "
+msgstr ""
+
+#: ../src/cpu/intel_cpus.cpp:574
+msgid "C0 active"
+msgstr "активно C0"
+
+#: ../src/cpu/intel_cpus.cpp:632
+#, c-format
+msgid "Average"
+msgstr ""
+
+#: ../src/cpu/intel_gpu.cpp:64
+#, fuzzy, c-format
+msgid " GPU "
+msgstr "GPU %i"
+
+#: ../src/devices/ahci.cpp:154
+#, c-format
+msgid "SATA link: %s"
+msgstr "Линк SATA: %s"
+
+#: ../src/devices/ahci.cpp:156
+#, c-format
+msgid "SATA disk: %s"
+msgstr "Диск SATA: %s"
+
+#: ../src/devices/ahci.cpp:374
+msgid "AHCI ALPM Residency Statistics - Not supported on this macine"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:389
+msgid "Link"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:390
+#, fuzzy
+msgid "Active"
+msgstr "активно C0"
+
+#: ../src/devices/ahci.cpp:391
+msgid "Partial"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:392
+msgid "Slumber"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:393
+msgid "Devslp"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:399
+msgid "AHCI ALPM Residency Statistics"
+msgstr ""
+
+#: ../src/devices/alsa.cpp:77
+#, c-format
+msgid "Audio codec %s: %s (%s)"
+msgstr "Аудиокодек %s: %s (%s)"
+
+#: ../src/devices/alsa.cpp:79 ../src/devices/alsa.cpp:81
+#, c-format
+msgid "Audio codec %s: %s"
+msgstr "Аудиокодек %s: %s"
+
+#: ../src/devices/devfreq.cpp:261
+#, fuzzy
+msgid "Device Freq stats"
+msgstr "Статистика устройств"
+
+#: ../src/devices/devfreq.cpp:279
+msgid " Devfreq is not enabled"
+msgstr ""
+
+#: ../src/devices/devfreq.cpp:284
+msgid " No devfreq devices available"
+msgstr ""
+
+#: ../src/devices/device.cpp:172 ../src/process/do_process.cpp:831
+#, c-format
+msgid "The battery reports a discharge rate of %sW\n"
+msgstr "Аккумулятор сообщает о скорости разряда в %sВт\\n"
+
+#: ../src/devices/device.cpp:174 ../src/process/do_process.cpp:833
+#, c-format
+msgid "The power consumed was %sJ\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:180
+#, c-format
+msgid "System baseline power is estimated at %sW\n"
+msgstr "Базовая мощность системы оценена в %sВ\\n"
+
+#: ../src/devices/device.cpp:187
+msgid "Power est. Usage Device name\n"
+msgstr "Потребление\\t Использование\\t Название устройства\\n"
+
+#: ../src/devices/device.cpp:189
+msgid " Usage Device name\n"
+msgstr "Использование\\t Название устройства\\n"
+
+#: ../src/devices/device.cpp:256
+#, fuzzy
+msgid "The battery reports a discharge rate of: "
+msgstr "Аккумулятор сообщает о скорости разряда в %sВт\\n"
+
+#: ../src/devices/device.cpp:261
+msgid "The power consumed was : "
+msgstr ""
+
+#: ../src/devices/device.cpp:268
+#, fuzzy
+msgid "The system baseline power is estimated at: "
+msgstr "Базовая мощность системы оценена в %sВ\\n"
+
+#: ../src/devices/device.cpp:277 ../src/process/do_process.cpp:850
+#: ../src/process/do_process.cpp:852 ../src/process/do_process.cpp:926
+#: ../src/process/do_process.cpp:1077
+msgid "Usage"
+msgstr "Использование"
+
+#: ../src/devices/device.cpp:278
+#, fuzzy
+msgid "Device Name"
+msgstr "Статистика устройств"
+
+#: ../src/devices/device.cpp:280 ../src/process/do_process.cpp:935
+#: ../src/process/do_process.cpp:1082
+msgid "PW Estimate"
+msgstr ""
+
+#. Report Output
+#: ../src/devices/device.cpp:317
+msgid "Device Power Report"
+msgstr ""
+
+#: ../src/devices/network.cpp:177
+#, c-format
+msgid "Network interface: %s (%s)"
+msgstr "Сетевой интерфейс: %s (%s)"
+
+#: ../src/devices/rfkill.cpp:65 ../src/devices/rfkill.cpp:69
+#, c-format
+msgid "Radio device: %s"
+msgstr "Радиоустройство: %s"
+
+#: ../src/devices/runtime_pm.cpp:216
+#, c-format
+msgid "I2C %s (%s): %s"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216 ../src/tuning/tuningi2c.cpp:57
+#: ../src/tuning/tuningi2c.cpp:59
+msgid "Adapter"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216 ../src/devlist.cpp:331
+#: ../src/tuning/tuningi2c.cpp:57 ../src/tuning/tuningi2c.cpp:59
+#, fuzzy
+msgid "Device"
+msgstr "Статистика устройств"
+
+#: ../src/devices/runtime_pm.cpp:241
+#, c-format
+msgid "PCI Device: %s"
+msgstr "PCI-устройство: %s"
+
+#: ../src/devices/usb.cpp:51 ../src/devices/usb.cpp:96
+#: ../src/devices/usb.cpp:98
+#, c-format
+msgid "USB device: %s"
+msgstr "USB-устройство: %s"
+
+#: ../src/devices/usb.cpp:94
+#, c-format
+msgid "USB device: %s (%s)"
+msgstr "USB-устройство: %s (%s)"
+
+#: ../src/devlist.cpp:330
+msgid "Process"
+msgstr ""
+
+#. Report Output
+#. No div attribute here inherits from device power report
+#: ../src/devlist.cpp:347
+msgid "Process Device Activity"
+msgstr ""
+
+#: ../src/display.cpp:70
+msgid "Overview"
+msgstr "Обзор"
+
+#: ../src/display.cpp:71
+msgid "Idle stats"
+msgstr "Статистика простоя"
+
+#: ../src/display.cpp:72
+msgid "Frequency stats"
+msgstr "Статистика частоты"
+
+#: ../src/display.cpp:73
+msgid "Device stats"
+msgstr "Статистика устройств"
+
+#: ../src/display.cpp:131
+msgid "Exit"
+msgstr "Выход"
+
+#: ../src/display.cpp:132
+msgid "Navigate"
+msgstr ""
+
+#: ../src/lib.cpp:288
+#, c-format
+msgid "%7sW"
+msgstr "%7sВ"
+
+#: ../src/lib.cpp:291
+#, c-format
+msgid " 0 mW"
+msgstr "0 мВ"
+
+#: ../src/lib.cpp:410
+msgid "PS/2 Touchpad / Keyboard / Mouse"
+msgstr "PS/2 Тачпад/Клавиатура/Мышь"
+
+#: ../src/lib.cpp:411
+msgid "SATA controller"
+msgstr "Контроллер SATA"
+
+#: ../src/lib.cpp:412
+msgid "Intel built in USB hub"
+msgstr "Встроенный USB-хаб Intel"
+
+#: ../src/lib.cpp:467
+#, c-format
+msgid "glob returned GLOB_NOSPACE\n"
+msgstr ""
+
+#: ../src/lib.cpp:471
+#, c-format
+msgid "glob returned GLOB_ABORTED\n"
+msgstr ""
+
+#: ../src/lib.cpp:475
+#, c-format
+msgid "glob returned GLOB_NOMATCH\n"
+msgstr ""
+
+#: ../src/lib.cpp:513 ../src/lib.cpp:549
+#, c-format
+msgid ""
+"Model-specific registers (MSR)\t\t\t not found (try enabling "
+"CONFIG_X86_MSR).\n"
+msgstr ""
+
+#: ../src/main.cpp:103
+#, fuzzy, c-format
+msgid "PowerTOP version "
+msgstr "Версия PowerTOP"
+
+#: ../src/main.cpp:109
+msgid "Set refresh time out"
+msgstr "Задать время до обновления"
+
+#: ../src/main.cpp:122
+msgid "Usage: powertop [OPTIONS]"
+msgstr "Использование: powertop [OPTIONS]"
+
+#: ../src/main.cpp:123
+msgid "sets all tunable options to their GOOD setting"
+msgstr ""
+
+#: ../src/main.cpp:124
+msgid "runs powertop in calibration mode"
+msgstr "запуск powertop в режиме калибровки"
+
+#: ../src/main.cpp:125 ../src/main.cpp:128
+msgid "[=filename]"
+msgstr ""
+
+#: ../src/main.cpp:125
+msgid "generate a csv report"
+msgstr "генерация csv-отчёта"
+
+#: ../src/main.cpp:126
+msgid "run in \"debug\" mode"
+msgstr "запуск в режиме \"debug\""
+
+#: ../src/main.cpp:127
+msgid "[=devnode]"
+msgstr "[=devnode]"
+
+#: ../src/main.cpp:127
+msgid "uses an Extech Power Analyzer for measurements"
+msgstr "использует Extech Power Analyzer для измерений"
+
+#: ../src/main.cpp:128
+msgid "generate a html report"
+msgstr "генерация html-отчёта"
+
+#: ../src/main.cpp:129
+msgid "[=iterations] number of times to run each test"
+msgstr "[=iterations] число итераций запуска каждого теста"
+
+#: ../src/main.cpp:130
+msgid "suppress stderr output"
+msgstr "подавить вывод в stderr"
+
+#: ../src/main.cpp:131 ../src/main.cpp:132
+msgid "[=seconds]"
+msgstr "[=seconds]"
+
+#: ../src/main.cpp:131
+msgid "interval for power consumption measurement"
+msgstr ""
+
+#: ../src/main.cpp:132
+msgid "generate a report for 'x' seconds"
+msgstr "генерация отчёта за 'x' секунд"
+
+#: ../src/main.cpp:133
+msgid "[=workload]"
+msgstr "[=workload]"
+
+#: ../src/main.cpp:133
+msgid "file to execute for workload"
+msgstr "файл для запуска нагрузки"
+
+#: ../src/main.cpp:134
+msgid "print version information"
+msgstr "печать информации о версии"
+
+#: ../src/main.cpp:135
+msgid "print this help menu"
+msgstr "вывести данное меню помощи"
+
+#: ../src/main.cpp:137
+#, fuzzy
+msgid "For more help please refer to the 'man 8 powertop'"
+msgstr "Для более подробной информации обратитесь к файлу README"
+
+#: ../src/main.cpp:232
+#, c-format
+msgid "Unknown issue running workload!\n"
+msgstr "В процессе работы возникла неизвестная ошибка!\\n"
+
+#: ../src/main.cpp:289
+msgid "PowerTOP is out of memory. PowerTOP is Aborting"
+msgstr "Недостаточно памяти для PowerTOP. Прерывание PowerTOP"
+
+#. one to warm up everything
+#: ../src/main.cpp:297
+#, c-format
+msgid "Preparing to take measurements\n"
+msgstr "Подготовка к взятию измерений\\n"
+
+#: ../src/main.cpp:302
+#, c-format
+msgid "Taking %d measurement(s) for a duration of %d second(s) each.\n"
+msgstr "Взятие %d измерение(-ий) длительностью %d секунд(а) каждое.\\n"
+
+#: ../src/main.cpp:304
+#, c-format
+msgid "Measuring workload %s.\n"
+msgstr "Замер нагрузки %s.\\n"
+
+#: ../src/main.cpp:329
+#, c-format
+msgid "PowerTOP "
+msgstr "PowerTOP"
+
+#: ../src/main.cpp:330 ../src/main.cpp:380
+#, c-format
+msgid "exiting...\n"
+msgstr "выход...\\n"
+
+#: ../src/main.cpp:364
+#, c-format
+msgid "modprobe cpufreq_stats failed"
+msgstr ""
+
+#: ../src/main.cpp:367
+#, c-format
+msgid "modprobe msr failed"
+msgstr ""
+
+#: ../src/main.cpp:379 ../src/main.cpp:383
+#, c-format
+msgid "Failed to mount debugfs!\n"
+msgstr "Не удалось подмонтировать debugfs!\\n"
+
+#: ../src/main.cpp:384
+#, c-format
+msgid "Should still be able to auto tune...\n"
+msgstr ""
+
+#: ../src/main.cpp:466
+#, c-format
+msgid "Invalid CSV filename\n"
+msgstr ""
+
+#: ../src/main.cpp:482
+#, c-format
+msgid "Invalid HTML filename\n"
+msgstr ""
+
+#: ../src/main.cpp:491
+#, fuzzy, c-format
+msgid "Quiet mode failed!\n"
+msgstr "Ошибка режима \"quite\"!\\n"
+
+#: ../src/main.cpp:559
+msgid "Leaving PowerTOP"
+msgstr "Завершение PowerTOP"
+
+#: ../src/parameters/persistent.cpp:46 ../src/parameters/persistent.cpp:155
+msgid "Cannot save to file"
+msgstr "Невозможно сохранить в файл"
+
+#: ../src/parameters/persistent.cpp:89 ../src/parameters/persistent.cpp:180
+msgid "Cannot load from file"
+msgstr "Невозможно загрузить из файла"
+
+#. '%i" is for count, do not translate
+#: ../src/parameters/persistent.cpp:138
+#, c-format
+msgid "Loaded %i prior measurements\n"
+msgstr "Загрузка %i предварительных замеров\\n"
+
+#: ../src/parameters/persistent.cpp:181
+msgid ""
+"File will be loaded after taking minimum number of measurement(s) with "
+"battery only \n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:115
+#, c-format
+msgid ""
+"Too many open files, please increase the limit of open file descriptors.\n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:117
+#, c-format
+msgid "PowerTOP %s needs the kernel to support the 'perf' subsystem\n"
+msgstr "PowerTOP %s необходима поддержка подсистемы 'perf' ядра\\n"
+
+#: ../src/perf/perf.cpp:118
+#, c-format
+msgid "as well as support for trace points in the kernel:\n"
+msgstr "а также поддержка trace points в ядре:\\n"
+
+#: ../src/process/do_process.cpp:819
+#, c-format
+msgid ""
+"Estimated power: %5.1f Measured power: %5.1f Sum: %5.1f\n"
+"\n"
+msgstr ""
+"Оценочное потребление: %5.1f\\t Измеренное потребление: %5.1f\\t Суммарно: "
+"%5.1f\\n \\n"
+
+#: ../src/process/do_process.cpp:838
+#, c-format
+msgid "The estimated remaining time is %i hours, %i minutes\n"
+msgstr "Оценочное время работы %i часов, %i минут\\n"
+
+#: ../src/process/do_process.cpp:846
+msgid "Summary"
+msgstr "Суммарно"
+
+#: ../src/process/do_process.cpp:846
+msgid "wakeups/second"
+msgstr "пробуждений/секунду"
+
+#: ../src/process/do_process.cpp:846
+msgid "GPU ops/seconds"
+msgstr "GPU операций/секунду"
+
+#: ../src/process/do_process.cpp:846
+msgid "VFS ops/sec and"
+msgstr "VFS операций/с и"
+
+#: ../src/process/do_process.cpp:846
+msgid "CPU use"
+msgstr "Использование CPU"
+
+#: ../src/process/do_process.cpp:850
+msgid "Power est."
+msgstr "Оценка потребления"
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:1078
+msgid "Events/s"
+msgstr "Событий/с"
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:931 ../src/process/do_process.cpp:1079
+msgid "Category"
+msgstr "Категория"
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:932 ../src/process/do_process.cpp:1080
+#: ../src/tuning/tuning.cpp:242 ../src/tuning/tuning.cpp:270
+#: ../src/tuning/tuning.cpp:288 ../src/wakeup/waketab.cpp:155
+msgid "Description"
+msgstr "Описание"
+
+#: ../src/process/do_process.cpp:927
+msgid "Wakeups/s"
+msgstr "Пробуждений/с"
+
+#: ../src/process/do_process.cpp:928
+msgid "GPU ops/s"
+msgstr "GPU операций/с"
+
+#: ../src/process/do_process.cpp:929
+msgid "Disk IO/s"
+msgstr "Диск ввод-вывод/с"
+
+#: ../src/process/do_process.cpp:930
+msgid "GFX Wakeups/s"
+msgstr "GFX пробуждений/с"
+
+#: ../src/process/do_process.cpp:1017
+msgid "Overview of Software Power Consumers"
+msgstr "Обзор программных потребителей энергии"
+
+#: ../src/process/do_process.cpp:1057
+msgid "Target:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1058
+msgid "1 units/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1059
+msgid "System: "
+msgstr ""
+
+#: ../src/process/do_process.cpp:1061
+#, fuzzy
+msgid " wakeup/s"
+msgstr "Пробуждений/с"
+
+#: ../src/process/do_process.cpp:1062
+msgid "CPU: "
+msgstr ""
+
+#: ../src/process/do_process.cpp:1064
+#, fuzzy, c-format
+msgid "% usage"
+msgstr "Использование"
+
+#: ../src/process/do_process.cpp:1065
+msgid "GPU:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1067 ../src/process/do_process.cpp:1073
+#, fuzzy
+msgid " ops/s"
+msgstr "GPU операций/с"
+
+#: ../src/process/do_process.cpp:1068
+msgid "GFX:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1070
+#, fuzzy
+msgid " wakeups/s"
+msgstr "Пробуждений/с"
+
+#: ../src/process/do_process.cpp:1071
+msgid "VFS:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1139
+#, fuzzy
+msgid "Top 10 Power Consumers"
+msgstr "Обзор программных потребителей энергии"
+
+#: ../src/report/report.cpp:122
+#, fuzzy
+msgid "PowerTOP Version"
+msgstr "Версия PowerTOP"
+
+#: ../src/report/report.cpp:131
+#, fuzzy
+msgid "Kernel Version"
+msgstr "Версия PowerTOP"
+
+#: ../src/report/report.cpp:135
+msgid "System Name"
+msgstr ""
+
+#: ../src/report/report.cpp:142
+msgid "CPU Information"
+msgstr ""
+
+#: ../src/report/report.cpp:154
+msgid "OS Information"
+msgstr ""
+
+#: ../src/report/report.cpp:161
+#, fuzzy
+msgid "System Information"
+msgstr "печать информации о версии"
+
+#: ../src/report/report.cpp:195
+#, fuzzy, c-format
+msgid "Cannot open output file %s (%s)\n"
+msgstr "Невозможно создать временный файл\\n"
+
+#: ../src/report/report.cpp:211
+#, c-format
+msgid "PowerTOP outputing using base filename %s\n"
+msgstr ""
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:49
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+msgid "Good"
+msgstr "Хорошо"
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:50
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+msgid "Bad"
+msgstr "Плохо"
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:51
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+#: ../src/wakeup/wakeup.cpp:50
+msgid "Unknown"
+msgstr "Неизвестно"
+
+#: ../src/tuning/bluetooth.cpp:48
+#, c-format
+msgid "Bluetooth device interface status"
+msgstr "Статус интерфейса bluetooth-устройства"
+
+#: ../src/tuning/ethernet.cpp:54 ../src/wakeup/wakeup_ethernet.cpp:51
+#, c-format
+msgid "Wake-on-lan status for device %s"
+msgstr "Статус wake-on-lan для устройства %s"
+
+#: ../src/tuning/runtime.cpp:48
+#, c-format
+msgid "Runtime PM for %s device %s"
+msgstr "УП времени выполнения для %s устройства %s"
+
+#: ../src/tuning/runtime.cpp:50
+#, c-format
+msgid "%s device %s has no runtime power management"
+msgstr "%s устройство %s не имеет управления питанием времени выполнения"
+
+#: ../src/tuning/runtime.cpp:74
+#, c-format
+msgid "PCI Device %s has no runtime power management"
+msgstr "PCI-устройство %s не имеет управления питанием времени выполнения"
+
+#: ../src/tuning/runtime.cpp:76
+#, c-format
+msgid "Runtime PM for PCI Device %s"
+msgstr "УП времени выполнения для PCI-устройства %s"
+
+#: ../src/tuning/tuning.cpp:62
+msgid "Enable Audio codec power management"
+msgstr "Активировать управление питанием аудиокодека"
+
+#: ../src/tuning/tuning.cpp:63
+msgid "NMI watchdog should be turned off"
+msgstr "NMI watchdog должен быть отключен"
+
+#: ../src/tuning/tuning.cpp:64
+msgid "Power Aware CPU scheduler"
+msgstr "Энергосберегающий планировщик CPU"
+
+#: ../src/tuning/tuning.cpp:65
+msgid "VM writeback timeout"
+msgstr "Таймаут обратной записи VM"
+
+#: ../src/tuning/tuning.cpp:81
+msgid "Tunables"
+msgstr "Переключатели"
+
+#: ../src/tuning/tuning.cpp:81
+msgid " <ESC> Exit | <Enter> Toggle tunable | <r> Window refresh"
+msgstr "<ESC> Выход| <Enter> Переключить| <r> Обновить окно"
+
+#: ../src/tuning/tuning.cpp:243 ../src/wakeup/waketab.cpp:156
+msgid "Script"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:257
+msgid "Software Settings in Need of Tuning"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:276
+msgid "Untunable Software Issues"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:300
+msgid "Optimal Tuned Software Settings"
+msgstr ""
+
+#: ../src/tuning/tuningi2c.cpp:57
+#, fuzzy, c-format
+msgid "Runtime PM for I2C %s %s (%s)"
+msgstr "УП времени выполнения для %s устройства %s"
+
+#: ../src/tuning/tuningi2c.cpp:59
+#, fuzzy, c-format
+msgid "I2C %s %s has no runtime power management"
+msgstr "%s устройство %s не имеет управления питанием времени выполнения"
+
+#: ../src/tuning/tuningsysfs.cpp:123
+#, fuzzy, c-format
+msgid "Enable SATA link power management for %s"
+msgstr "Активировать управление питанием линка SATA для %s"
+
+#: ../src/tuning/tuningusb.cpp:54
+#, c-format
+msgid "Autosuspend for unknown USB device %s (%s:%s)"
+msgstr "Autosuspend для неизвестного USB-устройства %s (%s:%s)"
+
+#: ../src/tuning/tuningusb.cpp:71 ../src/tuning/tuningusb.cpp:73
+#: ../src/tuning/tuningusb.cpp:75
+#, c-format
+msgid "Autosuspend for USB device %s [%s]"
+msgstr "Autosuspend для USB-устройства %s [%s]"
+
+#: ../src/tuning/wifi.cpp:48
+#, c-format
+msgid "Wireless Power Saving for interface %s"
+msgstr "Энергосбережение для беспроводного интерфейса %s"
+
+#: ../src/wakeup/waketab.cpp:42
+#, fuzzy
+msgid "WakeUp"
+msgstr "Пробуждений/с"
+
+#: ../src/wakeup/waketab.cpp:42
+#, fuzzy
+msgid " <ESC> Exit | <Enter> Toggle wakeup | <r> Window refresh"
+msgstr "<ESC> Выход| <Enter> Переключить| <r> Обновить окно"
+
+#. Report Output
+#: ../src/wakeup/waketab.cpp:170
+#, fuzzy
+msgid "Wake status of the devices"
+msgstr "Статус wake-on-lan для устройства %s"
+
+#: ../src/wakeup/wakeup.cpp:48 ../src/wakeup/wakeup_ethernet.cpp:47
+#: ../src/wakeup/wakeup_usb.cpp:47
+#, fuzzy
+msgid "Enable"
+msgstr "Переключатели"
+
+#: ../src/wakeup/wakeup.cpp:49 ../src/wakeup/wakeup_ethernet.cpp:47
+#: ../src/wakeup/wakeup_usb.cpp:47
+msgid "Disable"
+msgstr ""
+
+#: ../src/wakeup/wakeup_usb.cpp:51
+#, fuzzy, c-format
+msgid "Wake status for USB device %s"
+msgstr "Статус wake-on-lan для устройства %s"
+
+#~ msgid "Actual"
+#~ msgstr "Действительная"
+
+#~ msgid "Power Consumption Summary"
+#~ msgstr "Суммарное потребление энергии"
+
+#~ msgid "GPU ops/second"
+#~ msgstr "GPU операций/секунду"
+
+#~ msgid "VFS ops/sec"
+#~ msgstr "VFS операций/с"
+
+#~ msgid "GFX wakes/sec and"
+#~ msgstr "GFX пробуждений/секунду и"
+
+#~ msgid "Using 'ondemand' cpufreq governor"
+#~ msgstr "Использование регулятора cpufreq 'ondemand'"
+
+#~ msgid "[=FILENAME]"
+#~ msgstr "[=FILENAME]"
diff --git a/po/tr_TR.po b/po/tr_TR.po
new file mode 100644
index 0000000..e3c05b5
--- /dev/null
+++ b/po/tr_TR.po
@@ -0,0 +1,961 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Intel Corporation
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Caner BAŞARAN <basaran.caner@gmail.com>, 2012-2013
+msgid ""
+msgstr ""
+"Project-Id-Version: PowerTOP\n"
+"Report-Msgid-Bugs-To: powertop@lists.01.org\n"
+"POT-Creation-Date: 2019-01-04 13:55-0800\n"
+"PO-Revision-Date: 2013-11-05 08:40+0000\n"
+"Last-Translator: Margie Foster <margie@linux.intel.com>\n"
+"Language-Team: Turkish (Turkey) (http://www.transifex.com/projects/p/"
+"PowerTOP/language/tr_TR/)\n"
+"Language: tr_TR\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: ../src/calibrate/calibrate.cpp:238
+#, c-format
+msgid "Cannot create temp file\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:258
+#, c-format
+msgid "Calibrating: CPU usage on %i threads\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:273
+#, c-format
+msgid "Calibrating: CPU wakeup power consumption\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:290
+#, c-format
+msgid "Calibrating USB devices\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:292 ../src/calibrate/calibrate.cpp:309
+#: ../src/calibrate/calibrate.cpp:317 ../src/calibrate/calibrate.cpp:334
+#, c-format
+msgid ".... device %s \n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:307
+#, c-format
+msgid "Calibrating radio devices\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:331
+#, c-format
+msgid "Calibrating backlight\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:355 ../src/calibrate/calibrate.cpp:365
+#, c-format
+msgid "Calibrating idle\n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:378
+#, c-format
+msgid "Calibrating: disk usage \n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:403
+msgid "Starting PowerTOP power estimate calibration \n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:426
+msgid "Finishing PowerTOP power estimate calibration \n"
+msgstr ""
+
+#: ../src/calibrate/calibrate.cpp:430
+#, c-format
+msgid "Parameters after calibration:\n"
+msgstr ""
+
+#: ../src/cpu/abstract_cpu.cpp:74
+msgid "Idle"
+msgstr ""
+
+#: ../src/cpu/abstract_cpu.cpp:76
+msgid "Turbo Mode"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(HW)"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(OS)"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:91 ../src/cpu/intel_cpus.cpp:324
+#, c-format
+msgid " Core"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:85
+#, c-format
+msgid "cpu package %i"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:86
+msgid "cpu package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:89 ../src/cpu/cpu.cpp:96
+#, c-format
+msgid "package-%i"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:90
+msgid "cpu rapl package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:97
+msgid "dram rapl package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:471
+msgid "Processor Idle State Report"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:535 ../src/cpu/cpu.cpp:753
+msgid "Package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:566 ../src/cpu/cpu.cpp:775
+#, c-format
+msgid "Core %d"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:573
+#, c-format
+msgid "GPU %d"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:594
+#, fuzzy
+msgid "CPU"
+msgstr "CPU kullanımı"
+
+#: ../src/cpu/cpu.cpp:676
+msgid "Processor Frequency Report"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:796
+#, fuzzy, c-format
+msgid "CPU %d"
+msgstr "CPU kullanımı"
+
+#: ../src/cpu/cpu.cpp:997
+#, c-format
+msgid "cpu_idle event returned no state?\n"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:1012
+#, c-format
+msgid "power or cpu_frequency event returned no state?\n"
+msgstr ""
+
+#: ../src/cpu/cpu_linux.cpp:79
+msgid "C0 polling"
+msgstr ""
+
+#: ../src/cpu/cpu_linux.cpp:242
+#, c-format
+msgid " CPU(OS) %i"
+msgstr ""
+
+#: ../src/cpu/cpu_linux.cpp:341 ../src/cpu/intel_cpus.cpp:651
+#, c-format
+msgid " CPU %i"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(HW)"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(OS)"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:104 ../src/cpu/intel_cpus.cpp:412
+#, c-format
+msgid " Package"
+msgstr ""
+
+#: ../src/cpu/intel_cpus.cpp:129
+#, c-format
+msgid "read_msr cpu%d 0x%llx : "
+msgstr ""
+
+#: ../src/cpu/intel_cpus.cpp:574
+msgid "C0 active"
+msgstr ""
+
+#: ../src/cpu/intel_cpus.cpp:632
+#, c-format
+msgid "Average"
+msgstr ""
+
+#: ../src/cpu/intel_gpu.cpp:64
+#, c-format
+msgid " GPU "
+msgstr ""
+
+#: ../src/devices/ahci.cpp:154
+#, c-format
+msgid "SATA link: %s"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:156
+#, c-format
+msgid "SATA disk: %s"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:374
+msgid "AHCI ALPM Residency Statistics - Not supported on this macine"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:389
+msgid "Link"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:390
+msgid "Active"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:391
+msgid "Partial"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:392
+msgid "Slumber"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:393
+msgid "Devslp"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:399
+msgid "AHCI ALPM Residency Statistics"
+msgstr ""
+
+#: ../src/devices/alsa.cpp:77
+#, c-format
+msgid "Audio codec %s: %s (%s)"
+msgstr "Ses kodlayıcı %s: %s (%s)"
+
+#: ../src/devices/alsa.cpp:79 ../src/devices/alsa.cpp:81
+#, c-format
+msgid "Audio codec %s: %s"
+msgstr "Ses kodlayıcı %s: %s"
+
+#: ../src/devices/devfreq.cpp:261
+#, fuzzy
+msgid "Device Freq stats"
+msgstr "Aygıt İst"
+
+#: ../src/devices/devfreq.cpp:279
+msgid " Devfreq is not enabled"
+msgstr ""
+
+#: ../src/devices/devfreq.cpp:284
+msgid " No devfreq devices available"
+msgstr ""
+
+#: ../src/devices/device.cpp:172 ../src/process/do_process.cpp:831
+#, c-format
+msgid "The battery reports a discharge rate of %sW\n"
+msgstr "Pil saatte %sW boşalıyor \n"
+
+#: ../src/devices/device.cpp:174 ../src/process/do_process.cpp:833
+#, c-format
+msgid "The power consumed was %sJ\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:180
+#, c-format
+msgid "System baseline power is estimated at %sW\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:187
+msgid "Power est. Usage Device name\n"
+msgstr "Tahmini güç Kullanım Aygıt adı\n"
+
+#: ../src/devices/device.cpp:189
+msgid " Usage Device name\n"
+msgstr " Kullanım Aygıt adı\n"
+
+#: ../src/devices/device.cpp:256
+#, fuzzy
+msgid "The battery reports a discharge rate of: "
+msgstr "Pil saatte %sW boşalıyor \n"
+
+#: ../src/devices/device.cpp:261
+msgid "The power consumed was : "
+msgstr ""
+
+#: ../src/devices/device.cpp:268
+msgid "The system baseline power is estimated at: "
+msgstr ""
+
+#: ../src/devices/device.cpp:277 ../src/process/do_process.cpp:850
+#: ../src/process/do_process.cpp:852 ../src/process/do_process.cpp:926
+#: ../src/process/do_process.cpp:1077
+msgid "Usage"
+msgstr "Kullanım"
+
+#: ../src/devices/device.cpp:278
+#, fuzzy
+msgid "Device Name"
+msgstr "Aygıt İst"
+
+#: ../src/devices/device.cpp:280 ../src/process/do_process.cpp:935
+#: ../src/process/do_process.cpp:1082
+msgid "PW Estimate"
+msgstr ""
+
+#. Report Output
+#: ../src/devices/device.cpp:317
+msgid "Device Power Report"
+msgstr ""
+
+#: ../src/devices/network.cpp:177
+#, c-format
+msgid "Network interface: %s (%s)"
+msgstr ""
+
+#: ../src/devices/rfkill.cpp:65 ../src/devices/rfkill.cpp:69
+#, c-format
+msgid "Radio device: %s"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216
+#, c-format
+msgid "I2C %s (%s): %s"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216 ../src/tuning/tuningi2c.cpp:57
+#: ../src/tuning/tuningi2c.cpp:59
+msgid "Adapter"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216 ../src/devlist.cpp:331
+#: ../src/tuning/tuningi2c.cpp:57 ../src/tuning/tuningi2c.cpp:59
+#, fuzzy
+msgid "Device"
+msgstr "Aygıt İst"
+
+#: ../src/devices/runtime_pm.cpp:241
+#, c-format
+msgid "PCI Device: %s"
+msgstr "PCI Aygıt: %s"
+
+#: ../src/devices/usb.cpp:51 ../src/devices/usb.cpp:96
+#: ../src/devices/usb.cpp:98
+#, c-format
+msgid "USB device: %s"
+msgstr "USB Aygıt: %s"
+
+#: ../src/devices/usb.cpp:94
+#, c-format
+msgid "USB device: %s (%s)"
+msgstr "USB Aygıt: %s (%s)"
+
+#: ../src/devlist.cpp:330
+msgid "Process"
+msgstr ""
+
+#. Report Output
+#. No div attribute here inherits from device power report
+#: ../src/devlist.cpp:347
+msgid "Process Device Activity"
+msgstr ""
+
+#: ../src/display.cpp:70
+msgid "Overview"
+msgstr "Genel"
+
+#: ../src/display.cpp:71
+msgid "Idle stats"
+msgstr "Bekleme İst"
+
+#: ../src/display.cpp:72
+msgid "Frequency stats"
+msgstr "Frekans İst"
+
+#: ../src/display.cpp:73
+msgid "Device stats"
+msgstr "Aygıt İst"
+
+#: ../src/display.cpp:131
+msgid "Exit"
+msgstr "Çıkış"
+
+#: ../src/display.cpp:132
+msgid "Navigate"
+msgstr ""
+
+#: ../src/lib.cpp:288
+#, c-format
+msgid "%7sW"
+msgstr "% 7sW"
+
+#: ../src/lib.cpp:291
+#, c-format
+msgid " 0 mW"
+msgstr "0 mW"
+
+#: ../src/lib.cpp:410
+msgid "PS/2 Touchpad / Keyboard / Mouse"
+msgstr "PS/2 Dokunmatik Ped / Klavye / Fare"
+
+#: ../src/lib.cpp:411
+msgid "SATA controller"
+msgstr "SATA denetleyicisi"
+
+#: ../src/lib.cpp:412
+msgid "Intel built in USB hub"
+msgstr "Yerleşik Intel USB hub"
+
+#: ../src/lib.cpp:467
+#, c-format
+msgid "glob returned GLOB_NOSPACE\n"
+msgstr ""
+
+#: ../src/lib.cpp:471
+#, c-format
+msgid "glob returned GLOB_ABORTED\n"
+msgstr ""
+
+#: ../src/lib.cpp:475
+#, c-format
+msgid "glob returned GLOB_NOMATCH\n"
+msgstr ""
+
+#: ../src/lib.cpp:513 ../src/lib.cpp:549
+#, c-format
+msgid ""
+"Model-specific registers (MSR)\t\t\t not found (try enabling "
+"CONFIG_X86_MSR).\n"
+msgstr ""
+
+#: ../src/main.cpp:103
+#, c-format
+msgid "PowerTOP version "
+msgstr ""
+
+#: ../src/main.cpp:109
+msgid "Set refresh time out"
+msgstr ""
+
+#: ../src/main.cpp:122
+msgid "Usage: powertop [OPTIONS]"
+msgstr ""
+
+#: ../src/main.cpp:123
+msgid "sets all tunable options to their GOOD setting"
+msgstr ""
+
+#: ../src/main.cpp:124
+msgid "runs powertop in calibration mode"
+msgstr ""
+
+#: ../src/main.cpp:125 ../src/main.cpp:128
+msgid "[=filename]"
+msgstr ""
+
+#: ../src/main.cpp:125
+msgid "generate a csv report"
+msgstr ""
+
+#: ../src/main.cpp:126
+msgid "run in \"debug\" mode"
+msgstr ""
+
+#: ../src/main.cpp:127
+msgid "[=devnode]"
+msgstr ""
+
+#: ../src/main.cpp:127
+msgid "uses an Extech Power Analyzer for measurements"
+msgstr ""
+
+#: ../src/main.cpp:128
+msgid "generate a html report"
+msgstr ""
+
+#: ../src/main.cpp:129
+msgid "[=iterations] number of times to run each test"
+msgstr ""
+
+#: ../src/main.cpp:130
+msgid "suppress stderr output"
+msgstr ""
+
+#: ../src/main.cpp:131 ../src/main.cpp:132
+msgid "[=seconds]"
+msgstr ""
+
+#: ../src/main.cpp:131
+msgid "interval for power consumption measurement"
+msgstr ""
+
+#: ../src/main.cpp:132
+msgid "generate a report for 'x' seconds"
+msgstr ""
+
+#: ../src/main.cpp:133
+msgid "[=workload]"
+msgstr ""
+
+#: ../src/main.cpp:133
+msgid "file to execute for workload"
+msgstr ""
+
+#: ../src/main.cpp:134
+msgid "print version information"
+msgstr ""
+
+#: ../src/main.cpp:135
+msgid "print this help menu"
+msgstr ""
+
+#: ../src/main.cpp:137
+msgid "For more help please refer to the 'man 8 powertop'"
+msgstr ""
+
+#: ../src/main.cpp:232
+#, c-format
+msgid "Unknown issue running workload!\n"
+msgstr ""
+
+#: ../src/main.cpp:289
+msgid "PowerTOP is out of memory. PowerTOP is Aborting"
+msgstr ""
+
+#. one to warm up everything
+#: ../src/main.cpp:297
+#, c-format
+msgid "Preparing to take measurements\n"
+msgstr ""
+
+#: ../src/main.cpp:302
+#, c-format
+msgid "Taking %d measurement(s) for a duration of %d second(s) each.\n"
+msgstr ""
+
+#: ../src/main.cpp:304
+#, c-format
+msgid "Measuring workload %s.\n"
+msgstr ""
+
+#: ../src/main.cpp:329
+#, c-format
+msgid "PowerTOP "
+msgstr ""
+
+#: ../src/main.cpp:330 ../src/main.cpp:380
+#, c-format
+msgid "exiting...\n"
+msgstr ""
+
+#: ../src/main.cpp:364
+#, c-format
+msgid "modprobe cpufreq_stats failed"
+msgstr ""
+
+#: ../src/main.cpp:367
+#, c-format
+msgid "modprobe msr failed"
+msgstr ""
+
+#: ../src/main.cpp:379 ../src/main.cpp:383
+#, c-format
+msgid "Failed to mount debugfs!\n"
+msgstr ""
+
+#: ../src/main.cpp:384
+#, c-format
+msgid "Should still be able to auto tune...\n"
+msgstr ""
+
+#: ../src/main.cpp:466
+#, c-format
+msgid "Invalid CSV filename\n"
+msgstr ""
+
+#: ../src/main.cpp:482
+#, c-format
+msgid "Invalid HTML filename\n"
+msgstr ""
+
+#: ../src/main.cpp:491
+#, c-format
+msgid "Quiet mode failed!\n"
+msgstr ""
+
+#: ../src/main.cpp:559
+msgid "Leaving PowerTOP"
+msgstr ""
+
+#: ../src/parameters/persistent.cpp:46 ../src/parameters/persistent.cpp:155
+msgid "Cannot save to file"
+msgstr ""
+
+#: ../src/parameters/persistent.cpp:89 ../src/parameters/persistent.cpp:180
+msgid "Cannot load from file"
+msgstr ""
+
+#. '%i" is for count, do not translate
+#: ../src/parameters/persistent.cpp:138
+#, c-format
+msgid "Loaded %i prior measurements\n"
+msgstr ""
+
+#: ../src/parameters/persistent.cpp:181
+msgid ""
+"File will be loaded after taking minimum number of measurement(s) with "
+"battery only \n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:115
+#, c-format
+msgid ""
+"Too many open files, please increase the limit of open file descriptors.\n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:117
+#, c-format
+msgid "PowerTOP %s needs the kernel to support the 'perf' subsystem\n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:118
+#, c-format
+msgid "as well as support for trace points in the kernel:\n"
+msgstr ""
+
+#: ../src/process/do_process.cpp:819
+#, c-format
+msgid ""
+"Estimated power: %5.1f Measured power: %5.1f Sum: %5.1f\n"
+"\n"
+msgstr ""
+"Tahmini güç: %5.1f Ölçülen güç: %5.1f Toplam: %5.1f\n"
+"\n"
+
+#: ../src/process/do_process.cpp:838
+#, c-format
+msgid "The estimated remaining time is %i hours, %i minutes\n"
+msgstr ""
+
+#: ../src/process/do_process.cpp:846
+msgid "Summary"
+msgstr "Özet"
+
+#: ../src/process/do_process.cpp:846
+msgid "wakeups/second"
+msgstr ""
+
+#: ../src/process/do_process.cpp:846
+msgid "GPU ops/seconds"
+msgstr ""
+
+#: ../src/process/do_process.cpp:846
+msgid "VFS ops/sec and"
+msgstr ""
+
+#: ../src/process/do_process.cpp:846
+msgid "CPU use"
+msgstr "CPU kullanımı"
+
+#: ../src/process/do_process.cpp:850
+msgid "Power est."
+msgstr "Tahmini Güç"
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:1078
+msgid "Events/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:931 ../src/process/do_process.cpp:1079
+msgid "Category"
+msgstr "Kategori"
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:932 ../src/process/do_process.cpp:1080
+#: ../src/tuning/tuning.cpp:242 ../src/tuning/tuning.cpp:270
+#: ../src/tuning/tuning.cpp:288 ../src/wakeup/waketab.cpp:155
+msgid "Description"
+msgstr ""
+
+#: ../src/process/do_process.cpp:927
+msgid "Wakeups/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:928
+msgid "GPU ops/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:929
+msgid "Disk IO/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:930
+msgid "GFX Wakeups/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1017
+msgid "Overview of Software Power Consumers"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1057
+msgid "Target:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1058
+msgid "1 units/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1059
+msgid "System: "
+msgstr ""
+
+#: ../src/process/do_process.cpp:1061
+msgid " wakeup/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1062
+msgid "CPU: "
+msgstr ""
+
+#: ../src/process/do_process.cpp:1064
+#, fuzzy, c-format
+msgid "% usage"
+msgstr "Kullanım"
+
+#: ../src/process/do_process.cpp:1065
+msgid "GPU:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1067 ../src/process/do_process.cpp:1073
+msgid " ops/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1068
+msgid "GFX:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1070
+msgid " wakeups/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1071
+msgid "VFS:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1139
+msgid "Top 10 Power Consumers"
+msgstr ""
+
+#: ../src/report/report.cpp:122
+#, fuzzy
+msgid "PowerTOP Version"
+msgstr "Tahmini Güç"
+
+#: ../src/report/report.cpp:131
+msgid "Kernel Version"
+msgstr ""
+
+#: ../src/report/report.cpp:135
+msgid "System Name"
+msgstr ""
+
+#: ../src/report/report.cpp:142
+msgid "CPU Information"
+msgstr ""
+
+#: ../src/report/report.cpp:154
+msgid "OS Information"
+msgstr ""
+
+#: ../src/report/report.cpp:161
+msgid "System Information"
+msgstr ""
+
+#: ../src/report/report.cpp:195
+#, c-format
+msgid "Cannot open output file %s (%s)\n"
+msgstr ""
+
+#: ../src/report/report.cpp:211
+#, c-format
+msgid "PowerTOP outputing using base filename %s\n"
+msgstr ""
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:49
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+msgid "Good"
+msgstr "İyi"
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:50
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+msgid "Bad"
+msgstr "Kötü"
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:51
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+#: ../src/wakeup/wakeup.cpp:50
+msgid "Unknown"
+msgstr "Bilinmiyor"
+
+#: ../src/tuning/bluetooth.cpp:48
+#, c-format
+msgid "Bluetooth device interface status"
+msgstr ""
+
+#: ../src/tuning/ethernet.cpp:54 ../src/wakeup/wakeup_ethernet.cpp:51
+#, c-format
+msgid "Wake-on-lan status for device %s"
+msgstr ""
+
+#: ../src/tuning/runtime.cpp:48
+#, c-format
+msgid "Runtime PM for %s device %s"
+msgstr ""
+
+#: ../src/tuning/runtime.cpp:50
+#, c-format
+msgid "%s device %s has no runtime power management"
+msgstr ""
+
+#: ../src/tuning/runtime.cpp:74
+#, c-format
+msgid "PCI Device %s has no runtime power management"
+msgstr ""
+
+#: ../src/tuning/runtime.cpp:76
+#, c-format
+msgid "Runtime PM for PCI Device %s"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:62
+msgid "Enable Audio codec power management"
+msgstr "Etkin Ses kodlayıcı güç yönetimi"
+
+#: ../src/tuning/tuning.cpp:63
+msgid "NMI watchdog should be turned off"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:64
+msgid "Power Aware CPU scheduler"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:65
+msgid "VM writeback timeout"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:81
+msgid "Tunables"
+msgstr ""
+
+#: ../src/tuning/tuning.cpp:81
+msgid " <ESC> Exit | <Enter> Toggle tunable | <r> Window refresh"
+msgstr " <ESC> Çıkış | <Enter> Değer değiştirme | <r> Pencere yenileme"
+
+#: ../src/tuning/tuning.cpp:243 ../src/wakeup/waketab.cpp:156
+msgid "Script"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:257
+msgid "Software Settings in Need of Tuning"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:276
+msgid "Untunable Software Issues"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:300
+msgid "Optimal Tuned Software Settings"
+msgstr ""
+
+#: ../src/tuning/tuningi2c.cpp:57
+#, c-format
+msgid "Runtime PM for I2C %s %s (%s)"
+msgstr ""
+
+#: ../src/tuning/tuningi2c.cpp:59
+#, c-format
+msgid "I2C %s %s has no runtime power management"
+msgstr ""
+
+#: ../src/tuning/tuningsysfs.cpp:123
+#, fuzzy, c-format
+msgid "Enable SATA link power management for %s"
+msgstr "Etkin Ses kodlayıcı güç yönetimi"
+
+#: ../src/tuning/tuningusb.cpp:54
+#, c-format
+msgid "Autosuspend for unknown USB device %s (%s:%s)"
+msgstr ""
+
+#: ../src/tuning/tuningusb.cpp:71 ../src/tuning/tuningusb.cpp:73
+#: ../src/tuning/tuningusb.cpp:75
+#, c-format
+msgid "Autosuspend for USB device %s [%s]"
+msgstr ""
+
+#: ../src/tuning/wifi.cpp:48
+#, c-format
+msgid "Wireless Power Saving for interface %s"
+msgstr "%s arabirimi için Kablosuz Güç Tasarrufu"
+
+#: ../src/wakeup/waketab.cpp:42
+msgid "WakeUp"
+msgstr ""
+
+#: ../src/wakeup/waketab.cpp:42
+#, fuzzy
+msgid " <ESC> Exit | <Enter> Toggle wakeup | <r> Window refresh"
+msgstr " <ESC> Çıkış | <Enter> Değer değiştirme | <r> Pencere yenileme"
+
+#. Report Output
+#: ../src/wakeup/waketab.cpp:170
+msgid "Wake status of the devices"
+msgstr ""
+
+#: ../src/wakeup/wakeup.cpp:48 ../src/wakeup/wakeup_ethernet.cpp:47
+#: ../src/wakeup/wakeup_usb.cpp:47
+msgid "Enable"
+msgstr ""
+
+#: ../src/wakeup/wakeup.cpp:49 ../src/wakeup/wakeup_ethernet.cpp:47
+#: ../src/wakeup/wakeup_usb.cpp:47
+msgid "Disable"
+msgstr ""
+
+#: ../src/wakeup/wakeup_usb.cpp:51
+#, fuzzy, c-format
+msgid "Wake status for USB device %s"
+msgstr "USB Aygıt: %s"
diff --git a/po/zh_CN.po b/po/zh_CN.po
new file mode 100644
index 0000000..a9a2b47
--- /dev/null
+++ b/po/zh_CN.po
@@ -0,0 +1,996 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Intel Corporation
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Tommy He <lovenemesis@gmail.com>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: PowerTOP\n"
+"Report-Msgid-Bugs-To: powertop@lists.01.org\n"
+"POT-Creation-Date: 2019-01-04 13:55-0800\n"
+"PO-Revision-Date: 2013-11-05 08:40+0000\n"
+"Last-Translator: Margie Foster <margie@linux.intel.com>\n"
+"Language-Team: Chinese (China) (http://www.transifex.com/projects/p/PowerTOP/"
+"language/zh_CN/)\n"
+"Language: zh_CN\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: ../src/calibrate/calibrate.cpp:238
+#, c-format
+msgid "Cannot create temp file\n"
+msgstr "无法创建临时文件\n"
+
+#: ../src/calibrate/calibrate.cpp:258
+#, c-format
+msgid "Calibrating: CPU usage on %i threads\n"
+msgstr "校准:%i 线程中的 CPU 使用\n"
+
+#: ../src/calibrate/calibrate.cpp:273
+#, c-format
+msgid "Calibrating: CPU wakeup power consumption\n"
+msgstr "校准:CPU 唤醒电源消耗\n"
+
+#: ../src/calibrate/calibrate.cpp:290
+#, c-format
+msgid "Calibrating USB devices\n"
+msgstr "校准 USB 设备\n"
+
+#: ../src/calibrate/calibrate.cpp:292 ../src/calibrate/calibrate.cpp:309
+#: ../src/calibrate/calibrate.cpp:317 ../src/calibrate/calibrate.cpp:334
+#, c-format
+msgid ".... device %s \n"
+msgstr ".... 设别 %s \n"
+
+#: ../src/calibrate/calibrate.cpp:307
+#, c-format
+msgid "Calibrating radio devices\n"
+msgstr "校准无线电设备\n"
+
+#: ../src/calibrate/calibrate.cpp:331
+#, c-format
+msgid "Calibrating backlight\n"
+msgstr "校准背光\n"
+
+#: ../src/calibrate/calibrate.cpp:355 ../src/calibrate/calibrate.cpp:365
+#, c-format
+msgid "Calibrating idle\n"
+msgstr "校准空闲耗电\n"
+
+#: ../src/calibrate/calibrate.cpp:378
+#, c-format
+msgid "Calibrating: disk usage \n"
+msgstr "校准:磁盘使用\n"
+
+#: ../src/calibrate/calibrate.cpp:403
+msgid "Starting PowerTOP power estimate calibration \n"
+msgstr "开始 PowerTOP 电量预计校准\n"
+
+#: ../src/calibrate/calibrate.cpp:426
+msgid "Finishing PowerTOP power estimate calibration \n"
+msgstr "结束 PowerTOP 电量预计校准\n"
+
+#: ../src/calibrate/calibrate.cpp:430
+#, c-format
+msgid "Parameters after calibration:\n"
+msgstr "校准后参数:\n"
+
+#: ../src/cpu/abstract_cpu.cpp:74
+msgid "Idle"
+msgstr ""
+
+#: ../src/cpu/abstract_cpu.cpp:76
+msgid "Turbo Mode"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(HW)"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:37
+#, c-format
+msgid " Core(OS)"
+msgstr ""
+
+#: ../src/cpu/cpu_core.cpp:91 ../src/cpu/intel_cpus.cpp:324
+#, c-format
+msgid " Core"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:85
+#, c-format
+msgid "cpu package %i"
+msgstr "CPU 代号 %i"
+
+#: ../src/cpu/cpu.cpp:86
+msgid "cpu package"
+msgstr "CPU 代号"
+
+#: ../src/cpu/cpu.cpp:89 ../src/cpu/cpu.cpp:96
+#, fuzzy, c-format
+msgid "package-%i"
+msgstr "CPU 代号 %i"
+
+#: ../src/cpu/cpu.cpp:90
+msgid "cpu rapl package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:97
+msgid "dram rapl package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:471
+msgid "Processor Idle State Report"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:535 ../src/cpu/cpu.cpp:753
+msgid "Package"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:566 ../src/cpu/cpu.cpp:775
+#, c-format
+msgid "Core %d"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:573
+#, c-format
+msgid "GPU %d"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:594
+#, fuzzy
+msgid "CPU"
+msgstr "CPU 占用"
+
+#: ../src/cpu/cpu.cpp:676
+msgid "Processor Frequency Report"
+msgstr ""
+
+#: ../src/cpu/cpu.cpp:796
+#, fuzzy, c-format
+msgid "CPU %d"
+msgstr "CPU 占用"
+
+#: ../src/cpu/cpu.cpp:997
+#, c-format
+msgid "cpu_idle event returned no state?\n"
+msgstr "CPU 空闲事件没有返回状态?\n"
+
+#: ../src/cpu/cpu.cpp:1012
+#, c-format
+msgid "power or cpu_frequency event returned no state?\n"
+msgstr ""
+
+#: ../src/cpu/cpu_linux.cpp:79
+msgid "C0 polling"
+msgstr "C0 轮巡"
+
+#: ../src/cpu/cpu_linux.cpp:242
+#, c-format
+msgid " CPU(OS) %i"
+msgstr ""
+
+#: ../src/cpu/cpu_linux.cpp:341 ../src/cpu/intel_cpus.cpp:651
+#, c-format
+msgid " CPU %i"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(HW)"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(OS)"
+msgstr ""
+
+#: ../src/cpu/cpu_package.cpp:104 ../src/cpu/intel_cpus.cpp:412
+#, c-format
+msgid " Package"
+msgstr ""
+
+#: ../src/cpu/intel_cpus.cpp:129
+#, c-format
+msgid "read_msr cpu%d 0x%llx : "
+msgstr ""
+
+#: ../src/cpu/intel_cpus.cpp:574
+msgid "C0 active"
+msgstr "C0 运行"
+
+#: ../src/cpu/intel_cpus.cpp:632
+#, c-format
+msgid "Average"
+msgstr ""
+
+#: ../src/cpu/intel_gpu.cpp:64
+#, c-format
+msgid " GPU "
+msgstr ""
+
+#: ../src/devices/ahci.cpp:154
+#, c-format
+msgid "SATA link: %s"
+msgstr "SATA 连线: %s"
+
+#: ../src/devices/ahci.cpp:156
+#, c-format
+msgid "SATA disk: %s"
+msgstr "SATA 磁盘: %s"
+
+#: ../src/devices/ahci.cpp:374
+msgid "AHCI ALPM Residency Statistics - Not supported on this macine"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:389
+msgid "Link"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:390
+#, fuzzy
+msgid "Active"
+msgstr "C0 运行"
+
+#: ../src/devices/ahci.cpp:391
+msgid "Partial"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:392
+msgid "Slumber"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:393
+msgid "Devslp"
+msgstr ""
+
+#: ../src/devices/ahci.cpp:399
+msgid "AHCI ALPM Residency Statistics"
+msgstr ""
+
+#: ../src/devices/alsa.cpp:77
+#, c-format
+msgid "Audio codec %s: %s (%s)"
+msgstr "音频设备 %s: %s (%s)"
+
+#: ../src/devices/alsa.cpp:79 ../src/devices/alsa.cpp:81
+#, c-format
+msgid "Audio codec %s: %s"
+msgstr "音频设备 %s: %s"
+
+#: ../src/devices/devfreq.cpp:261
+#, fuzzy
+msgid "Device Freq stats"
+msgstr "设备统计"
+
+#: ../src/devices/devfreq.cpp:279
+msgid " Devfreq is not enabled"
+msgstr ""
+
+#: ../src/devices/devfreq.cpp:284
+msgid " No devfreq devices available"
+msgstr ""
+
+#: ../src/devices/device.cpp:172 ../src/process/do_process.cpp:831
+#, c-format
+msgid "The battery reports a discharge rate of %sW\n"
+msgstr "电池报告放电速率为 %sW\n"
+
+#: ../src/devices/device.cpp:174 ../src/process/do_process.cpp:833
+#, c-format
+msgid "The power consumed was %sJ\n"
+msgstr ""
+
+#: ../src/devices/device.cpp:180
+#, c-format
+msgid "System baseline power is estimated at %sW\n"
+msgstr "系统基线耗电量为 %sW\n"
+
+#: ../src/devices/device.cpp:187
+msgid "Power est. Usage Device name\n"
+msgstr "预计电量 使用量 设备名\n"
+
+#: ../src/devices/device.cpp:189
+msgid " Usage Device name\n"
+msgstr " 使用量 设备名\n"
+
+#: ../src/devices/device.cpp:256
+#, fuzzy
+msgid "The battery reports a discharge rate of: "
+msgstr "电池报告放电速率为 %sW\n"
+
+#: ../src/devices/device.cpp:261
+msgid "The power consumed was : "
+msgstr ""
+
+#: ../src/devices/device.cpp:268
+#, fuzzy
+msgid "The system baseline power is estimated at: "
+msgstr "系统基线耗电量为 %sW\n"
+
+#: ../src/devices/device.cpp:277 ../src/process/do_process.cpp:850
+#: ../src/process/do_process.cpp:852 ../src/process/do_process.cpp:926
+#: ../src/process/do_process.cpp:1077
+msgid "Usage"
+msgstr "用量"
+
+#: ../src/devices/device.cpp:278
+#, fuzzy
+msgid "Device Name"
+msgstr "设备统计"
+
+#: ../src/devices/device.cpp:280 ../src/process/do_process.cpp:935
+#: ../src/process/do_process.cpp:1082
+msgid "PW Estimate"
+msgstr ""
+
+#. Report Output
+#: ../src/devices/device.cpp:317
+msgid "Device Power Report"
+msgstr ""
+
+#: ../src/devices/network.cpp:177
+#, c-format
+msgid "Network interface: %s (%s)"
+msgstr "网络接口: %s (%s)"
+
+#: ../src/devices/rfkill.cpp:65 ../src/devices/rfkill.cpp:69
+#, c-format
+msgid "Radio device: %s"
+msgstr "无线电设备: %s"
+
+#: ../src/devices/runtime_pm.cpp:216
+#, c-format
+msgid "I2C %s (%s): %s"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216 ../src/tuning/tuningi2c.cpp:57
+#: ../src/tuning/tuningi2c.cpp:59
+msgid "Adapter"
+msgstr ""
+
+#: ../src/devices/runtime_pm.cpp:216 ../src/devlist.cpp:331
+#: ../src/tuning/tuningi2c.cpp:57 ../src/tuning/tuningi2c.cpp:59
+#, fuzzy
+msgid "Device"
+msgstr "设备统计"
+
+#: ../src/devices/runtime_pm.cpp:241
+#, c-format
+msgid "PCI Device: %s"
+msgstr "PCI 设备: %s"
+
+#: ../src/devices/usb.cpp:51 ../src/devices/usb.cpp:96
+#: ../src/devices/usb.cpp:98
+#, c-format
+msgid "USB device: %s"
+msgstr "USB 设备: %s"
+
+#: ../src/devices/usb.cpp:94
+#, c-format
+msgid "USB device: %s (%s)"
+msgstr "USB 设备: %s (%s)"
+
+#: ../src/devlist.cpp:330
+msgid "Process"
+msgstr ""
+
+#. Report Output
+#. No div attribute here inherits from device power report
+#: ../src/devlist.cpp:347
+msgid "Process Device Activity"
+msgstr ""
+
+#: ../src/display.cpp:70
+msgid "Overview"
+msgstr "概况"
+
+#: ../src/display.cpp:71
+msgid "Idle stats"
+msgstr "空闲统计"
+
+#: ../src/display.cpp:72
+msgid "Frequency stats"
+msgstr "频率统计"
+
+#: ../src/display.cpp:73
+msgid "Device stats"
+msgstr "设备统计"
+
+#: ../src/display.cpp:131
+msgid "Exit"
+msgstr "退出"
+
+#: ../src/display.cpp:132
+msgid "Navigate"
+msgstr ""
+
+#: ../src/lib.cpp:288
+#, c-format
+msgid "%7sW"
+msgstr "%7sW"
+
+#: ../src/lib.cpp:291
+#, c-format
+msgid " 0 mW"
+msgstr " 0 mW"
+
+#: ../src/lib.cpp:410
+msgid "PS/2 Touchpad / Keyboard / Mouse"
+msgstr "PS/2 触摸板 / 键盘 / 鼠标"
+
+#: ../src/lib.cpp:411
+msgid "SATA controller"
+msgstr "SATA 控制器"
+
+#: ../src/lib.cpp:412
+msgid "Intel built in USB hub"
+msgstr "Intel 内建 USB 集线器"
+
+#: ../src/lib.cpp:467
+#, c-format
+msgid "glob returned GLOB_NOSPACE\n"
+msgstr ""
+
+#: ../src/lib.cpp:471
+#, c-format
+msgid "glob returned GLOB_ABORTED\n"
+msgstr ""
+
+#: ../src/lib.cpp:475
+#, c-format
+msgid "glob returned GLOB_NOMATCH\n"
+msgstr ""
+
+#: ../src/lib.cpp:513 ../src/lib.cpp:549
+#, c-format
+msgid ""
+"Model-specific registers (MSR)\t\t\t not found (try enabling "
+"CONFIG_X86_MSR).\n"
+msgstr ""
+
+#: ../src/main.cpp:103
+#, fuzzy, c-format
+msgid "PowerTOP version "
+msgstr "PowerTOP 版本"
+
+#: ../src/main.cpp:109
+msgid "Set refresh time out"
+msgstr "设定刷新延迟"
+
+#: ../src/main.cpp:122
+msgid "Usage: powertop [OPTIONS]"
+msgstr "用法:powertop [选项]"
+
+#: ../src/main.cpp:123
+msgid "sets all tunable options to their GOOD setting"
+msgstr ""
+
+#: ../src/main.cpp:124
+msgid "runs powertop in calibration mode"
+msgstr "以校准模式运行 PowerTOP"
+
+#: ../src/main.cpp:125 ../src/main.cpp:128
+msgid "[=filename]"
+msgstr ""
+
+#: ../src/main.cpp:125
+msgid "generate a csv report"
+msgstr "生成 CSV 报告"
+
+#: ../src/main.cpp:126
+msgid "run in \"debug\" mode"
+msgstr "以“除错”模式运行"
+
+#: ../src/main.cpp:127
+msgid "[=devnode]"
+msgstr "[=devnode]"
+
+#: ../src/main.cpp:127
+msgid "uses an Extech Power Analyzer for measurements"
+msgstr "使用 Extech 电源分析仪进行测量"
+
+#: ../src/main.cpp:128
+msgid "generate a html report"
+msgstr "生成 HTML 报告"
+
+#: ../src/main.cpp:129
+msgid "[=iterations] number of times to run each test"
+msgstr "[=重复数] 运行每项测试的次数"
+
+#: ../src/main.cpp:130
+msgid "suppress stderr output"
+msgstr ""
+
+#: ../src/main.cpp:131 ../src/main.cpp:132
+msgid "[=seconds]"
+msgstr "[=秒]"
+
+#: ../src/main.cpp:131
+msgid "interval for power consumption measurement"
+msgstr ""
+
+#: ../src/main.cpp:132
+msgid "generate a report for 'x' seconds"
+msgstr "生成指定 'x' 秒数的报告"
+
+#: ../src/main.cpp:133
+msgid "[=workload]"
+msgstr ""
+
+#: ../src/main.cpp:133
+msgid "file to execute for workload"
+msgstr ""
+
+#: ../src/main.cpp:134
+msgid "print version information"
+msgstr "打印版本信息"
+
+#: ../src/main.cpp:135
+msgid "print this help menu"
+msgstr "打印此帮助菜单"
+
+#: ../src/main.cpp:137
+#, fuzzy
+msgid "For more help please refer to the 'man 8 powertop'"
+msgstr "更多帮助请查阅 README"
+
+#: ../src/main.cpp:232
+#, c-format
+msgid "Unknown issue running workload!\n"
+msgstr ""
+
+#: ../src/main.cpp:289
+msgid "PowerTOP is out of memory. PowerTOP is Aborting"
+msgstr "PowerTOP 内存溢出。 PowerTOP 正在退出。"
+
+#. one to warm up everything
+#: ../src/main.cpp:297
+#, c-format
+msgid "Preparing to take measurements\n"
+msgstr "准备开始测量\n"
+
+#: ../src/main.cpp:302
+#, c-format
+msgid "Taking %d measurement(s) for a duration of %d second(s) each.\n"
+msgstr "执行 %d 次测量,每个持续 %d 秒。\n"
+
+#: ../src/main.cpp:304
+#, c-format
+msgid "Measuring workload %s.\n"
+msgstr ""
+
+#: ../src/main.cpp:329
+#, c-format
+msgid "PowerTOP "
+msgstr "PowerTOP "
+
+#: ../src/main.cpp:330 ../src/main.cpp:380
+#, c-format
+msgid "exiting...\n"
+msgstr "退出……\n"
+
+#: ../src/main.cpp:364
+#, c-format
+msgid "modprobe cpufreq_stats failed"
+msgstr ""
+
+#: ../src/main.cpp:367
+#, c-format
+msgid "modprobe msr failed"
+msgstr ""
+
+#: ../src/main.cpp:379 ../src/main.cpp:383
+#, c-format
+msgid "Failed to mount debugfs!\n"
+msgstr "挂载 debugfs 失败!\n"
+
+#: ../src/main.cpp:384
+#, c-format
+msgid "Should still be able to auto tune...\n"
+msgstr ""
+
+#: ../src/main.cpp:466
+#, c-format
+msgid "Invalid CSV filename\n"
+msgstr ""
+
+#: ../src/main.cpp:482
+#, c-format
+msgid "Invalid HTML filename\n"
+msgstr ""
+
+#: ../src/main.cpp:491
+#, c-format
+msgid "Quiet mode failed!\n"
+msgstr ""
+
+#: ../src/main.cpp:559
+msgid "Leaving PowerTOP"
+msgstr "离开 PowerTOP"
+
+#: ../src/parameters/persistent.cpp:46 ../src/parameters/persistent.cpp:155
+msgid "Cannot save to file"
+msgstr ""
+
+#: ../src/parameters/persistent.cpp:89 ../src/parameters/persistent.cpp:180
+msgid "Cannot load from file"
+msgstr ""
+
+#. '%i" is for count, do not translate
+#: ../src/parameters/persistent.cpp:138
+#, c-format
+msgid "Loaded %i prior measurements\n"
+msgstr "载入之前 %i 的测量。\n"
+
+#: ../src/parameters/persistent.cpp:181
+msgid ""
+"File will be loaded after taking minimum number of measurement(s) with "
+"battery only \n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:115
+#, c-format
+msgid ""
+"Too many open files, please increase the limit of open file descriptors.\n"
+msgstr ""
+
+#: ../src/perf/perf.cpp:117
+#, c-format
+msgid "PowerTOP %s needs the kernel to support the 'perf' subsystem\n"
+msgstr ""
+"PowerTOP %s 需要内核支持 'perf' 子系统\n"
+"\n"
+
+#: ../src/perf/perf.cpp:118
+#, c-format
+msgid "as well as support for trace points in the kernel:\n"
+msgstr "以及支持内核中追溯点:\n"
+
+#: ../src/process/do_process.cpp:819
+#, c-format
+msgid ""
+"Estimated power: %5.1f Measured power: %5.1f Sum: %5.1f\n"
+"\n"
+msgstr ""
+"预计耗电量: %5.1f 测量耗电量: %5.1f 总计: %5.1f\n"
+"\n"
+
+#: ../src/process/do_process.cpp:838
+#, c-format
+msgid "The estimated remaining time is %i hours, %i minutes\n"
+msgstr "估计剩余时间 %i 小时, %i 分钟\n"
+
+#: ../src/process/do_process.cpp:846
+msgid "Summary"
+msgstr "摘要"
+
+#: ../src/process/do_process.cpp:846
+msgid "wakeups/second"
+msgstr "每秒唤醒数"
+
+#: ../src/process/do_process.cpp:846
+msgid "GPU ops/seconds"
+msgstr "每秒 GPU 操作数"
+
+#: ../src/process/do_process.cpp:846
+msgid "VFS ops/sec and"
+msgstr "每秒 VFS 操作数和"
+
+#: ../src/process/do_process.cpp:846
+msgid "CPU use"
+msgstr "CPU 占用"
+
+#: ../src/process/do_process.cpp:850
+msgid "Power est."
+msgstr "估计电量"
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:1078
+msgid "Events/s"
+msgstr "每秒事件数"
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:931 ../src/process/do_process.cpp:1079
+msgid "Category"
+msgstr "分类"
+
+#: ../src/process/do_process.cpp:850 ../src/process/do_process.cpp:852
+#: ../src/process/do_process.cpp:932 ../src/process/do_process.cpp:1080
+#: ../src/tuning/tuning.cpp:242 ../src/tuning/tuning.cpp:270
+#: ../src/tuning/tuning.cpp:288 ../src/wakeup/waketab.cpp:155
+msgid "Description"
+msgstr "描述"
+
+#: ../src/process/do_process.cpp:927
+msgid "Wakeups/s"
+msgstr "每秒唤醒数"
+
+#: ../src/process/do_process.cpp:928
+msgid "GPU ops/s"
+msgstr "每秒 GPU 操作数"
+
+#: ../src/process/do_process.cpp:929
+msgid "Disk IO/s"
+msgstr "每秒磁盘 IO 数"
+
+#: ../src/process/do_process.cpp:930
+msgid "GFX Wakeups/s"
+msgstr "每秒 GFX 唤醒数"
+
+#: ../src/process/do_process.cpp:1017
+msgid "Overview of Software Power Consumers"
+msgstr "软件电量消耗概览"
+
+#: ../src/process/do_process.cpp:1057
+msgid "Target:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1058
+msgid "1 units/s"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1059
+msgid "System: "
+msgstr ""
+
+#: ../src/process/do_process.cpp:1061
+#, fuzzy
+msgid " wakeup/s"
+msgstr "每秒唤醒数"
+
+#: ../src/process/do_process.cpp:1062
+msgid "CPU: "
+msgstr ""
+
+#: ../src/process/do_process.cpp:1064
+#, fuzzy, c-format
+msgid "% usage"
+msgstr "用量"
+
+#: ../src/process/do_process.cpp:1065
+msgid "GPU:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1067 ../src/process/do_process.cpp:1073
+#, fuzzy
+msgid " ops/s"
+msgstr "每秒 GPU 操作数"
+
+#: ../src/process/do_process.cpp:1068
+msgid "GFX:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1070
+#, fuzzy
+msgid " wakeups/s"
+msgstr "每秒唤醒数"
+
+#: ../src/process/do_process.cpp:1071
+msgid "VFS:"
+msgstr ""
+
+#: ../src/process/do_process.cpp:1139
+#, fuzzy
+msgid "Top 10 Power Consumers"
+msgstr "软件电量消耗概览"
+
+#: ../src/report/report.cpp:122
+#, fuzzy
+msgid "PowerTOP Version"
+msgstr "PowerTOP 版本"
+
+#: ../src/report/report.cpp:131
+#, fuzzy
+msgid "Kernel Version"
+msgstr "PowerTOP 版本"
+
+#: ../src/report/report.cpp:135
+msgid "System Name"
+msgstr ""
+
+#: ../src/report/report.cpp:142
+msgid "CPU Information"
+msgstr ""
+
+#: ../src/report/report.cpp:154
+msgid "OS Information"
+msgstr ""
+
+#: ../src/report/report.cpp:161
+#, fuzzy
+msgid "System Information"
+msgstr "打印版本信息"
+
+#: ../src/report/report.cpp:195
+#, fuzzy, c-format
+msgid "Cannot open output file %s (%s)\n"
+msgstr "无法创建临时文件\n"
+
+#: ../src/report/report.cpp:211
+#, c-format
+msgid "PowerTOP outputing using base filename %s\n"
+msgstr ""
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:49
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+msgid "Good"
+msgstr "良好"
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:50
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+msgid "Bad"
+msgstr "糟糕"
+
+#: ../src/tuning/bluetooth.cpp:46 ../src/tuning/ethernet.cpp:50
+#: ../src/tuning/runtime.cpp:42 ../src/tuning/tunable.cpp:51
+#: ../src/tuning/tuningi2c.cpp:35 ../src/tuning/tuningsysfs.cpp:45
+#: ../src/tuning/tuningusb.cpp:39 ../src/tuning/wifi.cpp:45
+#: ../src/wakeup/wakeup.cpp:50
+msgid "Unknown"
+msgstr "未知"
+
+#: ../src/tuning/bluetooth.cpp:48
+#, c-format
+msgid "Bluetooth device interface status"
+msgstr "蓝牙设备接口状态"
+
+#: ../src/tuning/ethernet.cpp:54 ../src/wakeup/wakeup_ethernet.cpp:51
+#, c-format
+msgid "Wake-on-lan status for device %s"
+msgstr "设备 %s 的网络唤醒状态"
+
+#: ../src/tuning/runtime.cpp:48
+#, c-format
+msgid "Runtime PM for %s device %s"
+msgstr "%s 设备 %s 的运行时电源管理"
+
+#: ../src/tuning/runtime.cpp:50
+#, c-format
+msgid "%s device %s has no runtime power management"
+msgstr "%s 设备 %s 没有运行时电源管理"
+
+#: ../src/tuning/runtime.cpp:74
+#, c-format
+msgid "PCI Device %s has no runtime power management"
+msgstr "PCI 设备 %s 没有运行时电源管理"
+
+#: ../src/tuning/runtime.cpp:76
+#, c-format
+msgid "Runtime PM for PCI Device %s"
+msgstr "PCI 设备 %s 的运行时电源管理"
+
+#: ../src/tuning/tuning.cpp:62
+msgid "Enable Audio codec power management"
+msgstr "启用音频设备电源管理"
+
+#: ../src/tuning/tuning.cpp:63
+msgid "NMI watchdog should be turned off"
+msgstr "需要关闭 NMI 监控"
+
+#: ../src/tuning/tuning.cpp:64
+msgid "Power Aware CPU scheduler"
+msgstr "支持节电的 CPU 调度器"
+
+#: ../src/tuning/tuning.cpp:65
+msgid "VM writeback timeout"
+msgstr "虚拟内存回写延时"
+
+#: ../src/tuning/tuning.cpp:81
+msgid "Tunables"
+msgstr "可调项"
+
+#: ../src/tuning/tuning.cpp:81
+msgid " <ESC> Exit | <Enter> Toggle tunable | <r> Window refresh"
+msgstr " <ESC> 退出 | <Enter> 切换可调整项 | <r> 窗口刷新"
+
+#: ../src/tuning/tuning.cpp:243 ../src/wakeup/waketab.cpp:156
+msgid "Script"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:257
+msgid "Software Settings in Need of Tuning"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:276
+msgid "Untunable Software Issues"
+msgstr ""
+
+#. Report Output
+#: ../src/tuning/tuning.cpp:300
+msgid "Optimal Tuned Software Settings"
+msgstr ""
+
+#: ../src/tuning/tuningi2c.cpp:57
+#, fuzzy, c-format
+msgid "Runtime PM for I2C %s %s (%s)"
+msgstr "%s 设备 %s 的运行时电源管理"
+
+#: ../src/tuning/tuningi2c.cpp:59
+#, fuzzy, c-format
+msgid "I2C %s %s has no runtime power management"
+msgstr "%s 设备 %s 没有运行时电源管理"
+
+#: ../src/tuning/tuningsysfs.cpp:123
+#, fuzzy, c-format
+msgid "Enable SATA link power management for %s"
+msgstr "启用音频设备电源管理"
+
+#: ../src/tuning/tuningusb.cpp:54
+#, c-format
+msgid "Autosuspend for unknown USB device %s (%s:%s)"
+msgstr "自动挂起未知 USB 设备 %s (%s:%s)"
+
+#: ../src/tuning/tuningusb.cpp:71 ../src/tuning/tuningusb.cpp:73
+#: ../src/tuning/tuningusb.cpp:75
+#, c-format
+msgid "Autosuspend for USB device %s [%s]"
+msgstr "自动挂起 USB 设备 %s [%s]"
+
+#: ../src/tuning/wifi.cpp:48
+#, c-format
+msgid "Wireless Power Saving for interface %s"
+msgstr "接口 %s 的无线节电设置"
+
+#: ../src/wakeup/waketab.cpp:42
+#, fuzzy
+msgid "WakeUp"
+msgstr "每秒唤醒数"
+
+#: ../src/wakeup/waketab.cpp:42
+#, fuzzy
+msgid " <ESC> Exit | <Enter> Toggle wakeup | <r> Window refresh"
+msgstr " <ESC> 退出 | <Enter> 切换可调整项 | <r> 窗口刷新"
+
+#. Report Output
+#: ../src/wakeup/waketab.cpp:170
+#, fuzzy
+msgid "Wake status of the devices"
+msgstr "设备 %s 的网络唤醒状态"
+
+#: ../src/wakeup/wakeup.cpp:48 ../src/wakeup/wakeup_ethernet.cpp:47
+#: ../src/wakeup/wakeup_usb.cpp:47
+#, fuzzy
+msgid "Enable"
+msgstr "可调项"
+
+#: ../src/wakeup/wakeup.cpp:49 ../src/wakeup/wakeup_ethernet.cpp:47
+#: ../src/wakeup/wakeup_usb.cpp:47
+msgid "Disable"
+msgstr ""
+
+#: ../src/wakeup/wakeup_usb.cpp:51
+#, fuzzy, c-format
+msgid "Wake status for USB device %s"
+msgstr "设备 %s 的网络唤醒状态"
+
+#~ msgid "Actual"
+#~ msgstr "实际"
+
+#~ msgid "Power Consumption Summary"
+#~ msgstr "电量消耗摘要"
+
+#~ msgid "GPU ops/second"
+#~ msgstr "每秒 GPU 操作数"
+
+#~ msgid "VFS ops/sec"
+#~ msgstr "每秒 VFS 操作数"
+
+#~ msgid "GFX wakes/sec and"
+#~ msgstr "每秒 GFX 唤醒数和"
+
+#~ msgid "Using 'ondemand' cpufreq governor"
+#~ msgstr "使用 '按需调整' CPU 频率控制器"
+
+#~ msgid "[=FILENAME]"
+#~ msgstr "[=文件名]"
diff --git a/po/zh_TW.po b/po/zh_TW.po
new file mode 100644
index 0000000..7e902fd
--- /dev/null
+++ b/po/zh_TW.po
@@ -0,0 +1,997 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Intel Corporation
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# Yuan CHAO <yuanchao@gmail.com>, 2012-2013
+msgid ""
+msgstr ""
+"Project-Id-Version: PowerTOP\n"
+"Report-Msgid-Bugs-To: \"powertop@lists.01.org\"\n"
+"POT-Creation-Date: 2022-09-29 04:45-0700\n"
+"PO-Revision-Date: 2013-11-05 08:40+0000\n"
+"Last-Translator: Margie Foster <margie@linux.intel.com>\n"
+"Language-Team: Chinese (Taiwan) (http://www.transifex.com/projects/p/"
+"PowerTOP/language/zh_TW/)\n"
+"Language: zh_TW\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: src/calibrate/calibrate.cpp:238
+#, c-format
+msgid "Cannot create temp file\n"
+msgstr "無法建立暫存檔案\n"
+
+#: src/calibrate/calibrate.cpp:258
+#, c-format
+msgid "Calibrating: CPU usage on %i threads\n"
+msgstr "校正: CPU 使用量於 %i 執行緒\n"
+
+#: src/calibrate/calibrate.cpp:273
+#, c-format
+msgid "Calibrating: CPU wakeup power consumption\n"
+msgstr "校正: CPU 喚醒電源使用量\n"
+
+#: src/calibrate/calibrate.cpp:290
+#, c-format
+msgid "Calibrating USB devices\n"
+msgstr "校正 USB 設備\n"
+
+#: src/calibrate/calibrate.cpp:292 src/calibrate/calibrate.cpp:309
+#: src/calibrate/calibrate.cpp:317 src/calibrate/calibrate.cpp:334
+#, c-format
+msgid ".... device %s \n"
+msgstr ".... 裝置 %s \n"
+
+#: src/calibrate/calibrate.cpp:307
+#, c-format
+msgid "Calibrating radio devices\n"
+msgstr "校正無線電設備\n"
+
+#: src/calibrate/calibrate.cpp:331
+#, c-format
+msgid "Calibrating backlight\n"
+msgstr "校正螢幕背光\n"
+
+#: src/calibrate/calibrate.cpp:355 src/calibrate/calibrate.cpp:365
+#, c-format
+msgid "Calibrating idle\n"
+msgstr "校正閒置\n"
+
+#: src/calibrate/calibrate.cpp:378
+#, c-format
+msgid "Calibrating: disk usage \n"
+msgstr "校正: 磁碟使用\n"
+
+#: src/calibrate/calibrate.cpp:403
+msgid "Starting PowerTOP power estimate calibration \n"
+msgstr "開始 PowerTOP 電源估計校正 \n"
+
+#: src/calibrate/calibrate.cpp:426
+msgid "Finishing PowerTOP power estimate calibration \n"
+msgstr "完成 PowerTOP 電源估計校正 \n"
+
+#: src/calibrate/calibrate.cpp:430
+#, c-format
+msgid "Parameters after calibration:\n"
+msgstr "校正取得參數:\n"
+
+#: src/cpu/abstract_cpu.cpp:74
+msgid "Idle"
+msgstr ""
+
+#: src/cpu/abstract_cpu.cpp:76
+msgid "Turbo Mode"
+msgstr ""
+
+#: src/cpu/cpu_core.cpp:37
+#, fuzzy, c-format
+msgid " Core(HW)"
+msgstr " 核心"
+
+#: src/cpu/cpu_core.cpp:37
+#, fuzzy, c-format
+msgid " Core(OS)"
+msgstr " 核心"
+
+#: src/cpu/cpu_core.cpp:91 src/cpu/intel_cpus.cpp:367
+#, c-format
+msgid " Core"
+msgstr " 核心"
+
+#: src/cpu/cpu.cpp:85
+#, c-format
+msgid "cpu package %i"
+msgstr "cpu 代號 %i"
+
+#: src/cpu/cpu.cpp:86
+msgid "cpu package"
+msgstr "cpu 代號"
+
+#: src/cpu/cpu.cpp:89 src/cpu/cpu.cpp:96
+#, fuzzy, c-format
+msgid "package-%i"
+msgstr "代號 %i"
+
+#: src/cpu/cpu.cpp:90
+msgid "cpu rapl package"
+msgstr ""
+
+#: src/cpu/cpu.cpp:97
+msgid "dram rapl package"
+msgstr ""
+
+#: src/cpu/cpu.cpp:471
+msgid "Processor Idle State Report"
+msgstr ""
+
+#: src/cpu/cpu.cpp:535 src/cpu/cpu.cpp:761
+msgid "Package"
+msgstr "代號"
+
+#: src/cpu/cpu.cpp:572 src/cpu/cpu.cpp:783
+#, fuzzy, c-format
+msgid "Core %d"
+msgstr "核心 %i"
+
+#: src/cpu/cpu.cpp:579
+#, fuzzy, c-format
+msgid "GPU %d"
+msgstr "GPU %i"
+
+#: src/cpu/cpu.cpp:602
+#, fuzzy
+msgid "CPU"
+msgstr "CPU %i"
+
+#: src/cpu/cpu.cpp:684
+msgid "Processor Frequency Report"
+msgstr ""
+
+#: src/cpu/cpu.cpp:804
+#, fuzzy, c-format
+msgid "CPU %d"
+msgstr "CPU %i"
+
+#: src/cpu/cpu.cpp:1005
+#, c-format
+msgid "cpu_idle event returned no state?\n"
+msgstr "cpu_idle 事件沒有傳回狀態?\n"
+
+#: src/cpu/cpu.cpp:1020
+#, c-format
+msgid "power or cpu_frequency event returned no state?\n"
+msgstr "power 或 cpu_frequecny 事件沒有傳回狀態?\n"
+
+#: src/cpu/cpu_linux.cpp:79
+msgid "C0 polling"
+msgstr "C0 輪巡"
+
+#: src/cpu/cpu_linux.cpp:242
+#, fuzzy, c-format
+msgid " CPU(OS) %i"
+msgstr " CPU %i"
+
+#: src/cpu/cpu_linux.cpp:341 src/cpu/intel_cpus.cpp:733
+#, c-format
+msgid " CPU %i"
+msgstr " CPU %i"
+
+#: src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(HW)"
+msgstr ""
+
+#: src/cpu/cpu_package.cpp:47
+#, c-format
+msgid " Pkg(OS)"
+msgstr ""
+
+#: src/cpu/cpu_package.cpp:104 src/cpu/intel_cpus.cpp:498
+#, c-format
+msgid " Package"
+msgstr "代號"
+
+#: src/cpu/intel_cpus.cpp:152
+#, c-format
+msgid "read_msr cpu%d 0x%llx : "
+msgstr ""
+
+#: src/cpu/intel_cpus.cpp:656
+msgid "C0 active"
+msgstr "C0 運作中"
+
+#: src/cpu/intel_cpus.cpp:714
+#, c-format
+msgid "Average"
+msgstr ""
+
+#: src/cpu/intel_gpu.cpp:64
+#, fuzzy, c-format
+msgid " GPU "
+msgstr "GPU %i"
+
+#: src/devices/ahci.cpp:154
+#, c-format
+msgid "SATA link: %s"
+msgstr "SATA 連線: %s"
+
+#: src/devices/ahci.cpp:156
+#, c-format
+msgid "SATA disk: %s"
+msgstr "SATA 磁碟: %s"
+
+#: src/devices/ahci.cpp:374
+msgid "AHCI ALPM Residency Statistics - Not supported on this macine"
+msgstr ""
+
+#: src/devices/ahci.cpp:389
+msgid "Link"
+msgstr ""
+
+#: src/devices/ahci.cpp:390
+#, fuzzy
+msgid "Active"
+msgstr "C0 運作中"
+
+#: src/devices/ahci.cpp:391
+msgid "Partial"
+msgstr ""
+
+#: src/devices/ahci.cpp:392
+msgid "Slumber"
+msgstr ""
+
+#: src/devices/ahci.cpp:393
+msgid "Devslp"
+msgstr ""
+
+#: src/devices/ahci.cpp:399
+msgid "AHCI ALPM Residency Statistics"
+msgstr ""
+
+#: src/devices/alsa.cpp:77
+#, c-format
+msgid "Audio codec %s: %s (%s)"
+msgstr "音效設備 %s: %s (%s)"
+
+#: src/devices/alsa.cpp:79 src/devices/alsa.cpp:81
+#, c-format
+msgid "Audio codec %s: %s"
+msgstr "音效設備 %s: %s"
+
+#: src/devices/devfreq.cpp:260
+#, fuzzy
+msgid "Device Freq stats"
+msgstr "設備統計"
+
+#: src/devices/devfreq.cpp:278
+msgid " Devfreq is not enabled"
+msgstr ""
+
+#: src/devices/devfreq.cpp:283
+msgid " No devfreq devices available"
+msgstr ""
+
+#: src/devices/device.cpp:172 src/process/do_process.cpp:831
+#, c-format
+msgid "The battery reports a discharge rate of %sW\n"
+msgstr "電池回報放電速率為 %sW\n"
+
+#: src/devices/device.cpp:174 src/process/do_process.cpp:833
+#, c-format
+msgid "The energy consumed was %sJ\n"
+msgstr ""
+
+#: src/devices/device.cpp:180
+#, c-format
+msgid "System baseline power is estimated at %sW\n"
+msgstr "預期系統基礎用電量為 %sW\n"
+
+#: src/devices/device.cpp:187
+msgid "Power est. Usage Device name\n"
+msgstr "電源預估 使用量 設備名稱\n"
+
+#: src/devices/device.cpp:189
+msgid " Usage Device name\n"
+msgstr " 使用量 設備名稱\n"
+
+#: src/devices/device.cpp:256
+#, fuzzy
+msgid "The battery reports a discharge rate of: "
+msgstr "電池回報放電速率為 %sW\n"
+
+#: src/devices/device.cpp:261
+msgid "The energy consumed was : "
+msgstr ""
+
+#: src/devices/device.cpp:268
+#, fuzzy
+msgid "The system baseline power is estimated at: "
+msgstr "預期系統基礎用電量為 %sW\n"
+
+#: src/devices/device.cpp:277 src/process/do_process.cpp:850
+#: src/process/do_process.cpp:852 src/process/do_process.cpp:926
+#: src/process/do_process.cpp:1077
+msgid "Usage"
+msgstr "用法"
+
+#: src/devices/device.cpp:278
+#, fuzzy
+msgid "Device Name"
+msgstr "設備統計"
+
+#: src/devices/device.cpp:280 src/process/do_process.cpp:935
+#: src/process/do_process.cpp:1082
+msgid "PW Estimate"
+msgstr ""
+
+#: src/devices/device.cpp:317
+msgid "Device Power Report"
+msgstr ""
+
+#: src/devices/network.cpp:177
+#, c-format
+msgid "Network interface: %s (%s)"
+msgstr "網路介面卡: %s (%s)"
+
+#: src/devices/rfkill.cpp:65 src/devices/rfkill.cpp:69
+#, c-format
+msgid "Radio device: %s"
+msgstr "無線電設備: %s"
+
+#: src/devices/runtime_pm.cpp:216
+#, c-format
+msgid "I2C %s (%s): %s"
+msgstr ""
+
+#: src/devices/runtime_pm.cpp:216 src/tuning/tuningi2c.cpp:57
+#: src/tuning/tuningi2c.cpp:59
+msgid "Adapter"
+msgstr ""
+
+#: src/devices/runtime_pm.cpp:216 src/devlist.cpp:331
+#: src/tuning/tuningi2c.cpp:57 src/tuning/tuningi2c.cpp:59
+#, fuzzy
+msgid "Device"
+msgstr "設備統計"
+
+#: src/devices/runtime_pm.cpp:241
+#, c-format
+msgid "PCI Device: %s"
+msgstr "PCI 設備: %s"
+
+#: src/devices/usb.cpp:51 src/devices/usb.cpp:96 src/devices/usb.cpp:98
+#, c-format
+msgid "USB device: %s"
+msgstr "USB 設備: %s"
+
+#: src/devices/usb.cpp:94
+#, c-format
+msgid "USB device: %s (%s)"
+msgstr "USB 設備: %s (%s)"
+
+#: src/devlist.cpp:330
+msgid "Process"
+msgstr ""
+
+#: src/devlist.cpp:347
+msgid "Process Device Activity"
+msgstr ""
+
+#: src/display.cpp:70
+msgid "Overview"
+msgstr "總覽"
+
+#: src/display.cpp:71
+msgid "Idle stats"
+msgstr "閒置統計"
+
+#: src/display.cpp:72
+msgid "Frequency stats"
+msgstr "頻率統計"
+
+#: src/display.cpp:73
+msgid "Device stats"
+msgstr "設備統計"
+
+#: src/display.cpp:131
+msgid "Exit"
+msgstr "離開"
+
+#: src/display.cpp:132
+msgid "Navigate"
+msgstr ""
+
+#: src/lib.cpp:288
+#, c-format
+msgid "%7sW"
+msgstr "%7sW"
+
+#: src/lib.cpp:291
+#, c-format
+msgid " 0 mW"
+msgstr " 0 mW"
+
+#: src/lib.cpp:410
+msgid "PS/2 Touchpad / Keyboard / Mouse"
+msgstr "PS/2 觸控板 / 鍵盤 / 滑鼠"
+
+#: src/lib.cpp:411
+msgid "SATA controller"
+msgstr "SATA 控制器"
+
+#: src/lib.cpp:412
+msgid "Intel built in USB hub"
+msgstr "Intel 內建 USB 集線器"
+
+#: src/lib.cpp:467
+#, c-format
+msgid "glob returned GLOB_NOSPACE\n"
+msgstr ""
+
+#: src/lib.cpp:471
+#, c-format
+msgid "glob returned GLOB_ABORTED\n"
+msgstr ""
+
+#: src/lib.cpp:475
+#, c-format
+msgid "glob returned GLOB_NOMATCH\n"
+msgstr ""
+
+#: src/lib.cpp:513 src/lib.cpp:549
+#, c-format
+msgid ""
+"Model-specific registers (MSR)\t\t\t not found (try enabling "
+"CONFIG_X86_MSR).\n"
+msgstr ""
+
+#: src/main.cpp:104
+#, fuzzy, c-format
+msgid "PowerTOP version "
+msgstr "PowerTop 版本"
+
+#: src/main.cpp:110
+msgid "Set refresh time out"
+msgstr "設定更新週期"
+
+#: src/main.cpp:123
+msgid "Usage: powertop [OPTIONS]"
+msgstr "用法: powertop [選項]"
+
+#: src/main.cpp:124
+msgid "sets all tunable options to their GOOD setting"
+msgstr ""
+
+#: src/main.cpp:125
+msgid "runs powertop in calibration mode"
+msgstr "以校正模式執行 powertop"
+
+#: src/main.cpp:126 src/main.cpp:129
+msgid "[=filename]"
+msgstr ""
+
+#: src/main.cpp:126
+msgid "generate a csv report"
+msgstr "產生 csv 報告"
+
+#: src/main.cpp:127
+msgid "run in \"debug\" mode"
+msgstr "以 \"debug\" 模式執行"
+
+#: src/main.cpp:128
+msgid "[=devnode]"
+msgstr "[= 設備節點]"
+
+#: src/main.cpp:128
+msgid "uses an Extech Power Analyzer for measurements"
+msgstr "使用 Extech 電源分析儀進行量測"
+
+#: src/main.cpp:129
+msgid "generate a html report"
+msgstr "產生 html 報告"
+
+#: src/main.cpp:130
+msgid "[=iterations] number of times to run each test"
+msgstr "[=iterations] 每次檢驗進行量測次數"
+
+#: src/main.cpp:131
+msgid "suppress stderr output"
+msgstr "關閉標準錯誤輸出"
+
+#: src/main.cpp:132 src/main.cpp:133
+msgid "[=seconds]"
+msgstr "[= 秒]"
+
+#: src/main.cpp:132
+msgid "interval for power consumption measurement"
+msgstr ""
+
+#: src/main.cpp:133
+msgid "generate a report for 'x' seconds"
+msgstr "產生蒐集資料 'x' 秒鐘的報告"
+
+#: src/main.cpp:134
+msgid "[=workload]"
+msgstr "[=工作負載]"
+
+#: src/main.cpp:134
+msgid "file to execute for workload"
+msgstr "工作負載要執行的檔案"
+
+#: src/main.cpp:135
+msgid "print version information"
+msgstr "顯示版本資訊"
+
+#: src/main.cpp:136
+msgid "print this help menu"
+msgstr "顯示此輔助說明選單"
+
+#: src/main.cpp:138
+#, fuzzy
+msgid "For more help please refer to the 'man 8 powertop'"
+msgstr "更多的輔助說明請參閱 README"
+
+#: src/main.cpp:233
+#, c-format
+msgid "Unknown issue running workload!\n"
+msgstr "執行工作負載發生未知問題!\n"
+
+#: src/main.cpp:290
+msgid "PowerTOP is out of memory. PowerTOP is Aborting"
+msgstr "PowerTOP 已耗盡記憶體,退出中。"
+
+#: src/main.cpp:298
+#, c-format
+msgid "Preparing to take measurements\n"
+msgstr "量測準備中\n"
+
+#: src/main.cpp:303
+#, c-format
+msgid "Taking %d measurement(s) for a duration of %d second(s) each.\n"
+msgstr "測量 %d 次於每 %d 秒。\n"
+
+#: src/main.cpp:305
+#, c-format
+msgid "Measuring workload %s.\n"
+msgstr "量測工作負載 %s 。\n"
+
+#: src/main.cpp:330
+#, c-format
+msgid "PowerTOP "
+msgstr "PowerTOP "
+
+#: src/main.cpp:331 src/main.cpp:381
+#, c-format
+msgid "exiting...\n"
+msgstr "離開中...\n"
+
+#: src/main.cpp:365
+#, c-format
+msgid "modprobe cpufreq_stats failed\n"
+msgstr ""
+
+#: src/main.cpp:368
+#, fuzzy, c-format
+msgid "modprobe msr failed\n"
+msgstr "進入安靜模式失敗!\n"
+
+#: src/main.cpp:380 src/main.cpp:384
+#, c-format
+msgid "Failed to mount debugfs!\n"
+msgstr "debugfs 掛載失敗!\n"
+
+#: src/main.cpp:385
+#, c-format
+msgid "Should still be able to auto tune...\n"
+msgstr ""
+
+#: src/main.cpp:467
+#, c-format
+msgid "Invalid CSV filename\n"
+msgstr ""
+
+#: src/main.cpp:483
+#, c-format
+msgid "Invalid HTML filename\n"
+msgstr ""
+
+#: src/main.cpp:492
+#, fuzzy, c-format
+msgid "Quiet mode failed!\n"
+msgstr "進入安靜模式失敗!\n"
+
+#: src/main.cpp:560
+msgid "Leaving PowerTOP"
+msgstr "離開 PowerTOP"
+
+#: src/parameters/persistent.cpp:46 src/parameters/persistent.cpp:155
+msgid "Cannot save to file"
+msgstr "無法儲存檔案"
+
+#: src/parameters/persistent.cpp:89 src/parameters/persistent.cpp:180
+msgid "Cannot load from file"
+msgstr "無法讀取檔案"
+
+#: src/parameters/persistent.cpp:138
+#, c-format
+msgid "Loaded %i prior measurements\n"
+msgstr "已載入 %i 筆先前量測數據\n"
+
+#: src/parameters/persistent.cpp:181
+msgid ""
+"File will be loaded after taking minimum number of measurement(s) with "
+"battery only \n"
+msgstr ""
+
+#: src/perf/perf.cpp:115
+#, c-format
+msgid ""
+"Too many open files, please increase the limit of open file descriptors.\n"
+msgstr ""
+
+#: src/perf/perf.cpp:117
+#, c-format
+msgid "PowerTOP %s needs the kernel to support the 'perf' subsystem\n"
+msgstr "PowerTOP %s 需要 Linux 核心 'perf' 子系統支援\n"
+
+#: src/perf/perf.cpp:118
+#, c-format
+msgid "as well as support for trace points in the kernel:\n"
+msgstr "以及 Linux 核心中斷點 (trace point) 支援:\n"
+
+#: src/process/do_process.cpp:819
+#, c-format
+msgid ""
+"Estimated power: %5.1f Measured power: %5.1f Sum: %5.1f\n"
+"\n"
+msgstr ""
+"預估用電量: %5.1f 實測用電量: %5.1f 總計: %5.1f\n"
+"\n"
+
+#: src/process/do_process.cpp:838
+#, c-format
+msgid "The estimated remaining time is %i hours, %i minutes\n"
+msgstr "估計剩餘時間為 %i 小時 %i 分鐘\n"
+
+#: src/process/do_process.cpp:846
+msgid "Summary"
+msgstr "總覽"
+
+#: src/process/do_process.cpp:846
+msgid "wakeups/second"
+msgstr "喚醒 / 秒"
+
+#: src/process/do_process.cpp:846
+msgid "GPU ops/seconds"
+msgstr "GPU 指令 / 秒"
+
+#: src/process/do_process.cpp:846
+msgid "VFS ops/sec and"
+msgstr "VFS 指令 / 秒 以及"
+
+#: src/process/do_process.cpp:846
+msgid "CPU use"
+msgstr "CPU 用量"
+
+#: src/process/do_process.cpp:850
+msgid "Power est."
+msgstr "電源預計"
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:1078
+msgid "Events/s"
+msgstr "事件 / 秒"
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:931 src/process/do_process.cpp:1079
+msgid "Category"
+msgstr "分類"
+
+#: src/process/do_process.cpp:850 src/process/do_process.cpp:852
+#: src/process/do_process.cpp:932 src/process/do_process.cpp:1080
+#: src/tuning/tuning.cpp:242 src/tuning/tuning.cpp:270
+#: src/tuning/tuning.cpp:295 src/wakeup/waketab.cpp:155
+msgid "Description"
+msgstr "描述"
+
+#: src/process/do_process.cpp:927
+msgid "Wakeups/s"
+msgstr "喚醒 / 秒"
+
+#: src/process/do_process.cpp:928
+msgid "GPU ops/s"
+msgstr "GPU 指令 / 秒"
+
+#: src/process/do_process.cpp:929
+msgid "Disk IO/s"
+msgstr "磁碟 IO / 秒"
+
+#: src/process/do_process.cpp:930
+msgid "GFX Wakeups/s"
+msgstr "GFX 喚醒 / 秒"
+
+#: src/process/do_process.cpp:1017
+msgid "Overview of Software Power Consumers"
+msgstr "軟體耗電量大戶總覽"
+
+#: src/process/do_process.cpp:1057
+msgid "Target:"
+msgstr ""
+
+#: src/process/do_process.cpp:1058
+msgid "1 units/s"
+msgstr ""
+
+#: src/process/do_process.cpp:1059
+msgid "System: "
+msgstr ""
+
+#: src/process/do_process.cpp:1061
+#, fuzzy
+msgid " wakeup/s"
+msgstr "喚醒 / 秒"
+
+#: src/process/do_process.cpp:1062
+msgid "CPU: "
+msgstr ""
+
+#: src/process/do_process.cpp:1064
+#, fuzzy, c-format
+msgid "% usage"
+msgstr "用法"
+
+#: src/process/do_process.cpp:1065
+msgid "GPU:"
+msgstr ""
+
+#: src/process/do_process.cpp:1067 src/process/do_process.cpp:1073
+#, fuzzy
+msgid " ops/s"
+msgstr "GPU 指令 / 秒"
+
+#: src/process/do_process.cpp:1068
+msgid "GFX:"
+msgstr ""
+
+#: src/process/do_process.cpp:1070
+#, fuzzy
+msgid " wakeups/s"
+msgstr "喚醒 / 秒"
+
+#: src/process/do_process.cpp:1071
+msgid "VFS:"
+msgstr ""
+
+#: src/process/do_process.cpp:1139
+#, fuzzy
+msgid "Top 10 Power Consumers"
+msgstr "軟體耗電量大戶總覽"
+
+#: src/report/report.cpp:122
+#, fuzzy
+msgid "PowerTOP Version"
+msgstr "PowerTop 版本"
+
+#: src/report/report.cpp:131
+#, fuzzy
+msgid "Kernel Version"
+msgstr "PowerTop 版本"
+
+#: src/report/report.cpp:135
+msgid "System Name"
+msgstr ""
+
+#: src/report/report.cpp:142
+msgid "CPU Information"
+msgstr ""
+
+#: src/report/report.cpp:154
+msgid "OS Information"
+msgstr ""
+
+#: src/report/report.cpp:161
+#, fuzzy
+msgid "System Information"
+msgstr "顯示版本資訊"
+
+#: src/report/report.cpp:195
+#, fuzzy, c-format
+msgid "Cannot open output file %s (%s)\n"
+msgstr "無法建立暫存檔案\n"
+
+#: src/report/report.cpp:211
+#, c-format
+msgid "PowerTOP outputting using base filename %s\n"
+msgstr ""
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:49
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45
+msgid "Good"
+msgstr "好"
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:50
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45
+msgid "Bad"
+msgstr "壞"
+
+#: src/tuning/bluetooth.cpp:46 src/tuning/ethernet.cpp:50
+#: src/tuning/runtime.cpp:42 src/tuning/tunable.cpp:51
+#: src/tuning/tuningi2c.cpp:35 src/tuning/tuningsysfs.cpp:45
+#: src/tuning/tuningusb.cpp:39 src/tuning/wifi.cpp:45 src/wakeup/wakeup.cpp:50
+msgid "Unknown"
+msgstr "未知"
+
+#: src/tuning/bluetooth.cpp:48
+#, c-format
+msgid "Bluetooth device interface status"
+msgstr "藍牙設備介面狀態"
+
+#: src/tuning/ethernet.cpp:54 src/wakeup/wakeup_ethernet.cpp:51
+#, c-format
+msgid "Wake-on-lan status for device %s"
+msgstr "網路喚醒啟用狀態於設備 %s"
+
+#: src/tuning/runtime.cpp:48
+#, c-format
+msgid "Runtime PM for %s device %s"
+msgstr "執行時期省電 %s 設備 %s"
+
+#: src/tuning/runtime.cpp:50
+#, c-format
+msgid "%s device %s has no runtime power management"
+msgstr "%s 設備 %s 沒有執行時期電源管理功能"
+
+#: src/tuning/runtime.cpp:74
+#, c-format
+msgid "PCI Device %s has no runtime power management"
+msgstr "PCI 設備 %s 沒有執行時期電源管理功能"
+
+#: src/tuning/runtime.cpp:76
+#, c-format
+msgid "Runtime PM for PCI Device %s"
+msgstr "PCI 設備 %s 電源管理"
+
+#: src/tuning/runtime.cpp:80
+#, fuzzy, c-format
+msgid "Runtime PM for port %s of PCI device: %s"
+msgstr "執行時期省電 %s 設備 %s"
+
+#: src/tuning/runtime.cpp:83
+#, fuzzy, c-format
+msgid "Runtime PM for disk %s"
+msgstr "執行時期省電 %s 設備 %s"
+
+#: src/tuning/tuning.cpp:62
+msgid "Enable Audio codec power management"
+msgstr "啟用音效設備電源管理功能"
+
+#: src/tuning/tuning.cpp:63
+msgid "NMI watchdog should be turned off"
+msgstr "NMI watchdog 監控應該關閉"
+
+#: src/tuning/tuning.cpp:64
+msgid "Power Aware CPU scheduler"
+msgstr "省電型 CPU 排程器 "
+
+#: src/tuning/tuning.cpp:65
+msgid "VM writeback timeout"
+msgstr "VM 回寫延時"
+
+#: src/tuning/tuning.cpp:81
+msgid "Tunables"
+msgstr "可調選項"
+
+#: src/tuning/tuning.cpp:81
+msgid " <ESC> Exit | <Enter> Toggle tunable | <r> Window refresh"
+msgstr " <ESC> 離開 | <Enter> 切換選項開關 | <r> 更新視窗內容"
+
+#: src/tuning/tuning.cpp:243 src/wakeup/waketab.cpp:156
+msgid "Script"
+msgstr ""
+
+#: src/tuning/tuning.cpp:257
+msgid "Software Settings in Need of Tuning"
+msgstr ""
+
+#: src/tuning/tuning.cpp:276
+msgid "Untunable Software Issues"
+msgstr ""
+
+#: src/tuning/tuning.cpp:307
+msgid "Optimal Tuned Software Settings"
+msgstr ""
+
+#: src/tuning/tuningi2c.cpp:57
+#, fuzzy, c-format
+msgid "Runtime PM for I2C %s %s (%s)"
+msgstr "執行時期省電 %s 設備 %s"
+
+#: src/tuning/tuningi2c.cpp:59
+#, fuzzy, c-format
+msgid "I2C %s %s has no runtime power management"
+msgstr "%s 設備 %s 沒有執行時期電源管理功能"
+
+#: src/tuning/tuningsysfs.cpp:123
+#, fuzzy, c-format
+msgid "Enable SATA link power management for %s"
+msgstr "啟用 %s 的 SATA 連線電源管理"
+
+#: src/tuning/tuningusb.cpp:54
+#, c-format
+msgid "Autosuspend for unknown USB device %s (%s:%s)"
+msgstr "自動閒置於未知的 USB 設備 %s (%s:%s)"
+
+#: src/tuning/tuningusb.cpp:71 src/tuning/tuningusb.cpp:73
+#: src/tuning/tuningusb.cpp:75
+#, c-format
+msgid "Autosuspend for USB device %s [%s]"
+msgstr "自動閒置於 USB 設備 %s [%s]"
+
+#: src/tuning/wifi.cpp:48
+#, c-format
+msgid "Wireless Power Saving for interface %s"
+msgstr "無線網路省電狀態於設備 %s"
+
+#: src/wakeup/waketab.cpp:42
+#, fuzzy
+msgid "WakeUp"
+msgstr "喚醒 / 秒"
+
+#: src/wakeup/waketab.cpp:42
+#, fuzzy
+msgid " <ESC> Exit | <Enter> Toggle wakeup | <r> Window refresh"
+msgstr " <ESC> 離開 | <Enter> 切換選項開關 | <r> 更新視窗內容"
+
+#: src/wakeup/waketab.cpp:170
+#, fuzzy
+msgid "Wake status of the devices"
+msgstr "網路喚醒啟用狀態於設備 %s"
+
+#: src/wakeup/wakeup.cpp:48 src/wakeup/wakeup_ethernet.cpp:47
+#: src/wakeup/wakeup_usb.cpp:47
+#, fuzzy
+msgid "Enabled"
+msgstr "可調選項"
+
+#: src/wakeup/wakeup.cpp:49 src/wakeup/wakeup_ethernet.cpp:47
+#: src/wakeup/wakeup_usb.cpp:47
+msgid "Disabled"
+msgstr ""
+
+#: src/wakeup/wakeup_usb.cpp:51
+#, fuzzy, c-format
+msgid "Wake status for USB device %s"
+msgstr "網路喚醒啟用狀態於設備 %s"
+
+#~ msgid "Actual"
+#~ msgstr "實際"
+
+#, fuzzy
+#~ msgid "I2C Device: %s"
+#~ msgstr "PCI 設備: %s"
+
+#~ msgid "[=FILENAME]"
+#~ msgstr "[= 檔案名稱]"
+
+#~ msgid "Using 'ondemand' cpufreq governor"
+#~ msgstr "使用 'ondemand' cpu 排程器"
+
+#~ msgid "Power Consumption Summary"
+#~ msgstr "電源使用量總覽"
+
+#~ msgid "GPU ops/second"
+#~ msgstr "GPU 指令 / 秒"
+
+#~ msgid "VFS ops/sec"
+#~ msgstr "VFS 指令 / 秒"
+
+#~ msgid "GFX wakes/sec and"
+#~ msgstr "GFX 喚醒 / 秒 以及"
diff --git a/powertop.service b/powertop.service
new file mode 100644
index 0000000..5a44ca2
--- /dev/null
+++ b/powertop.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Extend the battery life of laptop
+
+[Service]
+Type=oneshot
+ExecStart=/usr/sbin/powertop --auto-tune
+
+[Install]
+WantedBy=multi-user.target sleep.target
diff --git a/scripts/bash-completion/Makefile.am b/scripts/bash-completion/Makefile.am
new file mode 100644
index 0000000..45073bd
--- /dev/null
+++ b/scripts/bash-completion/Makefile.am
@@ -0,0 +1,2 @@
+bashcompletiondir = @bashcompletiondir@
+dist_bashcompletion_DATA = powertop
diff --git a/scripts/bash-completion/powertop b/scripts/bash-completion/powertop
new file mode 100644
index 0000000..03d238e
--- /dev/null
+++ b/scripts/bash-completion/powertop
@@ -0,0 +1,43 @@
+#!/bin/bash
+#
+# Powertop tab completion for bash.
+#
+# This is part of PowerTOP
+#
+# This program file 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; version 2 of the License.
+#
+# This program 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 in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+# or just google for it.
+
+_powertop()
+{
+ local cur prev words cword split
+ _init_completion -s || return
+
+ case $prev in
+ '-C'|'--csv'|'--extech'|'-r'|'--html'|'-w'|'--workload')
+ _filedir
+ return 0
+ ;;
+ esac
+
+ local all_long_options=$( _parse_help "$1" )
+
+ COMPREPLY=( $( compgen -W "${all_long_options}" -- "$cur" ) )
+
+ return 0
+}
+
+# load the completion
+complete -F _powertop powertop
diff --git a/scripts/regenerate-potfiles-in b/scripts/regenerate-potfiles-in
new file mode 100644
index 0000000..a178fa0
--- /dev/null
+++ b/scripts/regenerate-potfiles-in
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+echo "INFO: checking for git ..."
+git --version > /dev/null 2>&1 || exit 1
+
+echo "INFO: priming ./POTFILES.in.new ..."
+touch POTFILES.in.new || exit 2
+echo "# List of source files which contain translatable strings." > POTFILES.in.new || exit 3
+echo "" >> POTFILES.in.new || exit 4
+
+echo "INFO: populating ./POTFILES.in.new ..."
+git grep -l -e "__(" -e "_(" | sort >> POTFILES.in.new || exit 5
+
+echo "INFO: contents of ./POTFILES.in.new ..."
+cat POTFILES.in.new
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..6b523f6
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,176 @@
+AUTOMAKE_OPTIONS = subdir-objects
+
+sbin_PROGRAMS = powertop
+nodist_powertop_SOURCES = css.h
+
+powertop_SOURCES = \
+ css.h \
+ devlist.cpp \
+ devlist.h \
+ display.cpp \
+ display.h \
+ lib.cpp \
+ lib.h \
+ main.cpp \
+ powertop.css \
+ \
+ calibrate/calibrate.cpp \
+ calibrate/calibrate.h \
+ cpu/abstract_cpu.cpp \
+ cpu/cpu.cpp \
+ cpu/cpu.h \
+ cpu/cpu_core.cpp \
+ cpu/cpu_linux.cpp \
+ cpu/cpu_package.cpp \
+ cpu/cpu_rapl_device.cpp \
+ cpu/cpu_rapl_device.h \
+ cpu/cpudevice.cpp \
+ cpu/cpudevice.h \
+ cpu/dram_rapl_device.cpp \
+ cpu/dram_rapl_device.h \
+ cpu/intel_cpus.cpp \
+ cpu/intel_cpus.h \
+ cpu/intel_gpu.cpp \
+ cpu/rapl/rapl_interface.cpp \
+ cpu/rapl/rapl_interface.h \
+ devices/ahci.cpp \
+ devices/ahci.h \
+ devices/alsa.cpp \
+ devices/alsa.h \
+ devices/backlight.cpp \
+ devices/backlight.h \
+ devices/devfreq.cpp \
+ devices/devfreq.h \
+ devices/device.cpp \
+ devices/device.h \
+ devices/gpu_rapl_device.cpp \
+ devices/gpu_rapl_device.h \
+ devices/i915-gpu.cpp \
+ devices/i915-gpu.h \
+ devices/network.cpp \
+ devices/network.h \
+ devices/rfkill.cpp \
+ devices/rfkill.h \
+ devices/runtime_pm.cpp \
+ devices/runtime_pm.h \
+ devices/thinkpad-fan.cpp \
+ devices/thinkpad-fan.h \
+ devices/thinkpad-light.cpp \
+ devices/thinkpad-light.h \
+ devices/usb.cpp \
+ devices/usb.h \
+ measurement/acpi.cpp \
+ measurement/acpi.h \
+ measurement/extech.cpp \
+ measurement/extech.h \
+ measurement/measurement.cpp \
+ measurement/measurement.h \
+ measurement/sysfs.cpp \
+ measurement/sysfs.h \
+ measurement/opal-sensors.cpp \
+ measurement/opal-sensors.h \
+ parameters/learn.cpp \
+ parameters/parameters.cpp \
+ parameters/parameters.h \
+ parameters/persistent.cpp \
+ perf/perf.cpp \
+ perf/perf.h \
+ perf/perf_bundle.cpp \
+ perf/perf_bundle.h \
+ perf/perf_event.h \
+ process/do_process.cpp \
+ process/interrupt.cpp \
+ process/interrupt.h \
+ process/powerconsumer.cpp \
+ process/powerconsumer.h \
+ process/process.cpp \
+ process/process.h \
+ process/processdevice.cpp \
+ process/processdevice.h \
+ process/timer.cpp \
+ process/timer.h \
+ process/work.cpp \
+ process/work.h \
+ report/report-data-html.cpp \
+ report/report-data-html.h \
+ report/report-formatter-base.cpp \
+ report/report-formatter-base.h \
+ report/report-formatter-csv.cpp \
+ report/report-formatter-csv.h \
+ report/report-formatter-html.cpp \
+ report/report-formatter-html.h \
+ report/report-formatter.h \
+ report/report-maker.cpp \
+ report/report-maker.h \
+ report/report.cpp \
+ report/report.h \
+ tuning/bluetooth.cpp \
+ tuning/bluetooth.h \
+ tuning/ethernet.cpp \
+ tuning/ethernet.h \
+ tuning/iw.c \
+ tuning/iw.h \
+ tuning/nl80211.h \
+ tuning/runtime.cpp \
+ tuning/runtime.h \
+ tuning/tunable.cpp \
+ tuning/tunable.h \
+ tuning/tuning.cpp \
+ tuning/tuning.h \
+ tuning/tuningsysfs.cpp \
+ tuning/tuningsysfs.h \
+ tuning/tuningusb.cpp \
+ tuning/tuningusb.h \
+ tuning/tuningi2c.cpp \
+ tuning/tuningi2c.h \
+ tuning/wifi.cpp \
+ tuning/wifi.h \
+ wakeup/wakeup.cpp \
+ wakeup/waketab.cpp \
+ wakeup/wakeup_ethernet.cpp \
+ wakeup/wakeup_usb.cpp \
+ wakeup/wakeup_usb.h \
+ wakeup/wakeup.h \
+ wakeup/wakeup_ethernet.h
+
+powertop_CXXFLAGS = \
+ -Wall \
+ -Wformat \
+ -Wshadow \
+ -fno-omit-frame-pointer \
+ -fstack-protector \
+ $(GLIB2_CFLAGS) \
+ $(LIBNL_CFLAGS) \
+ $(NCURSES_CFLAGS) \
+ $(PCIUTILS_CFLAGS) \
+ $(PTHREAD_CFLAGS)
+
+
+powertop_CPPFLAGS = \
+ -DLOCALEDIR=\"$(localedir)\" \
+ $(GLIB2_CFLAGS) \
+ $(LIBNL_CFLAGS) \
+ $(LIBZ_CFLAGS) \
+ $(NCURSES_CFLAGS) \
+ $(PCIUTILS_CFLAGS) \
+ $(PTHREAD_CFLAGS)
+
+powertop_LDADD = \
+ ../traceevent/libtraceevnet.la
+
+AM_LDFLAGS = \
+ $(LIBNL_LIBS) \
+ $(LIBS) \
+ $(LIBZ_LIBS) \
+ $(NCURSES_LIBS) \
+ $(PCIUTILS_LIBS) \
+ $(PTHREAD_LIBS) \
+ $(RESOLV_LIBS)
+
+BUILT_SOURCES = css.h
+CLEANFILES = css.h
+
+css.h: powertop.css
+ $(SHELL) ${srcdir}/csstoh.sh ${srcdir}/powertop.css css.h
+
+EXTRA_DIST = ${srcdir}/csstoh.sh
diff --git a/src/calibrate/calibrate.cpp b/src/calibrate/calibrate.cpp
new file mode 100644
index 0000000..745d544
--- /dev/null
+++ b/src/calibrate/calibrate.cpp
@@ -0,0 +1,435 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <iostream>
+#include <fstream>
+#include <algorithm>
+
+#include "calibrate.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <math.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <limits.h>
+
+#include "../parameters/parameters.h"
+extern "C" {
+#include "../tuning/iw.h"
+}
+
+#include <map>
+#include <vector>
+#include <string>
+
+using namespace std;
+
+
+static vector<string> usb_devices;
+static vector<string> rfkill_devices;
+static vector<string> backlight_devices;
+static vector<string> scsi_link_devices;
+static int blmax;
+
+static map<string, string> saved_sysfs;
+
+
+static volatile int stop_measurement;
+
+static int wireless_PS;
+
+
+static void save_sysfs(const char *filename)
+{
+ char line[4096];
+ ifstream file;
+
+ file.open(filename, ios::in);
+ if (!file)
+ return;
+ file.getline(line, 4096);
+ file.close();
+
+ saved_sysfs[filename] = line;
+}
+
+static void restore_all_sysfs(void)
+{
+ map<string, string>::iterator it;
+
+ for (it = saved_sysfs.begin(); it != saved_sysfs.end(); it++)
+ write_sysfs(it->first, it->second);
+
+ set_wifi_power_saving("wlan0", wireless_PS);
+}
+
+static void find_all_usb_callback(const char *d_name)
+{
+ char filename[PATH_MAX];
+ ifstream file;
+
+ snprintf(filename, sizeof(filename), "/sys/bus/usb/devices/%s/power/active_duration", d_name);
+ if (access(filename, R_OK) != 0)
+ return;
+
+ snprintf(filename, sizeof(filename), "/sys/bus/usb/devices/%s/power/idVendor", d_name);
+ file.open(filename, ios::in);
+ if (file) {
+ file.getline(filename, sizeof(filename));
+ file.close();
+ if (strcmp(filename, "1d6b") == 0)
+ return;
+ }
+
+ snprintf(filename, sizeof(filename), "/sys/bus/usb/devices/%s/power/control", d_name);
+ save_sysfs(filename);
+ usb_devices.push_back(filename);
+}
+
+static void find_all_usb(void)
+{
+ process_directory("/sys/bus/usb/devices/", find_all_usb_callback);
+}
+
+static void suspend_all_usb_devices(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < usb_devices.size(); i++)
+ write_sysfs(usb_devices[i], "auto\n");
+}
+
+static void find_all_rfkill_callback(const char *d_name)
+{
+ char filename[PATH_MAX];
+ snprintf(filename, sizeof(filename), "/sys/class/rfkill/%s/soft", d_name);
+ if (access(filename, R_OK) != 0)
+ return;
+ save_sysfs(filename);
+ rfkill_devices.push_back(filename);
+}
+
+static void find_all_rfkill(void)
+{
+ process_directory("/sys/class/rfkill/", find_all_rfkill_callback);
+}
+
+static void rfkill_all_radios(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < rfkill_devices.size(); i++)
+ write_sysfs(rfkill_devices[i], "1\n");
+}
+static void unrfkill_all_radios(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < rfkill_devices.size(); i++)
+ write_sysfs(rfkill_devices[i], "0\n");
+}
+
+static void find_backlight_callback(const char *d_name)
+{
+ char filename[PATH_MAX];
+ snprintf(filename, sizeof(filename), "/sys/class/backlight/%s/brightness", d_name);
+ if (access(filename, R_OK) != 0)
+ return;
+
+ save_sysfs(filename);
+ backlight_devices.push_back(filename);
+ snprintf(filename, sizeof(filename), "/sys/class/backlight/%s/max_brightness", d_name);
+ blmax = read_sysfs(filename);
+}
+
+static void find_backlight(void)
+{
+ process_directory("/sys/class/backlight/", find_backlight_callback);
+}
+
+static void lower_backlight(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < backlight_devices.size(); i++)
+ write_sysfs(backlight_devices[i], "0\n");
+}
+
+static void find_scsi_link_callback(const char *d_name)
+{
+ char filename[PATH_MAX];
+ snprintf(filename, sizeof(filename), "/sys/class/scsi_host/%s/link_power_management_policy", d_name);
+ if (access(filename, R_OK)!=0)
+ return;
+
+ save_sysfs(filename);
+ scsi_link_devices.push_back(filename);
+}
+
+static void find_scsi_link(void)
+{
+ process_directory("/sys/class/scsi_host/", find_scsi_link_callback);
+}
+
+static void set_scsi_link(const char *state)
+{
+ unsigned int i;
+
+ for (i = 0; i < scsi_link_devices.size(); i++)
+ write_sysfs(scsi_link_devices[i], state);
+}
+
+
+static void *burn_cpu(void *dummy)
+{
+ volatile double d = 1.1;
+
+ while (!stop_measurement) {
+ d = pow(d, 1.0001);
+ }
+ return NULL;
+}
+
+static void *burn_cpu_wakeups(void *dummy)
+{
+ struct timespec tm;
+
+ while (!stop_measurement) {
+ tm.tv_sec = 0;
+ tm.tv_nsec = (unsigned long)dummy;
+ nanosleep(&tm, NULL);
+ }
+ return NULL;
+}
+
+static void *burn_disk(void *dummy)
+{
+ int fd;
+ char buffer[64*1024];
+ char filename[256];
+
+ strcpy(filename ,"/tmp/powertop.XXXXXX");
+ fd = mkstemp(filename);
+
+ if (fd < 0) {
+ printf(_("Cannot create temp file\n"));
+ return NULL;
+ }
+
+ while (!stop_measurement) {
+ lseek(fd, 0, SEEK_SET);
+ if(write(fd, buffer, 64*1024) == -1)
+ printf("Error: %s\n", strerror(errno));
+ fdatasync(fd);
+ }
+ unlink(filename);
+ return NULL;
+}
+
+
+static void cpu_calibration(int threads)
+{
+ int i;
+ pthread_t thr;
+
+ printf(_("Calibrating: CPU usage on %i threads\n"), threads);
+
+ stop_measurement = 0;
+ for (i = 0; i < threads; i++)
+ pthread_create(&thr, NULL, burn_cpu, NULL);
+
+ one_measurement(15, 15, NULL);
+ stop_measurement = 1;
+ sleep(1);
+}
+
+static void wakeup_calibration(unsigned long interval)
+{
+ pthread_t thr;
+
+ printf(_("Calibrating: CPU wakeup power consumption\n"));
+
+ stop_measurement = 0;
+
+ pthread_create(&thr, NULL, burn_cpu_wakeups, (void *)interval);
+
+ one_measurement(15, 15, NULL);
+ stop_measurement = 1;
+ sleep(1);
+}
+
+static void usb_calibration(void)
+{
+ unsigned int i;
+
+ /* chances are one of the USB devices is bluetooth; unrfkill first */
+ unrfkill_all_radios();
+ printf(_("Calibrating USB devices\n"));
+ for (i = 0; i < usb_devices.size(); i++) {
+ printf(_(".... device %s \n"), usb_devices[i].c_str());
+ suspend_all_usb_devices();
+ write_sysfs(usb_devices[i], "on\n");
+ one_measurement(15, 15, NULL);
+ suspend_all_usb_devices();
+ sleep(3);
+ }
+ rfkill_all_radios();
+ sleep(4);
+}
+
+static void rfkill_calibration(void)
+{
+ unsigned int i;
+
+ printf(_("Calibrating radio devices\n"));
+ for (i = 0; i < rfkill_devices.size(); i++) {
+ printf(_(".... device %s \n"), rfkill_devices[i].c_str());
+ rfkill_all_radios();
+ write_sysfs(rfkill_devices[i], "0\n");
+ one_measurement(15, 15, NULL);
+ rfkill_all_radios();
+ sleep(3);
+ }
+ for (i = 0; i < rfkill_devices.size(); i++) {
+ printf(_(".... device %s \n"), rfkill_devices[i].c_str());
+ unrfkill_all_radios();
+ write_sysfs(rfkill_devices[i], "1\n");
+ one_measurement(15, 15, NULL);
+ unrfkill_all_radios();
+ sleep(3);
+ }
+ rfkill_all_radios();
+}
+
+static void backlight_calibration(void)
+{
+ unsigned int i;
+
+ printf(_("Calibrating backlight\n"));
+ for (i = 0; i < backlight_devices.size(); i++) {
+ char str[4096];
+ printf(_(".... device %s \n"), backlight_devices[i].c_str());
+ lower_backlight();
+ one_measurement(15, 15, NULL);
+ sprintf(str, "%i\n", blmax / 4);
+ write_sysfs(backlight_devices[i], str);
+ one_measurement(15, 15, NULL);
+
+ sprintf(str, "%i\n", blmax / 2);
+ write_sysfs(backlight_devices[i], str);
+ one_measurement(15, 15, NULL);
+
+ sprintf(str, "%i\n", 3 * blmax / 4 );
+ write_sysfs(backlight_devices[i], str);
+ one_measurement(15, 15, NULL);
+
+ sprintf(str, "%i\n", blmax);
+ write_sysfs(backlight_devices[i], str);
+ one_measurement(15, 15, NULL);
+ lower_backlight();
+ sleep(1);
+ }
+ printf(_("Calibrating idle\n"));
+ if(!system("DISPLAY=:0 /usr/bin/xset dpms force off"))
+ printf("System is not available\n");
+ one_measurement(15, 15, NULL);
+ if(!system("DISPLAY=:0 /usr/bin/xset dpms force on"))
+ printf("System is not available\n");
+}
+
+static void idle_calibration(void)
+{
+ printf(_("Calibrating idle\n"));
+ if(!system("DISPLAY=:0 /usr/bin/xset dpms force off"))
+ printf("System is not available\n");
+ one_measurement(15, 15, NULL);
+ if(!system("DISPLAY=:0 /usr/bin/xset dpms force on"))
+ printf("System is not available\n");
+}
+
+
+static void disk_calibration(void)
+{
+ pthread_t thr;
+
+ printf(_("Calibrating: disk usage \n"));
+
+ set_scsi_link("min_power");
+
+ stop_measurement = 0;
+ pthread_create(&thr, NULL, burn_disk, NULL);
+
+ one_measurement(15, 15, NULL);
+ stop_measurement = 1;
+ sleep(1);
+
+
+}
+
+
+void calibrate(void)
+{
+ find_all_usb();
+ find_all_rfkill();
+ find_backlight();
+ find_scsi_link();
+ wireless_PS = get_wifi_power_saving("wlan0");
+
+ save_sysfs("/sys/module/snd_hda_intel/parameters/power_save");
+
+ cout << _("Starting PowerTOP power estimate calibration \n");
+ suspend_all_usb_devices();
+ rfkill_all_radios();
+ lower_backlight();
+ set_wifi_power_saving("wlan0", 1);
+
+ sleep(4);
+
+
+ idle_calibration();
+ disk_calibration();
+ backlight_calibration();
+
+ write_sysfs("/sys/module/snd_hda_intel/parameters/power_save", "1\n");
+ cpu_calibration(1);
+ cpu_calibration(4);
+ wakeup_calibration(10000);
+ wakeup_calibration(100000);
+ wakeup_calibration(1000000);
+ set_wifi_power_saving("wlan0", 0);
+ usb_calibration();
+ rfkill_calibration();
+
+ cout << _("Finishing PowerTOP power estimate calibration \n");
+
+ restore_all_sysfs();
+ learn_parameters(300, 1);
+ printf(_("Parameters after calibration:\n"));
+ dump_parameter_bundle();
+ save_parameters("saved_parameters.powertop");
+ save_all_results("saved_results.powertop");
+
+}
diff --git a/src/calibrate/calibrate.h b/src/calibrate/calibrate.h
new file mode 100644
index 0000000..de71938
--- /dev/null
+++ b/src/calibrate/calibrate.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef __INCLUDE_GUARD_CALIBRATE_H
+#define __INCLUDE_GUARD_CALIBRATE_H
+
+extern void one_measurement(int seconds, int sample_interval, char *workload);
+extern void calibrate(void);
+
+
+#endif
diff --git a/src/cpu/abstract_cpu.cpp b/src/cpu/abstract_cpu.cpp
new file mode 100644
index 0000000..066891d
--- /dev/null
+++ b/src/cpu/abstract_cpu.cpp
@@ -0,0 +1,535 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <iostream>
+#include <fstream>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include "cpu.h"
+#include "../lib.h"
+
+abstract_cpu::~abstract_cpu()
+{
+ unsigned int i=0;
+ for (i=0; i < cstates.size(); i++){
+ delete cstates[i];
+ }
+ cstates.clear();
+
+ for (i=0; i < pstates.size(); i++){
+ delete pstates[i];
+ }
+ pstates.clear();
+}
+
+void abstract_cpu::account_freq(uint64_t freq, uint64_t duration)
+{
+ struct frequency *state = NULL;
+ unsigned int i;
+
+ for (i = 0; i < pstates.size(); i++) {
+ if (freq == pstates[i]->freq) {
+ state = pstates[i];
+ break;
+ }
+ }
+
+
+ if (!state) {
+ state = new(std::nothrow) struct frequency;
+
+ if (!state)
+ return;
+
+ memset(state, 0, sizeof(*state));
+
+ pstates.push_back(state);
+
+ state->freq = freq;
+ hz_to_human(freq, state->human_name);
+ if (freq == 0)
+ pt_strcpy(state->human_name, _("Idle"));
+ if (is_turbo(freq, max_frequency, max_minus_one_frequency))
+ pt_strcpy(state->human_name, _("Turbo Mode"));
+
+ state->after_count = 1;
+ }
+
+
+ state->time_after += duration;
+
+
+}
+
+void abstract_cpu::freq_updated(uint64_t time)
+{
+ if(parent)
+ parent->calculate_freq(time);
+ old_idle = idle;
+}
+
+void abstract_cpu::measurement_start(void)
+{
+ unsigned int i;
+ ifstream file;
+ char filename[4096];
+
+ last_stamp = 0;
+
+ for (i = 0; i < cstates.size(); i++)
+ delete cstates[i];
+ cstates.resize(0);
+
+ for (i = 0; i < pstates.size(); i++)
+ delete pstates[i];
+ pstates.resize(0);
+
+ current_frequency = 0;
+ idle = false;
+ old_idle = true;
+
+
+ snprintf(filename, sizeof(filename), "/sys/devices/system/cpu/cpu%i/cpufreq/scaling_available_frequencies", number);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> max_frequency;
+ file >> max_minus_one_frequency;
+ file.close();
+ }
+
+ for (i = 0; i < children.size(); i++)
+ if (children[i])
+ children[i]->measurement_start();
+
+ gettimeofday(&stamp_before, NULL);
+
+ last_stamp = 0;
+
+ for (i = 0; i < children.size(); i++)
+ if (children[i])
+ children[i]->wiggle();
+
+}
+
+void abstract_cpu::measurement_end(void)
+{
+ unsigned int i, j;
+
+ total_stamp = 0;
+ gettimeofday(&stamp_after, NULL);
+ for (i = 0; i < children.size(); i++)
+ if (children[i])
+ children[i]->wiggle();
+
+ time_factor = 1000000.0 * (stamp_after.tv_sec - stamp_before.tv_sec) + stamp_after.tv_usec - stamp_before.tv_usec;
+
+
+ for (i = 0; i < children.size(); i++)
+ if (children[i])
+ children[i]->measurement_end();
+
+ for (i = 0; i < children.size(); i++)
+ if (children[i]) {
+ for (j = 0; j < children[i]->cstates.size(); j++) {
+ struct idle_state *state;
+ state = children[i]->cstates[j];
+ if (!state)
+ continue;
+
+ update_cstate( state->linux_name, state->human_name, state->usage_before, state->duration_before, state->before_count);
+ finalize_cstate(state->linux_name, state->usage_after, state->duration_after, state->after_count);
+ }
+ for (j = 0; j < children[i]->pstates.size(); j++) {
+ struct frequency *state;
+ state = children[i]->pstates[j];
+ if (!state)
+ continue;
+
+ update_pstate( state->freq, state->human_name, state->time_before, state->before_count);
+ finalize_pstate(state->freq, state->time_after, state->after_count);
+ }
+ }
+
+ for (i = 0; i < cstates.size(); i++) {
+ struct idle_state *state = cstates[i];
+
+ if (state->after_count == 0)
+ continue;
+
+ if (state->after_count != state->before_count)
+ continue;
+
+ state->usage_delta = (state->usage_after - state->usage_before) / state->after_count;
+ state->duration_delta = (state->duration_after - state->duration_before) / state->after_count;
+ }
+}
+
+void abstract_cpu::insert_cstate(const char *linux_name, const char *human_name, uint64_t usage, uint64_t duration, int count, int level)
+{
+ struct idle_state *state;
+ const char *c;
+
+ state = new(std::nothrow) struct idle_state;
+
+ if (!state)
+ return;
+
+ memset(state, 0, sizeof(*state));
+
+ cstates.push_back(state);
+
+ pt_strcpy(state->linux_name, linux_name);
+ pt_strcpy(state->human_name, human_name);
+
+ state->line_level = -1;
+
+ c = human_name;
+ while (*c) {
+ if (strcmp(linux_name, "active")==0) {
+ state->line_level = LEVEL_C0;
+ break;
+ }
+ if (*c >= '0' && *c <='9') {
+ state->line_level = strtoull(c, NULL, 10);
+ if(*(c+1) != '-'){
+ int greater_line_level = strtoull(c, NULL, 10);
+ for(unsigned int pos = 0; pos < cstates.size(); pos++){
+ if(*c == cstates[pos]->human_name[1]){
+ if(*(c+1) != cstates[pos]->human_name[2]){
+ greater_line_level = max(greater_line_level, cstates[pos]->line_level);
+ state->line_level = greater_line_level + 1;
+ }
+ }
+ }
+ }
+ break;
+ }
+ c++;
+ }
+
+ /* some architectures (ARM) don't have good numbers in their human name.. fall back to the linux name for those */
+ c = linux_name;
+ while (*c && state->line_level < 0) {
+ if (*c >= '0' && *c <='9') {
+ state->line_level = strtoull(c, NULL, 10);
+ break;
+ }
+ c++;
+ }
+
+ if (level >= 0)
+ state->line_level = level;
+
+ state->usage_before = usage;
+ state->duration_before = duration;
+ state->before_count = count;
+}
+
+void abstract_cpu::finalize_cstate(const char *linux_name, uint64_t usage, uint64_t duration, int count)
+{
+ unsigned int i;
+ struct idle_state *state = NULL;
+
+ for (i = 0; i < cstates.size(); i++) {
+ if (strcmp(linux_name, cstates[i]->linux_name) == 0) {
+ state = cstates[i];
+ break;
+ }
+ }
+
+ if (!state) {
+ cout << "Invalid C state finalize " << linux_name << " \n";
+ return;
+ }
+
+ state->usage_after += usage;
+ state->duration_after += duration;
+ state->after_count += count;
+}
+
+void abstract_cpu::update_cstate(const char *linux_name, const char *human_name, uint64_t usage, uint64_t duration, int count, int level)
+{
+ unsigned int i;
+ struct idle_state *state = NULL;
+
+ for (i = 0; i < cstates.size(); i++) {
+ if (strcmp(linux_name, cstates[i]->linux_name) == 0) {
+ state = cstates[i];
+ break;
+ }
+ }
+
+ if (!state) {
+ insert_cstate(linux_name, human_name, usage, duration, count, level);
+ return;
+ }
+
+ state->usage_before += usage;
+ state->duration_before += duration;
+ state->before_count += count;
+
+}
+
+int abstract_cpu::has_cstate_level(int level)
+{
+ unsigned int i;
+
+ if (level == LEVEL_HEADER)
+ return 1;
+
+ for (i = 0; i < cstates.size(); i++)
+ if (cstates[i]->line_level == level)
+ return 1;
+
+ for (i = 0; i < children.size(); i++)
+ if (children[i])
+ if (children[i]->has_cstate_level(level))
+ return 1;
+ return 0;
+}
+
+int abstract_cpu::has_pstate_level(int level)
+{
+ unsigned int i;
+
+ if (level == LEVEL_HEADER)
+ return 1;
+
+ if (level >= 0 && level < (int)pstates.size())
+ return 1;
+
+ for (i = 0; i < children.size(); i++)
+ if (children[i])
+ if (children[i]->has_pstate_level(level))
+ return 1;
+ return 0;
+}
+
+
+
+void abstract_cpu::insert_pstate(uint64_t freq, const char *human_name, uint64_t duration, int count)
+{
+ struct frequency *state;
+
+ state = new(std::nothrow) struct frequency;
+
+ if (!state)
+ return;
+
+ memset(state, 0, sizeof(*state));
+
+ pstates.push_back(state);
+
+ state->freq = freq;
+ pt_strcpy(state->human_name, human_name);
+
+
+ state->time_before = duration;
+ state->before_count = count;
+}
+
+void abstract_cpu::finalize_pstate(uint64_t freq, uint64_t duration, int count)
+{
+ unsigned int i;
+ struct frequency *state = NULL;
+
+ for (i = 0; i < pstates.size(); i++) {
+ if (freq == pstates[i]->freq) {
+ state = pstates[i];
+ break;
+ }
+ }
+
+ if (!state) {
+ cout << "Invalid P state finalize " << freq << " \n";
+ return;
+ }
+ state->time_after += duration;
+ state->after_count += count;
+
+}
+
+void abstract_cpu::update_pstate(uint64_t freq, const char *human_name, uint64_t duration, int count)
+{
+ unsigned int i;
+ struct frequency *state = NULL;
+
+ for (i = 0; i < pstates.size(); i++) {
+ if (freq == pstates[i]->freq) {
+ state = pstates[i];
+ break;
+ }
+ }
+
+ if (!state) {
+ insert_pstate(freq, human_name, duration, count);
+ return;
+ }
+
+ state->time_before += duration;
+ state->before_count += count;
+}
+
+
+void abstract_cpu::calculate_freq(uint64_t time)
+{
+ uint64_t freq = 0;
+ bool is_idle = true;
+ unsigned int i;
+
+ /* calculate the maximum frequency of all children */
+ for (i = 0; i < children.size(); i++)
+ if (children[i] && children[i]->has_pstates()) {
+ uint64_t f = 0;
+ if (!children[i]->idle) {
+ f = children[i]->current_frequency;
+ is_idle = false;
+ }
+ if (f > freq)
+ freq = f;
+ }
+
+ current_frequency = freq;
+ idle = is_idle;
+ freq_updated(time);
+}
+
+void abstract_cpu::change_effective_frequency(uint64_t time, uint64_t frequency)
+{
+ unsigned int i;
+ uint64_t time_delta, fr;
+
+ if (last_stamp)
+ time_delta = time - last_stamp;
+ else
+ time_delta = 1;
+
+ fr = effective_frequency;
+ if (old_idle)
+ fr = 0;
+
+ account_freq(fr, time_delta);
+
+ effective_frequency = frequency;
+ last_stamp = time;
+
+ /* propagate to all children */
+ for (i = 0; i < children.size(); i++)
+ if (children[i]) {
+ children[i]->change_effective_frequency(time, frequency);
+ }
+}
+
+
+void abstract_cpu::wiggle(void)
+{
+ char filename[PATH_MAX];
+ ifstream ifile;
+ ofstream ofile;
+ uint64_t minf,maxf;
+ uint64_t setspeed = 0;
+
+ /* wiggle a CPU so that we have a record of it at the start and end of the perf trace */
+
+ snprintf(filename, sizeof(filename), "/sys/devices/system/cpu/cpu%i/cpufreq/scaling_max_freq", first_cpu);
+ ifile.open(filename, ios::in);
+ ifile >> maxf;
+ ifile.close();
+
+ snprintf(filename, sizeof(filename), "/sys/devices/system/cpu/cpu%i/cpufreq/scaling_min_freq", first_cpu);
+ ifile.open(filename, ios::in);
+ ifile >> minf;
+ ifile.close();
+
+ /* In case of the userspace governor, remember the old setspeed setting, it will be affected by wiggle */
+ snprintf(filename, sizeof(filename), "/sys/devices/system/cpu/cpu%i/cpufreq/scaling_setspeed", first_cpu);
+ ifile.open(filename, ios::in);
+ /* Note that non-userspace governors report "<unsupported>". In that case ifile will fail and setspeed remains 0 */
+ ifile >> setspeed;
+ ifile.close();
+
+ ofile.open(filename, ios::out);
+ ofile << maxf;
+ ofile.close();
+ ofile.open(filename, ios::out);
+ ofile << minf;
+ ofile.close();
+ snprintf(filename, sizeof(filename), "/sys/devices/system/cpu/cpu%i/cpufreq/scaling_max_freq", first_cpu);
+ ofile.open(filename, ios::out);
+ ofile << minf;
+ ofile.close();
+ ofile.open(filename, ios::out);
+ ofile << maxf;
+ ofile.close();
+
+ if (setspeed != 0) {
+ snprintf(filename, sizeof(filename), "/sys/devices/system/cpu/cpu%i/cpufreq/scaling_setspeed", first_cpu);
+ ofile.open(filename, ios::out);
+ ofile << setspeed;
+ ofile.close();
+ }
+}
+uint64_t abstract_cpu::total_pstate_time(void)
+{
+ unsigned int i;
+ uint64_t stamp = 0;
+
+ for (i = 0; i < pstates.size(); i++)
+ stamp += pstates[i]->time_after;
+
+ return stamp;
+}
+
+
+void abstract_cpu::validate(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < children.size(); i++) {
+ if (children[i])
+ children[i]->validate();
+ }
+}
+
+void abstract_cpu::reset_pstate_data(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < pstates.size(); i++) {
+ pstates[i]->time_before = 0;
+ pstates[i]->time_after = 0;
+ }
+ for (i = 0; i < cstates.size(); i++) {
+ cstates[i]->duration_before = 0;
+ cstates[i]->duration_after = 0;
+ cstates[i]->before_count = 0;
+ cstates[i]->after_count = 0;
+ }
+
+ for (i = 0; i < children.size(); i++)
+ if (children[i])
+ children[i]->reset_pstate_data();
+}
diff --git a/src/cpu/cpu.cpp b/src/cpu/cpu.cpp
new file mode 100644
index 0000000..1c12765
--- /dev/null
+++ b/src/cpu/cpu.cpp
@@ -0,0 +1,1075 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <iostream>
+#include <fstream>
+#include <vector>
+#include <string.h>
+#include <stdlib.h>
+#include <ncurses.h>
+#include <unistd.h>
+#include "cpu.h"
+#include "cpudevice.h"
+#include "cpu_rapl_device.h"
+#include "dram_rapl_device.h"
+#include "intel_cpus.h"
+#include "../parameters/parameters.h"
+
+#include "../perf/perf_bundle.h"
+#include "../lib.h"
+#include "../display.h"
+#include "../report/report.h"
+#include "../report/report-maker.h"
+#include "../report/report-data-html.h"
+
+static class abstract_cpu system_level;
+
+vector<class abstract_cpu *> all_cpus;
+
+static class perf_bundle * perf_events;
+
+
+
+class perf_power_bundle: public perf_bundle
+{
+ virtual void handle_trace_point(void *trace, int cpu, uint64_t time);
+
+};
+
+
+static class abstract_cpu * new_package(int package, int cpu, char * vendor, int family, int model)
+{
+ class abstract_cpu *ret = NULL;
+ class cpudevice *cpudev;
+ class cpu_rapl_device *cpu_rapl_dev;
+ class dram_rapl_device *dram_rapl_dev;
+
+ char packagename[128];
+ if (strcmp(vendor, "GenuineIntel") == 0)
+ if (family == 6)
+ if (is_supported_intel_cpu(model, cpu)) {
+ ret = new class nhm_package(model);
+ ret->set_intel_MSR(true);
+ }
+
+ if (!ret) {
+ ret = new class cpu_package;
+ ret->set_intel_MSR(false);
+ }
+
+ ret->set_number(package, cpu);
+ ret->set_type("Package");
+ ret->childcount = 0;
+
+ snprintf(packagename, sizeof(packagename), _("cpu package %i"), cpu);
+ cpudev = new class cpudevice(_("cpu package"), packagename, ret);
+ all_devices.push_back(cpudev);
+
+ snprintf(packagename, sizeof(packagename), _("package-%i"), cpu);
+ cpu_rapl_dev = new class cpu_rapl_device(cpudev, _("cpu rapl package"), packagename, ret);
+ if (cpu_rapl_dev->device_present())
+ all_devices.push_back(cpu_rapl_dev);
+ else
+ delete cpu_rapl_dev;
+
+ snprintf(packagename, sizeof(packagename), _("package-%i"), cpu);
+ dram_rapl_dev = new class dram_rapl_device(cpudev, _("dram rapl package"), packagename, ret);
+ if (dram_rapl_dev->device_present())
+ all_devices.push_back(dram_rapl_dev);
+ else
+ delete dram_rapl_dev;
+
+ return ret;
+}
+
+static class abstract_cpu * new_core(int core, int cpu, char * vendor, int family, int model)
+{
+ class abstract_cpu *ret = NULL;
+
+ if (strcmp(vendor, "GenuineIntel") == 0)
+ if (family == 6)
+ if (is_supported_intel_cpu(model, cpu)) {
+ ret = new class nhm_core(model);
+ ret->set_intel_MSR(true);
+ }
+
+ if (!ret) {
+ ret = new class cpu_core;
+ ret->set_intel_MSR(false);
+ }
+
+ ret->set_number(core, cpu);
+ ret->childcount = 0;
+ ret->set_type("Core");
+
+ return ret;
+}
+
+static class abstract_cpu * new_i965_gpu(void)
+{
+ class abstract_cpu *ret = NULL;
+
+ ret = new class i965_core;
+ ret->childcount = 0;
+ ret->set_type("GPU");
+
+ return ret;
+}
+
+static class abstract_cpu * new_cpu(int number, char * vendor, int family, int model)
+{
+ class abstract_cpu * ret = NULL;
+
+ if (strcmp(vendor, "GenuineIntel") == 0)
+ if (family == 6)
+ if (is_supported_intel_cpu(model, number)) {
+ ret = new class nhm_cpu;
+ ret->set_intel_MSR(true);
+ }
+
+ if (!ret) {
+ ret = new class cpu_linux;
+ ret->set_intel_MSR(false);
+ }
+ ret->set_number(number, number);
+ ret->set_type("CPU");
+ ret->childcount = 0;
+
+ return ret;
+}
+
+
+
+
+static void handle_one_cpu(unsigned int number, char *vendor, int family, int model)
+{
+ char filename[PATH_MAX];
+ ifstream file;
+ unsigned int package_number = 0;
+ unsigned int core_number = 0;
+ class abstract_cpu *package, *core, *cpu;
+
+ snprintf(filename, sizeof(filename), "/sys/devices/system/cpu/cpu%i/topology/core_id", number);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> core_number;
+ file.close();
+ }
+
+ snprintf(filename, sizeof(filename), "/sys/devices/system/cpu/cpu%i/topology/physical_package_id", number);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> package_number;
+ if (package_number == (unsigned int) -1)
+ package_number = 0;
+ file.close();
+ }
+
+
+ if (system_level.children.size() <= package_number)
+ system_level.children.resize(package_number + 1, NULL);
+
+ if (!system_level.children[package_number]) {
+ system_level.children[package_number] = new_package(package_number, number, vendor, family, model);
+ system_level.childcount++;
+ }
+
+ package = system_level.children[package_number];
+ package->parent = &system_level;
+
+ if (package->children.size() <= core_number)
+ package->children.resize(core_number + 1, NULL);
+
+ if (!package->children[core_number]) {
+ package->children[core_number] = new_core(core_number, number, vendor, family, model);
+ package->childcount++;
+ }
+
+ core = package->children[core_number];
+ core->parent = package;
+
+ if (core->children.size() <= number)
+ core->children.resize(number + 1, NULL);
+ if (!core->children[number]) {
+ core->children[number] = new_cpu(number, vendor, family, model);
+ core->childcount++;
+ }
+
+ cpu = core->children[number];
+ cpu->parent = core;
+
+ if (number >= all_cpus.size())
+ all_cpus.resize(number + 1, NULL);
+ all_cpus[number] = cpu;
+}
+
+static void handle_i965_gpu(void)
+{
+ unsigned int core_number = 0;
+ class abstract_cpu *package;
+
+
+ package = system_level.children[0];
+
+ core_number = package->children.size();
+
+ if (package->children.size() <= core_number)
+ package->children.resize(core_number + 1, NULL);
+
+ if (!package->children[core_number]) {
+ package->children[core_number] = new_i965_gpu();
+ package->childcount++;
+ }
+}
+
+
+void enumerate_cpus(void)
+{
+ ifstream file;
+ char line[4096];
+
+ int number = -1;
+ char vendor[128];
+ int family = 0;
+ int model = 0;
+
+ file.open("/proc/cpuinfo", ios::in);
+
+ if (!file)
+ return;
+ /* Not all /proc/cpuinfo include "vendor_id\t". */
+ vendor[0] = '\0';
+
+ while (file) {
+
+ file.getline(line, sizeof(line));
+ if (strncmp(line, "vendor_id\t",10) == 0) {
+ char *c;
+ c = strchr(line, ':');
+ if (c) {
+ c++;
+ if (*c == ' ')
+ c++;
+ pt_strcpy(vendor, c);
+ }
+ }
+ if (strncmp(line, "processor\t",10) == 0) {
+ char *c;
+ c = strchr(line, ':');
+ if (c) {
+ c++;
+ number = strtoull(c, NULL, 10);
+ }
+ }
+ if (strncmp(line, "cpu family\t",11) == 0) {
+ char *c;
+ c = strchr(line, ':');
+ if (c) {
+ c++;
+ family = strtoull(c, NULL, 10);
+ }
+ }
+ if (strncmp(line, "model\t",6) == 0) {
+ char *c;
+ c = strchr(line, ':');
+ if (c) {
+ c++;
+ model = strtoull(c, NULL, 10);
+ }
+ }
+ /* on x86 and others 'bogomips' is last
+ * on ARM it *can* be bogomips, or 'CPU revision'
+ * on POWER, it's revision
+ */
+ if (strncasecmp(line, "bogomips\t", 9) == 0
+ || strncasecmp(line, "CPU revision\t", 13) == 0
+ || strncmp(line, "revision", 8) == 0) {
+ if (number == -1) {
+ /* Not all /proc/cpuinfo include "processor\t". */
+ number = 0;
+ }
+ if (number >= 0) {
+ handle_one_cpu(number, vendor, family, model);
+ set_max_cpu(number);
+ number = -2;
+ }
+ }
+ }
+
+
+ file.close();
+
+ if (access("/sys/class/drm/card0/power/rc6_residency_ms", R_OK) == 0)
+ handle_i965_gpu();
+
+ perf_events = new perf_power_bundle();
+
+ if (!perf_events->add_event("power:cpu_idle")){
+ perf_events->add_event("power:power_start");
+ perf_events->add_event("power:power_end");
+ }
+ if (!perf_events->add_event("power:cpu_frequency"))
+ perf_events->add_event("power:power_frequency");
+
+}
+
+void start_cpu_measurement(void)
+{
+ perf_events->start();
+ system_level.measurement_start();
+}
+
+void end_cpu_measurement(void)
+{
+ system_level.measurement_end();
+ perf_events->stop();
+}
+
+static void expand_string(char *string, unsigned int newlen)
+{
+ while (strlen(string) < newlen)
+ strcat(string, " ");
+}
+
+static int has_state_level(class abstract_cpu *acpu, int state, int line)
+{
+ switch (state) {
+ case PSTATE:
+ return acpu->has_pstate_level(line);
+ break;
+ case CSTATE:
+ return acpu->has_cstate_level(line);
+ break;
+ }
+ return 0;
+}
+
+static const char * fill_state_name(class abstract_cpu *acpu, int state, int line, char *buf)
+{
+ switch (state) {
+ case PSTATE:
+ return acpu->fill_pstate_name(line, buf);
+ break;
+ case CSTATE:
+ return acpu->fill_cstate_name(line, buf);
+ break;
+ }
+ return "-EINVAL";
+}
+
+static const char * fill_state_line(class abstract_cpu *acpu, int state, int line,
+ char *buf, const char *sep = "")
+{
+ switch (state) {
+ case PSTATE:
+ return acpu->fill_pstate_line(line, buf);
+ break;
+ case CSTATE:
+ return acpu->fill_cstate_line(line, buf, sep);
+ break;
+ }
+ return "-EINVAL";
+}
+
+static int get_cstates_num(void)
+{
+ unsigned int package, core, cpu;
+ class abstract_cpu *_package, * _core, * _cpu;
+ unsigned int i;
+ int cstates_num;
+
+ for (package = 0, cstates_num = 0;
+ package < system_level.children.size(); package++) {
+ _package = system_level.children[package];
+ if (_package == NULL)
+ continue;
+
+ /* walk package cstates and get largest cstates number */
+ for (i = 0; i < _package->cstates.size(); i++)
+ cstates_num = std::max(cstates_num,
+ (_package->cstates[i])->line_level);
+
+ /*
+ * for each core in this package, walk core cstates and get
+ * largest cstates number
+ */
+ for (core = 0; core < _package->children.size(); core++) {
+ _core = _package->children[core];
+ if (_core == NULL)
+ continue;
+
+ for (i = 0; i < _core->cstates.size(); i++)
+ cstates_num = std::max(cstates_num,
+ (_core->cstates[i])->line_level);
+
+ /*
+ * for each core, walk the logical cpus in case
+ * there is are more linux cstates than hw cstates
+ */
+ for (cpu = 0; cpu < _core->children.size(); cpu++) {
+ _cpu = _core->children[cpu];
+ if (_cpu == NULL)
+ continue;
+
+ for (i = 0; i < _cpu->cstates.size(); i++)
+ cstates_num = std::max(cstates_num,
+ (_cpu->cstates[i])->line_level);
+ }
+ }
+ }
+
+ return cstates_num;
+}
+
+void report_display_cpu_cstates(void)
+{
+ char buffer[512], buffer2[512], tmp_num[50];
+ unsigned int package, core, cpu;
+ int line, cstates_num, title=0, core_num=0;
+ class abstract_cpu *_package, *_core = NULL, * _cpu;
+ const char* core_type = NULL;
+
+ cstates_num = get_cstates_num();
+ /* div attr css_class and css_id */
+ tag_attr div_attr;
+ init_div(&div_attr, "clear_block", "cpuidle");
+
+ /* Set Table attributes, rows, and cols */
+ table_attributes std_table_css;
+ table_size pkg_tbl_size;
+ table_size core_tbl_size;
+ table_size cpu_tbl_size;
+
+
+ /* Set Title attributes */
+ tag_attr title_attr;
+ init_title_attr(&title_attr);
+
+ /* Report add section */
+ report.add_div(&div_attr);
+ report.add_title(&title_attr, __("Processor Idle State Report"));
+
+ /* Set array of data in row Major order */
+ int idx1, idx2, idx3;
+ string tmp_str;
+
+ for (package = 0; package < system_level.children.size(); package++) {
+ bool first_core = true;
+ idx1=0;
+ idx2=0;
+ idx3=0;
+
+ _package = system_level.children[package];
+ if (!_package)
+ continue;
+ /* Tables for PKG, CORE, CPU */
+ pkg_tbl_size.cols=2;
+ pkg_tbl_size.rows= ((cstates_num+1)-LEVEL_HEADER)+1;
+ string *pkg_data = new string[pkg_tbl_size.cols * pkg_tbl_size.rows];
+
+ core_tbl_size.cols=2;
+ core_tbl_size.rows=(cstates_num *_package->children.size())
+ + _package->children.size();
+ string *core_data = new string[core_tbl_size.cols * core_tbl_size.rows];
+ int num_cpus=0, num_cores=0;
+
+ for (core = 0; core < _package->children.size(); core++) {
+ _core = _package->children[core];
+ if (!_core)
+ continue;
+ core_type = _core->get_type();
+ if (core_type != NULL)
+ if (strcmp(core_type, "Core") == 0 )
+ num_cores+=1;
+
+ for (cpu = 0; cpu < _core->children.size(); cpu++) {
+ _cpu = _core->children[cpu];
+ if (!_cpu)
+ continue;
+ num_cpus+=1;
+ }
+ }
+ cpu_tbl_size.cols=(2 * (num_cpus / num_cores)) + 1;
+ cpu_tbl_size.rows = ((cstates_num+1-LEVEL_HEADER) * _package->children.size())
+ + _package->children.size();
+ string *cpu_data = new string[cpu_tbl_size.cols * cpu_tbl_size.rows];
+
+ for (core = 0; core < _package->children.size(); core++) {
+ cpu_data[idx3]="&nbsp;";
+ idx3+=1;
+ _core = _package->children[core];
+
+ if (!_core)
+ continue;
+
+ /* *** PKG STARTS *** */
+ for (line = LEVEL_HEADER; line <= cstates_num; line++) {
+ bool first_cpu = true;
+ if (!_package->has_cstate_level(line))
+ continue;
+ buffer[0] = 0;
+ buffer2[0] = 0;
+ if (line == LEVEL_HEADER) {
+ if (first_core) {
+ pkg_data[idx1]=__("Package");
+ idx1+=1;
+ sprintf(tmp_num,"%d", _package->get_number());
+ pkg_data[idx1]= string(tmp_num);
+ idx1+=1;
+ }
+ } else if (first_core) {
+ tmp_str=string(_package->fill_cstate_name(line, buffer));
+ pkg_data[idx1]=(tmp_str=="" ? "&nbsp;" : tmp_str);
+ idx1+=1;
+ tmp_str=string(_package->fill_cstate_line(line, buffer2));
+ pkg_data[idx1]=(tmp_str=="" ? "&nbsp;" : tmp_str);
+ idx1+=1;
+ }
+
+ /* *** CORE STARTS *** */
+ if (!_core->can_collapse()) {
+ buffer[0] = 0;
+ buffer2[0] = 0;
+
+ /*
+ * Patch for compatibility with Ryzen processors
+ * See https://github.com/fenrus75/powertop/issues/64
+ */
+ if(idx2 >= core_tbl_size.cols * core_tbl_size.rows) break;
+
+ if (line == LEVEL_HEADER) {
+ /* Here we need to check for which core type we
+ * are using. Do not use the core type for the
+ * report.addf as it breaks an important macro use
+ * for translation decision making for the reports.
+ * */
+ core_type = _core->get_type();
+ if (core_type != NULL) {
+ if (strcmp(core_type, "Core") == 0 ) {
+ core_data[idx2]="";
+ idx2+=1;
+ snprintf(tmp_num, sizeof(tmp_num), __("Core %d"), _core->get_number());
+ core_data[idx2]=string(tmp_num);
+ idx2+=1;
+ core_num+=1;
+ } else {
+ core_data[idx2]="";
+ idx2+=1;
+ snprintf(tmp_num, sizeof(tmp_num), __("GPU %d"), _core->get_number());
+ core_data[idx2]=string(tmp_num);
+ idx2+=1;
+ }
+ }
+ } else {
+
+
+ tmp_str=string(_core->fill_cstate_name(line, buffer));
+ core_data[idx2]=(tmp_str=="" ? "&nbsp;" : tmp_str);
+ idx2+=1;
+ tmp_str=string(_core->fill_cstate_line(line, buffer2));
+ core_data[idx2]=(tmp_str=="" ? "&nbsp;" : tmp_str);
+ idx2+=1;
+ }
+ }
+ // *** CPU STARTS ***
+ for (cpu = 0; cpu < _core->children.size(); cpu++) {
+ _cpu = _core->children[cpu];
+
+ if (!_cpu)
+ continue;
+ if (line == LEVEL_HEADER) {
+ cpu_data[idx3] = __("CPU");
+ idx3+=1;
+ sprintf(tmp_num,"%d",_cpu->get_number());
+ cpu_data[idx3]=string(tmp_num);
+ idx3+=1;
+ continue;
+ }
+
+ if (first_cpu) {
+ title+=1;
+ cpu_data[idx3]=(string(_cpu->fill_cstate_name(line, buffer)));
+ idx3+=1;
+ first_cpu = false;
+ }
+
+ buffer[0] = 0;
+ tmp_str=string(_cpu->fill_cstate_percentage(line, buffer));
+ cpu_data[idx3]=(tmp_str=="" ? "&nbsp;" : tmp_str);
+ idx3+=1;
+
+ if (line != LEVEL_C0){
+ tmp_str=string(_cpu->fill_cstate_time(line, buffer));
+ cpu_data[idx3]=(tmp_str=="" ? "&nbsp;" : tmp_str);
+ idx3+=1;
+ } else {
+ cpu_data[idx3]="&nbsp;";
+ idx3+=1;
+ }
+ }
+ }
+ first_core = false;
+ }
+
+ /* Report Output */
+ if(core_num > 0)
+ title=title/core_num;
+ else if(_core && _core->children.size() > 0)
+ title=title/_core->children.size();
+
+ init_pkg_table_attr(&std_table_css, pkg_tbl_size.rows, pkg_tbl_size.cols);
+ report.add_table(pkg_data, &std_table_css);
+ if (!_core->can_collapse()){
+ init_core_table_attr(&std_table_css, title+1, core_tbl_size.rows,
+ core_tbl_size.cols);
+ report.add_table(core_data, &std_table_css);
+ }
+ init_cpu_table_attr(&std_table_css, title+1, cpu_tbl_size.rows,
+ cpu_tbl_size.cols);
+ report.add_table(cpu_data, &std_table_css);
+ delete [] pkg_data;
+ delete [] core_data;
+ delete [] cpu_data;
+ }
+ report.end_div();
+}
+
+void report_display_cpu_pstates(void)
+{
+ char buffer[512], buffer2[512], tmp_num[50];
+ unsigned int package, core, cpu;
+ int line, title=0;
+ class abstract_cpu *_package, *_core = NULL, * _cpu;
+ unsigned int i, pstates_num;
+ const char* core_type = NULL;
+
+ /* div attr css_class and css_id */
+ tag_attr div_attr;
+ init_div(&div_attr, "clear_block", "cpufreq");
+
+ /* Set Table attributes, rows, and cols */
+ table_attributes std_table_css;
+ table_size pkg_tbl_size;
+ table_size core_tbl_size;
+ table_size cpu_tbl_size;
+
+
+ /* Set Title attributes */
+ tag_attr title_attr;
+ init_title_attr(&title_attr);
+
+ /* Report add section */
+ report.add_div(&div_attr);
+ report.add_title(&title_attr, __("Processor Frequency Report"));
+
+ /* Set array of data in row Major order */
+ int idx1, idx2, idx3, num_cpus=0, num_cores=0;
+ string tmp_str;
+
+ for (i = 0, pstates_num = 0; i < all_cpus.size(); i++) {
+ if (all_cpus[i])
+ pstates_num = std::max<unsigned int>(pstates_num,
+ all_cpus[i]->pstates.size());
+ }
+
+ for (package = 0; package < system_level.children.size(); package++) {
+ bool first_core = true;
+ idx1=0;
+ idx2=0;
+ idx3=0;
+
+ _package = system_level.children[package];
+ if (!_package)
+ continue;
+
+ /* Tables for PKG, CORE, CPU */
+ pkg_tbl_size.cols=2;
+ pkg_tbl_size.rows=((pstates_num+1)-LEVEL_HEADER)+2;
+ string *pkg_data = new string[pkg_tbl_size.cols * pkg_tbl_size.rows];
+
+ core_tbl_size.cols=2;
+ core_tbl_size.rows=((pstates_num+2) *_package->children.size());
+ string *core_data = new string[core_tbl_size.cols * core_tbl_size.rows];
+
+ /* PKG */
+ num_cpus=0;
+ num_cores=0;
+ for (core = 0; core < _package->children.size(); core++) {
+ _core = _package->children[core];
+ if (!_core)
+ continue;
+
+ core_type = _core->get_type();
+ if (core_type != NULL)
+ if (strcmp(core_type, "Core") == 0 )
+ num_cores+=1;
+
+ for (cpu = 0; cpu < _core->children.size(); cpu++) {
+ _cpu = _core->children[cpu];
+ if (!_cpu)
+ continue;
+ num_cpus+=1;
+ }
+ }
+ cpu_tbl_size.cols= (num_cpus/ num_cores) + 1;
+ cpu_tbl_size.rows= (pstates_num+2) * _package->children.size()
+ + _package->children.size();
+ string *cpu_data = new string[cpu_tbl_size.cols * cpu_tbl_size.rows];
+
+ /* Core */
+ for (core = 0; core < _package->children.size(); core++) {
+ cpu_data[idx3]="&nbsp;";
+ idx3+=1;
+ _core = _package->children[core];
+ if (!_core)
+ continue;
+
+ if (!_core->has_pstates())
+ continue;
+
+ for (line = LEVEL_HEADER; line < (int)pstates_num; line++) {
+ bool first_cpu = true;
+
+ if (!_package->has_pstate_level(line))
+ continue;
+
+ buffer[0] = 0;
+ buffer2[0] = 0;
+ if (first_core) {
+ if (line == LEVEL_HEADER) {
+ pkg_data[idx1]=__("Package");
+ idx1+=1;
+ sprintf(tmp_num,"%d", _package->get_number());
+ pkg_data[idx1]= string(tmp_num);
+ idx1+=1;
+ } else {
+ tmp_str=string(_package->fill_pstate_name(line, buffer));
+ pkg_data[idx1]=(tmp_str=="" ? "&nbsp;" : tmp_str);
+ idx1+=1;
+ tmp_str=string(_package->fill_pstate_line(line, buffer2));
+ pkg_data[idx1]=(tmp_str=="" ? "&nbsp;" : tmp_str);
+ idx1+=1;
+ }
+ }
+
+
+ if (!_core->can_collapse()) {
+ buffer[0] = 0;
+ buffer2[0] = 0;
+ if (line == LEVEL_HEADER) {
+ core_data[idx2]="";
+ idx2+=1;
+ snprintf(tmp_num, sizeof(tmp_num), __("Core %d"), _core->get_number());
+ core_data[idx2]=string(tmp_num);
+ idx2+=1;
+ } else {
+ tmp_str=string(_core->fill_pstate_name(line, buffer));
+ core_data[idx2]= (tmp_str=="" ? "&nbsp;" : tmp_str);
+ idx2+=1;
+ tmp_str=string(_core->fill_pstate_line(line, buffer2));
+ core_data[idx2]= (tmp_str=="" ? "&nbsp;" : tmp_str);
+ idx2+=1;
+ }
+ }
+
+ /* CPU */
+ for (cpu = 0; cpu < _core->children.size(); cpu++) {
+ buffer[0] = 0;
+ _cpu = _core->children[cpu];
+ if (!_cpu)
+ continue;
+
+ if (line == LEVEL_HEADER) {
+ snprintf(tmp_num, sizeof(tmp_num), __("CPU %d"), _cpu->get_number());
+ cpu_data[idx3] = string(tmp_num);
+ idx3+=1;
+ continue;
+ }
+
+ if (first_cpu) {
+ tmp_str=string(_cpu->fill_pstate_name(line, buffer));
+ cpu_data[idx3]=(tmp_str=="" ? "&nbsp;" : tmp_str);
+ idx3+=1;
+ first_cpu = false;
+ }
+
+ buffer[0] = 0;
+ tmp_str=string(_cpu->fill_pstate_line(line, buffer));
+ cpu_data[idx3]=(tmp_str=="" ? "&nbsp;" : tmp_str);
+ idx3+=1;
+ }
+ }
+ first_core = false;
+ }
+ init_pkg_table_attr(&std_table_css, pkg_tbl_size.rows, pkg_tbl_size.cols);
+ report.add_table(pkg_data, &std_table_css);
+ if(_core && !_core->can_collapse()){
+ title=pstates_num+2;
+ init_core_table_attr(&std_table_css, title,
+ core_tbl_size.rows, core_tbl_size.cols);
+ report.add_table(core_data, &std_table_css);
+ } else {
+ title=pstates_num+1;
+ }
+
+ init_cpu_table_attr(&std_table_css, title,
+ cpu_tbl_size.rows, cpu_tbl_size.cols);
+ report.add_table(cpu_data, &std_table_css);
+ delete [] pkg_data;
+ delete [] core_data;
+ delete [] cpu_data;
+ }
+ report.end_div();
+}
+
+void impl_w_display_cpu_states(int state)
+{
+ WINDOW *win;
+ char buffer[128];
+ char linebuf[1024];
+ unsigned int package, core, cpu;
+ int line, loop, cstates_num, pstates_num;
+ class abstract_cpu *_package, * _core, * _cpu;
+ int ctr = 0;
+ unsigned int i;
+
+ cstates_num = get_cstates_num();
+
+ for (i = 0, pstates_num = 0; i < all_cpus.size(); i++) {
+ if (!all_cpus[i])
+ continue;
+
+ pstates_num = std::max<int>(pstates_num, all_cpus[i]->pstates.size());
+ }
+
+ if (state == PSTATE) {
+ win = get_ncurses_win("Frequency stats");
+ loop = pstates_num;
+ } else {
+ win = get_ncurses_win("Idle stats");
+ loop = cstates_num;
+ }
+
+ if (!win)
+ return;
+
+ wclear(win);
+ wmove(win, 2,0);
+
+ for (package = 0; package < system_level.children.size(); package++) {
+ int first_pkg = 0;
+ _package = system_level.children[package];
+ if (!_package)
+ continue;
+
+ for (core = 0; core < _package->children.size(); core++) {
+ _core = _package->children[core];
+ if (!_core)
+ continue;
+ if (!_core->has_pstates() && state == PSTATE)
+ continue;
+
+ for (line = LEVEL_HEADER; line <= loop; line++) {
+ int first = 1;
+ ctr = 0;
+ linebuf[0] = 0;
+
+ if (!has_state_level(_package, state, line))
+ continue;
+
+ buffer[0] = 0;
+ if (first_pkg == 0) {
+ strcat(linebuf, fill_state_name(_package, state, line, buffer));
+ expand_string(linebuf, ctr + 10);
+ strcat(linebuf, fill_state_line(_package, state, line, buffer));
+ }
+ ctr += 20;
+ expand_string(linebuf, ctr);
+
+ strcat(linebuf, "| ");
+ ctr += strlen("| ");
+
+ if (!_core->can_collapse()) {
+ buffer[0] = 0;
+ strcat(linebuf, fill_state_name(_core, state, line, buffer));
+ expand_string(linebuf, ctr + 10);
+ strcat(linebuf, fill_state_line(_core, state, line, buffer));
+ ctr += 20;
+ expand_string(linebuf, ctr);
+
+ strcat(linebuf, "| ");
+ ctr += strlen("| ");
+ }
+
+ for (cpu = 0; cpu < _core->children.size(); cpu++) {
+ _cpu = _core->children[cpu];
+ if (!_cpu)
+ continue;
+
+ if (first == 1) {
+ strcat(linebuf, fill_state_name(_cpu, state, line, buffer));
+ expand_string(linebuf, ctr + 10);
+ first = 0;
+ ctr += 12;
+ }
+ buffer[0] = 0;
+ strcat(linebuf, fill_state_line(_cpu, state, line, buffer));
+ ctr += 10;
+ expand_string(linebuf, ctr);
+
+ }
+ strcat(linebuf, "\n");
+ wprintw(win, "%s", linebuf);
+ }
+ wprintw(win, "\n");
+ first_pkg++;
+ }
+ }
+}
+
+void w_display_cpu_pstates(void)
+{
+ impl_w_display_cpu_states(PSTATE);
+}
+
+void w_display_cpu_cstates(void)
+{
+ impl_w_display_cpu_states(CSTATE);
+}
+
+struct power_entry {
+#ifndef __i386__
+ int dummy;
+#endif
+ int64_t type;
+ int64_t value;
+} __attribute__((packed));
+
+
+void perf_power_bundle::handle_trace_point(void *trace, int cpunr, uint64_t time)
+{
+ struct event_format *event;
+ struct pevent_record rec; /* holder */
+ class abstract_cpu *cpu;
+ int type;
+
+ rec.data = trace;
+
+ type = pevent_data_type(perf_event::pevent, &rec);
+ event = pevent_find_event(perf_event::pevent, type);
+
+ if (!event)
+ return;
+
+ if (cpunr >= (int)all_cpus.size()) {
+ cout << "INVALID cpu nr in handle_trace_point\n";
+ return;
+ }
+
+ cpu = all_cpus[cpunr];
+
+#if 0
+ unsigned int i;
+ printf("Time is %llu \n", time);
+ for (i = 0; i < system_level.children.size(); i++)
+ if (system_level.children[i])
+ system_level.children[i]->validate();
+#endif
+ unsigned long long val;
+ int ret;
+ if (strcmp(event->name, "cpu_idle")==0) {
+
+ ret = pevent_get_field_val(NULL, event, "state", &rec, &val, 0);
+ if (ret < 0) {
+ fprintf(stderr, _("cpu_idle event returned no state?\n"));
+ exit(-1);
+ }
+
+ if (val == (unsigned int)-1)
+ cpu->go_unidle(time);
+ else
+ cpu->go_idle(time);
+ }
+
+ if (strcmp(event->name, "power_frequency") == 0
+ || strcmp(event->name, "cpu_frequency") == 0){
+
+ ret = pevent_get_field_val(NULL, event, "state", &rec, &val, 0);
+ if (ret < 0) {
+ fprintf(stderr, _("power or cpu_frequency event returned no state?\n"));
+ exit(-1);
+ }
+
+ cpu->change_freq(time, val);
+ }
+
+ if (strcmp(event->name, "power_start")==0)
+ cpu->go_idle(time);
+ if (strcmp(event->name, "power_end")==0)
+ cpu->go_unidle(time);
+
+#if 0
+ unsigned int i;
+ for (i = 0; i < system_level.children.size(); i++)
+ if (system_level.children[i])
+ system_level.children[i]->validate();
+#endif
+}
+
+void process_cpu_data(void)
+{
+ unsigned int i;
+ system_level.reset_pstate_data();
+
+ perf_events->process();
+
+ for (i = 0; i < system_level.children.size(); i++)
+ if (system_level.children[i])
+ system_level.children[i]->validate();
+
+}
+
+void end_cpu_data(void)
+{
+ system_level.reset_pstate_data();
+
+ perf_events->clear();
+}
+
+void clear_cpu_data(void)
+{
+ if (perf_events)
+ perf_events->release();
+ delete perf_events;
+}
+
+
+void clear_all_cpus(void)
+{
+ unsigned int i;
+ for (i = 0; i < all_cpus.size(); i++) {
+ delete all_cpus[i];
+ }
+ all_cpus.clear();
+}
diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h
new file mode 100644
index 0000000..9114764
--- /dev/null
+++ b/src/cpu/cpu.h
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+
+#ifndef __INCLUDE_GUARD_CPUDEV_H
+#define __INCLUDE_GUARD_CPUDEV_H
+
+#include <iostream>
+#include <vector>
+#include <string>
+#include <stdint.h>
+#include <sys/time.h>
+
+using namespace std;
+
+class abstract_cpu;
+
+#define LEVEL_C0 -1
+#define LEVEL_HEADER -2
+
+#define PSTATE 1
+#define CSTATE 2
+
+struct idle_state {
+ char linux_name[16]; /* state0 etc.. cpuidle name */
+ char human_name[32];
+
+ uint64_t usage_before;
+ uint64_t usage_after;
+ uint64_t usage_delta;
+
+ uint64_t duration_before;
+ uint64_t duration_after;
+ uint64_t duration_delta;
+
+ int before_count;
+ int after_count;
+
+ int line_level;
+};
+
+struct frequency {
+ char human_name[32];
+ int line_level;
+
+ uint64_t freq;
+
+ uint64_t time_after;
+ uint64_t time_before;
+
+ int before_count;
+ int after_count;
+
+ double display_value;
+};
+
+class abstract_cpu
+{
+protected:
+ int first_cpu;
+ struct timeval stamp_before, stamp_after;
+ double time_factor;
+ uint64_t max_frequency = 0;
+ uint64_t max_minus_one_frequency = 0;
+
+ virtual void account_freq(uint64_t frequency, uint64_t duration);
+ virtual void freq_updated(uint64_t time);
+
+public:
+ uint64_t last_stamp;
+ uint64_t total_stamp;
+ int number;
+ int childcount;
+ const char* name;
+ bool idle, old_idle, has_intel_MSR;
+ uint64_t current_frequency;
+ uint64_t effective_frequency;
+
+ vector<class abstract_cpu *> children;
+ vector<struct idle_state *> cstates;
+ vector<struct frequency *> pstates;
+
+ virtual ~abstract_cpu();
+
+ class abstract_cpu *parent;
+
+
+ int get_first_cpu() { return first_cpu; }
+ void set_number(int _number, int cpu) {this->number = _number; this->first_cpu = cpu;};
+ void set_intel_MSR(bool _bool_value) {this->has_intel_MSR = _bool_value;};
+ void set_type(const char* _name) {this->name = _name;};
+ int get_number(void) { return number; };
+ const char* get_type(void) { return name; };
+
+ virtual void measurement_start(void);
+ virtual void measurement_end(void);
+
+ virtual int can_collapse(void) { return 0;};
+
+
+ /* C state related methods */
+
+ void insert_cstate(const char *linux_name, const char *human_name, uint64_t usage, uint64_t duration, int count, int level = -1);
+ void update_cstate(const char *linux_name, const char *human_name, uint64_t usage, uint64_t duration, int count, int level = -1);
+ void finalize_cstate(const char *linux_name, uint64_t usage, uint64_t duration, int count);
+
+ virtual int has_cstate_level(int level);
+
+ virtual char * fill_cstate_line(int line_nr, char *buffer, const char *separator="") { return buffer;};
+ virtual char * fill_cstate_percentage(int line_nr, char *buffer) { return buffer; };
+ virtual char * fill_cstate_time(int line_nr, char *buffer) { return buffer; };
+ virtual char * fill_cstate_name(int line_nr, char *buffer) { return buffer;};
+
+
+ /* P state related methods */
+ void insert_pstate(uint64_t freq, const char *human_name, uint64_t duration, int count);
+ void update_pstate(uint64_t freq, const char *human_name, uint64_t duration, int count);
+ void finalize_pstate(uint64_t freq, uint64_t duration, int count);
+
+
+ virtual char * fill_pstate_line(int line_nr, char *buffer) { return buffer;};
+ virtual char * fill_pstate_name(int line_nr, char *buffer) { return buffer;};
+ virtual int has_pstate_level(int level);
+ virtual int has_pstates(void) { return 1; };
+
+ /* Frequency micro accounting methods */
+ virtual void calculate_freq(uint64_t time);
+ virtual void go_idle(uint64_t time) { idle = true; freq_updated(time); }
+ virtual void go_unidle(uint64_t time) { idle = false; freq_updated(time); }
+ virtual void change_freq(uint64_t time, int freq) { current_frequency = freq; freq_updated(time); }
+
+ virtual void change_effective_frequency(uint64_t time, uint64_t freq);
+
+ virtual void wiggle(void);
+
+ virtual uint64_t total_pstate_time(void);
+
+ virtual void validate(void);
+ virtual void reset_pstate_data(void);
+};
+
+extern vector<class abstract_cpu *> all_cpus;
+
+class cpu_linux: public abstract_cpu
+{
+ void parse_pstates_start(void);
+ void parse_cstates_start(void);
+ void parse_pstates_end(void);
+ void parse_cstates_end(void);
+
+public:
+ virtual void measurement_start(void);
+ virtual void measurement_end(void);
+
+ virtual char * fill_cstate_line(int line_nr, char *buffer, const char *separator="");
+ virtual char * fill_cstate_name(int line_nr, char *buffer);
+ virtual char * fill_cstate_percentage(int line_nr, char *buffer);
+ virtual char * fill_cstate_time(int line_nr, char *buffer);
+
+ virtual char * fill_pstate_line(int line_nr, char *buffer);
+ virtual char * fill_pstate_name(int line_nr, char *buffer);
+};
+
+class cpu_core: public abstract_cpu
+{
+public:
+ virtual char * fill_cstate_line(int line_nr, char *buffer, const char *separator="");
+ virtual char * fill_cstate_name(int line_nr, char *buffer);
+
+ virtual char * fill_pstate_line(int line_nr, char *buffer);
+ virtual char * fill_pstate_name(int line_nr, char *buffer);
+
+ virtual int can_collapse(void) { return childcount == 1;};
+};
+
+class cpu_package: public abstract_cpu
+{
+protected:
+ virtual void freq_updated(uint64_t time);
+public:
+ virtual char * fill_cstate_line(int line_nr, char *buffer, const char *separator="");
+ virtual char * fill_cstate_name(int line_nr, char *buffer);
+
+ virtual char * fill_pstate_line(int line_nr, char *buffer);
+ virtual char * fill_pstate_name(int line_nr, char *buffer);
+ virtual int can_collapse(void) { return childcount == 1;};
+};
+
+extern void enumerate_cpus(void);
+
+extern void report_display_cpu_pstates(void);
+extern void report_display_cpu_cstates(void);
+
+
+
+extern void display_cpu_cstates(const char *start= "",
+ const char *end = "",
+ const char *linestart = "",
+ const char *separator = "| ",
+ const char *lineend = "\n");
+
+extern void w_display_cpu_cstates(void);
+extern void w_display_cpu_pstates(void);
+
+
+extern void start_cpu_measurement(void);
+extern void end_cpu_measurement(void);
+extern void process_cpu_data(void);
+extern void end_cpu_data(void);
+extern void clear_cpu_data(void);
+extern void clear_all_cpus(void);
+
+#endif
diff --git a/src/cpu/cpu_core.cpp b/src/cpu/cpu_core.cpp
new file mode 100644
index 0000000..e1372f7
--- /dev/null
+++ b/src/cpu/cpu_core.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <stdio.h>
+#include "cpu.h"
+#include "../lib.h"
+
+#include "../parameters/parameters.h"
+
+char * cpu_core::fill_cstate_line(int line_nr, char *buffer, const char *separator)
+{
+ unsigned int i;
+ buffer[0] = 0;
+
+ if (line_nr == LEVEL_HEADER)
+ sprintf(buffer, this->has_intel_MSR ? _(" Core(HW)"): _(" Core(OS)"));
+
+ for (i = 0; i < cstates.size(); i++) {
+ if (cstates[i]->line_level != line_nr)
+ continue;
+ sprintf(buffer,"%5.1f%%", percentage(cstates[i]->duration_delta / time_factor));
+ }
+
+ return buffer;
+}
+
+
+char * cpu_core::fill_cstate_name(int line_nr, char *buffer)
+{
+ unsigned int i;
+ buffer[0] = 0;
+
+ for (i = 0; i < cstates.size(); i++) {
+ if (cstates[i]->line_level != line_nr)
+ continue;
+
+ sprintf(buffer,"%s", cstates[i]->human_name);
+ }
+
+ return buffer;
+}
+
+
+
+char * cpu_core::fill_pstate_name(int line_nr, char *buffer)
+{
+ buffer[0] = 0;
+
+ if (line_nr >= (int)pstates.size() || line_nr < 0)
+ return buffer;
+
+ sprintf(buffer,"%s", pstates[line_nr]->human_name);
+
+ return buffer;
+}
+
+char * cpu_core::fill_pstate_line(int line_nr, char *buffer)
+{
+ buffer[0] = 0;
+ unsigned int i;
+
+ if (total_stamp ==0) {
+ for (i = 0; i < pstates.size(); i++)
+ total_stamp += pstates[i]->time_after;
+ if (total_stamp == 0)
+ total_stamp = 1;
+ }
+
+ if (line_nr == LEVEL_HEADER) {
+ sprintf(buffer,_(" Core"));
+ return buffer;
+ }
+
+ if (line_nr >= (int)pstates.size() || line_nr < 0)
+ return buffer;
+
+ sprintf(buffer," %5.1f%% ", percentage(1.0* (pstates[line_nr]->time_after) / total_stamp));
+ return buffer;
+}
diff --git a/src/cpu/cpu_linux.cpp b/src/cpu/cpu_linux.cpp
new file mode 100644
index 0000000..d7ce93d
--- /dev/null
+++ b/src/cpu/cpu_linux.cpp
@@ -0,0 +1,350 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <iostream>
+#include <fstream>
+
+#include "cpu.h"
+#include "../lib.h"
+
+#include <stdlib.h>
+
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+
+void cpu_linux::parse_cstates_start(void)
+{
+ ifstream file;
+ DIR *dir;
+ struct dirent *entry;
+ char filename[256];
+ int len;
+
+ len = snprintf(filename, sizeof(filename), "/sys/devices/system/cpu/cpu%i/cpuidle", number);
+
+ dir = opendir(filename);
+ if (!dir)
+ return;
+
+ /* For each C-state, there is a stateX directory which
+ * contains a 'usage' and a 'time' (duration) file */
+ while ((entry = readdir(dir))) {
+ char linux_name[64];
+ char human_name[64];
+ uint64_t usage = 0;
+ uint64_t duration = 0;
+
+
+ if (strlen(entry->d_name) < 3)
+ continue;
+
+ pt_strcpy(linux_name, entry->d_name);
+ pt_strcpy(human_name, linux_name);
+
+ snprintf(filename + len, sizeof(filename) - len, "/%s/name", entry->d_name);
+
+ file.open(filename, ios::in);
+ if (file) {
+ file.getline(human_name, sizeof(human_name));
+ file.close();
+ }
+
+ if (strcmp(human_name, "C0")==0)
+ pt_strcpy(human_name, _("C0 polling"));
+
+ snprintf(filename + len, sizeof(filename) - len, "/%s/usage", entry->d_name);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> usage;
+ file.close();
+ } else
+ continue;
+
+ snprintf(filename + len, sizeof(filename) - len, "/%s/time", entry->d_name);
+
+ file.open(filename, ios::in);
+ if (file) {
+ file >> duration;
+ file.close();
+ }
+
+
+ update_cstate(linux_name, human_name, usage, duration, 1);
+
+ }
+ closedir(dir);
+}
+
+
+void cpu_linux::parse_pstates_start(void)
+{
+ ifstream file;
+ char filename[256];
+ unsigned int i;
+
+ last_stamp = 0;
+ for (i = 0; i < children.size(); i++)
+ if (children[i])
+ children[i]->wiggle();
+
+ snprintf(filename, sizeof(filename), "/sys/devices/system/cpu/cpu%i/cpufreq/stats/time_in_state", first_cpu);
+
+ file.open(filename, ios::in);
+
+ if (file) {
+ char line[1024];
+
+ while (file) {
+ uint64_t f;
+ file.getline(line, sizeof(line));
+ f = strtoull(line, NULL, 10);
+ account_freq(f, 0);
+ }
+ file.close();
+ }
+ account_freq(0, 0);
+}
+
+void cpu_linux::measurement_start(void)
+{
+ abstract_cpu::measurement_start();
+ parse_cstates_start();
+ parse_pstates_start();
+}
+
+void cpu_linux::parse_cstates_end(void)
+{
+ DIR *dir;
+ struct dirent *entry;
+ char filename[256];
+ ifstream file;
+ int len;
+
+ len = snprintf(filename, sizeof(filename), "/sys/devices/system/cpu/cpu%i/cpuidle", number);
+
+ dir = opendir(filename);
+ if (!dir)
+ return;
+
+ /* For each C-state, there is a stateX directory which
+ * contains a 'usage' and a 'time' (duration) file */
+ while ((entry = readdir(dir))) {
+ char linux_name[64];
+ char human_name[64];
+ uint64_t usage = 0;
+ uint64_t duration = 0;
+
+
+ if (strlen(entry->d_name) < 3)
+ continue;
+
+ pt_strcpy(linux_name, entry->d_name);
+ pt_strcpy(human_name, linux_name);
+
+
+ snprintf(filename + len, sizeof(filename) - len, "/%s/usage", entry->d_name);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> usage;
+ file.close();
+ } else
+ continue;
+
+ snprintf(filename + len, sizeof(filename) - len, "/%s/time", entry->d_name);
+
+ file.open(filename, ios::in);
+ if (file) {
+ file >> duration;
+ file.close();
+ }
+
+
+ finalize_cstate(linux_name, usage, duration, 1);
+
+ }
+ closedir(dir);
+}
+
+void cpu_linux::parse_pstates_end(void)
+{
+ char filename[256];
+ ifstream file;
+
+ snprintf(filename, sizeof(filename), "/sys/devices/system/cpu/cpu%i/cpufreq/stats/time_in_state", number);
+
+ file.open(filename, ios::in);
+
+ if (file) {
+ char line[1024];
+
+ while (file) {
+ uint64_t f,count;
+ char *c;
+
+ memset(line, 0, sizeof(line));
+
+ file.getline(line, sizeof(line));
+
+ f = strtoull(line, &c, 10);
+ if (!c)
+ break;
+
+ count = strtoull(c, NULL, 10);
+
+ if (f > 0)
+ finalize_pstate(f, count, 1);
+
+
+ }
+ file.close();
+ }
+}
+
+void cpu_linux::measurement_end(void)
+{
+ parse_cstates_end();
+ parse_pstates_end();
+ abstract_cpu::measurement_end();
+}
+
+char * cpu_linux::fill_cstate_line(int line_nr, char *buffer, const char *separator)
+{
+ unsigned int i;
+ buffer[0] = 0;
+
+ if (line_nr == LEVEL_HEADER) {
+ sprintf(buffer,_(" CPU(OS) %i"), number);
+ return buffer;
+ }
+
+ for (i = 0; i < cstates.size(); i++) {
+ if (cstates[i]->line_level != line_nr)
+ continue;
+
+ if (line_nr == LEVEL_C0)
+ sprintf(buffer,"%5.1f%%", percentage(cstates[i]->duration_delta / time_factor));
+ else
+ sprintf(buffer,"%5.1f%%%s %6.1f ms",
+ percentage(cstates[i]->duration_delta / time_factor),
+ separator,
+ 1.0 * cstates[i]->duration_delta / (1 + cstates[i]->usage_delta) / 1000);
+ }
+
+ return buffer;
+}
+
+char * cpu_linux::fill_cstate_percentage(int line_nr, char *buffer)
+{
+ unsigned int i;
+ buffer[0] = 0;
+
+ for (i = 0; i < cstates.size(); i++) {
+ if (cstates[i]->line_level != line_nr)
+ continue;
+
+ sprintf(buffer,"%5.1f%%",
+ percentage(cstates[i]->duration_delta / time_factor));
+ break;
+ }
+
+ return buffer;
+}
+
+char * cpu_linux::fill_cstate_time(int line_nr, char *buffer)
+{
+ unsigned int i;
+ buffer[0] = 0;
+
+ if (line_nr == LEVEL_C0)
+ return buffer;
+
+ for (i = 0; i < cstates.size(); i++) {
+ if (cstates[i]->line_level != line_nr)
+ continue;
+
+ sprintf(buffer,"%6.1f ms",
+ 1.0 * cstates[i]->duration_delta /
+ (1 + cstates[i]->usage_delta) / 1000);
+ break;
+ }
+
+ return buffer;
+}
+
+char * cpu_linux::fill_cstate_name(int line_nr, char *buffer)
+{
+ unsigned int i;
+ buffer[0] = 0;
+
+ for (i = 0; i < cstates.size(); i++) {
+ if (cstates[i]->line_level != line_nr)
+ continue;
+
+ sprintf(buffer,"%s", cstates[i]->human_name);
+ }
+
+ return buffer;
+}
+
+
+char * cpu_linux::fill_pstate_name(int line_nr, char *buffer)
+{
+ buffer[0] = 0;
+
+ if (line_nr >= (int)pstates.size() || line_nr < 0)
+ return buffer;
+
+ sprintf(buffer,"%s", pstates[line_nr]->human_name);
+
+ return buffer;
+}
+
+char * cpu_linux::fill_pstate_line(int line_nr, char *buffer)
+{
+ buffer[0] = 0;
+
+ if (total_stamp ==0) {
+ unsigned int i;
+ for (i = 0; i < pstates.size(); i++)
+ total_stamp += pstates[i]->time_after;
+ if (total_stamp == 0)
+ total_stamp = 1;
+ }
+
+ if (line_nr == LEVEL_HEADER) {
+ sprintf(buffer,_(" CPU %i"), number);
+ return buffer;
+ }
+
+ if (line_nr >= (int)pstates.size() || line_nr < 0)
+ return buffer;
+
+ sprintf(buffer," %5.1f%% ", percentage(1.0* (pstates[line_nr]->time_after) / total_stamp));
+ return buffer;
+}
diff --git a/src/cpu/cpu_package.cpp b/src/cpu/cpu_package.cpp
new file mode 100644
index 0000000..926a484
--- /dev/null
+++ b/src/cpu/cpu_package.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <stdio.h>
+#include "cpu.h"
+#include "../lib.h"
+#include "../parameters/parameters.h"
+
+void cpu_package::freq_updated(uint64_t time)
+{
+ if (parent)
+ parent->calculate_freq(time);
+ /*
+ * Make the frequency changes to propagate to all cores in a package.
+ */
+ change_effective_frequency(time, current_frequency);
+ old_idle = idle;
+}
+
+char * cpu_package::fill_cstate_line(int line_nr, char *buffer, const char *separator)
+{
+ unsigned int i;
+ buffer[0] = 0;
+
+ if (line_nr == LEVEL_HEADER) {
+ sprintf(buffer, this->has_intel_MSR ? _(" Pkg(HW)"): _(" Pkg(OS)"));
+ }
+
+ for (i = 0; i < cstates.size(); i++) {
+ if (cstates[i]->line_level != line_nr)
+ continue;
+
+ sprintf(buffer,"%5.1f%%", percentage(cstates[i]->duration_delta / time_factor));
+ }
+
+ return buffer;
+}
+
+
+char * cpu_package::fill_cstate_name(int line_nr, char *buffer)
+{
+ unsigned int i;
+ buffer[0] = 0;
+
+ for (i = 0; i < cstates.size(); i++) {
+ if (cstates[i]->line_level != line_nr)
+ continue;
+
+ sprintf(buffer,"%s", cstates[i]->human_name);
+ }
+
+ return buffer;
+}
+
+
+
+char * cpu_package::fill_pstate_name(int line_nr, char *buffer)
+{
+ buffer[0] = 0;
+
+ if (line_nr >= (int)pstates.size() || line_nr < 0)
+ return buffer;
+
+ sprintf(buffer,"%s", pstates[line_nr]->human_name);
+
+ return buffer;
+}
+
+char * cpu_package::fill_pstate_line(int line_nr, char *buffer)
+{
+ buffer[0] = 0;
+ unsigned int i;
+
+ if (total_stamp ==0) {
+ for (i = 0; i < pstates.size(); i++)
+ total_stamp += pstates[i]->time_after;
+ if (total_stamp == 0)
+ total_stamp = 1;
+ }
+
+
+ if (line_nr == LEVEL_HEADER) {
+ sprintf(buffer,_(" Package"));
+ return buffer;
+ }
+
+ if (line_nr >= (int)pstates.size() || line_nr < 0)
+ return buffer;
+
+ sprintf(buffer," %5.1f%% ", percentage(1.0* (pstates[line_nr]->time_after) / total_stamp));
+ return buffer;
+}
diff --git a/src/cpu/cpu_rapl_device.cpp b/src/cpu/cpu_rapl_device.cpp
new file mode 100644
index 0000000..357a1c8
--- /dev/null
+++ b/src/cpu/cpu_rapl_device.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Srinivas Pandruvada<Srinivas.Pandruvada@linux.intel.com>
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "../parameters/parameters.h"
+#include "cpu_rapl_device.h"
+
+cpu_rapl_device::cpu_rapl_device(cpudevice *parent, const char *classname, const char *dev_name, class abstract_cpu *_cpu)
+ : cpudevice(classname, dev_name, _cpu),
+ device_valid(false)
+{
+ if (_cpu)
+ rapl = new c_rapl_interface(dev_name, cpu->get_first_cpu());
+ else
+ rapl = new c_rapl_interface();
+ last_time = time(NULL);
+ if (rapl->pp0_domain_present()) {
+ device_valid = true;
+ parent->add_child(this);
+ rapl->get_pp0_energy_status(&last_energy);
+ }
+}
+
+void cpu_rapl_device::start_measurement(void)
+{
+ last_time = time(NULL);
+
+ rapl->get_pp0_energy_status(&last_energy);
+}
+
+void cpu_rapl_device::end_measurement(void)
+{
+ time_t curr_time = time(NULL);
+ double energy;
+
+ consumed_power = 0.0;
+ if ((curr_time - last_time) > 0) {
+ rapl->get_pp0_energy_status(&energy);
+ consumed_power = (energy-last_energy)/(curr_time-last_time);
+ last_energy = energy;
+ last_time = curr_time;
+ }
+}
+
+double cpu_rapl_device::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ if (rapl->pp0_domain_present())
+ return consumed_power;
+ else
+ return 0.0;
+}
diff --git a/src/cpu/cpu_rapl_device.h b/src/cpu/cpu_rapl_device.h
new file mode 100644
index 0000000..407f2da
--- /dev/null
+++ b/src/cpu/cpu_rapl_device.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Srinivas Pandruvada <Srinivas.Pandruvada@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_CPU_RAPL_DEVICE_H
+#define _INCLUDE_GUARD_CPU_RAPL_DEVICE_H
+
+#include <vector>
+#include <string>
+
+using namespace std;
+
+#include <sys/time.h>
+#include "cpudevice.h"
+#include "rapl/rapl_interface.h"
+
+class cpu_rapl_device: public cpudevice {
+
+ c_rapl_interface *rapl;
+ time_t last_time;
+ double last_energy;
+ double consumed_power;
+ bool device_valid;
+
+public:
+ cpu_rapl_device(cpudevice *parent, const char *classname = "cpu_core", const char *device_name = "cpu_core", class abstract_cpu *_cpu = NULL);
+ ~cpu_rapl_device() { delete rapl; }
+ virtual const char * device_name(void) {return "CPU core";};
+ bool device_present() { return device_valid;}
+ virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+};
+
+
+#endif
diff --git a/src/cpu/cpudevice.cpp b/src/cpu/cpudevice.cpp
new file mode 100644
index 0000000..4c7ca7b
--- /dev/null
+++ b/src/cpu/cpudevice.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include "cpudevice.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "../lib.h"
+#include "../parameters/parameters.h"
+
+
+cpudevice::cpudevice(const char *classname, const char *dev_name, class abstract_cpu *_cpu)
+{
+ pt_strcpy(_class, classname);
+ pt_strcpy(_cpuname, dev_name);
+ cpu = _cpu;
+ wake_index = get_param_index("cpu-wakeups");;
+ consumption_index = get_param_index("cpu-consumption");;
+ r_wake_index = get_result_index("cpu-wakeups");;
+ r_consumption_index = get_result_index("cpu-consumption");;
+}
+
+const char * cpudevice::device_name(void)
+{
+ if (child_devices.size())
+ return "CPU misc";
+ else
+ return "CPU use";
+}
+
+double cpudevice::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ double power;
+ double factor;
+ double _utilization;
+ double child_power;
+
+ power = 0;
+ factor = get_parameter_value(wake_index, bundle);
+ _utilization = get_result_value(r_wake_index, result);
+
+ power += _utilization * factor / 10000.0;
+
+ factor = get_parameter_value(consumption_index, bundle);
+ _utilization = get_result_value(r_consumption_index, result);
+
+ power += _utilization * factor;
+
+ for (unsigned int i = 0; i < child_devices.size(); ++i) {
+ child_power = child_devices[i]->power_usage(result, bundle);
+ if ((power - child_power) > 0.0)
+ power -= child_power;
+ }
+
+ return power;
+}
+
+double cpudevice::utilization(void)
+{
+ double _utilization;
+ _utilization = get_result_value(r_consumption_index);
+
+ return _utilization * 100;
+
+}
diff --git a/src/cpu/cpudevice.h b/src/cpu/cpudevice.h
new file mode 100644
index 0000000..841a101
--- /dev/null
+++ b/src/cpu/cpudevice.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_CPUDEVICE_H
+#define _INCLUDE_GUARD_CPUDEVICE_H
+
+#include <vector>
+#include <string>
+
+using namespace std;
+
+#include "../devices/device.h"
+#include "cpu.h"
+
+class cpudevice: public device {
+protected:
+ char _class[128];
+ char _cpuname[128];
+
+ vector<string> params;
+ class abstract_cpu *cpu;
+ int wake_index;
+ int consumption_index;
+ int r_wake_index;
+ int r_consumption_index;
+
+ vector<device *>child_devices;
+
+public:
+ cpudevice(const char *classname = "cpu", const char *device_name = "cpu0", class abstract_cpu *_cpu = NULL);
+ virtual const char * class_name(void) { return _class;};
+
+ virtual const char * device_name(void);
+
+ virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
+ virtual bool show_in_list(void) {return false;};
+ virtual double utilization(void); /* percentage */
+ void add_child(device *dev_ptr) { child_devices.push_back(dev_ptr);}
+};
+
+
+#endif \ No newline at end of file
diff --git a/src/cpu/dram_rapl_device.cpp b/src/cpu/dram_rapl_device.cpp
new file mode 100644
index 0000000..36d47a2
--- /dev/null
+++ b/src/cpu/dram_rapl_device.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Srinivas Pandruvada <Srinivas.Pandruvada@linux.intel.com>
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "../parameters/parameters.h"
+#include "dram_rapl_device.h"
+
+
+dram_rapl_device::dram_rapl_device(cpudevice *parent, const char *classname, const char *dev_name, class abstract_cpu *_cpu)
+ : cpudevice(classname, dev_name, _cpu),
+ device_valid(false)
+{
+ if (_cpu)
+ rapl = new c_rapl_interface(dev_name, cpu->get_first_cpu());
+ else
+ rapl = new c_rapl_interface();
+ last_time = time(NULL);
+ if (rapl->dram_domain_present()) {
+ device_valid = true;
+ parent->add_child(this);
+ rapl->get_dram_energy_status(&last_energy);
+ }
+}
+
+void dram_rapl_device::start_measurement(void)
+{
+ last_time = time(NULL);
+
+ rapl->get_dram_energy_status(&last_energy);
+}
+
+void dram_rapl_device::end_measurement(void)
+{
+ time_t curr_time = time(NULL);
+ double energy;
+
+ consumed_power = 0.0;
+ if ((curr_time - last_time) > 0) {
+ rapl->get_dram_energy_status(&energy);
+ consumed_power = (energy-last_energy)/(curr_time-last_time);
+ last_energy = energy;
+ last_time = curr_time;
+ }
+}
+
+double dram_rapl_device::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ if (rapl->dram_domain_present())
+ return consumed_power;
+ else
+ return 0.0;
+}
diff --git a/src/cpu/dram_rapl_device.h b/src/cpu/dram_rapl_device.h
new file mode 100644
index 0000000..dc53094
--- /dev/null
+++ b/src/cpu/dram_rapl_device.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Srinivas Pandruvada <Srinivas.Pandruvada@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_DRAM_RAPL_DEVICE_H
+#define _INCLUDE_GUARD_DRAM_RAPL_DEVICE_H
+
+#include <vector>
+#include <string>
+
+using namespace std;
+
+#include <sys/time.h>
+#include "cpudevice.h"
+#include "rapl/rapl_interface.h"
+
+class dram_rapl_device: public cpudevice {
+
+ c_rapl_interface *rapl;
+ time_t last_time;
+ double last_energy;
+ double consumed_power;
+ bool device_valid;
+
+public:
+ dram_rapl_device(cpudevice *parent, const char *classname = "dram_core", const char *device_name = "dram_core", class abstract_cpu *_cpu = NULL);
+ ~dram_rapl_device() { delete rapl; }
+ virtual const char * device_name(void) {return "DRAM";};
+ bool device_present() { return device_valid;}
+ virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
+ void start_measurement(void);
+ void end_measurement(void);
+
+};
+
+
+#endif
diff --git a/src/cpu/intel_cpus.cpp b/src/cpu/intel_cpus.cpp
new file mode 100644
index 0000000..a7145d7
--- /dev/null
+++ b/src/cpu/intel_cpus.cpp
@@ -0,0 +1,757 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include "intel_cpus.h"
+#include <iostream>
+#include <fstream>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <limits.h>
+
+#include "../lib.h"
+#include "../parameters/parameters.h"
+#include "../display.h"
+
+static int intel_cpu_models[] = {
+ 0x1A, /* Core i7, Xeon 5500 series */
+ 0x1E, /* Core i7 and i5 Processor - Lynnfield Jasper Forest */
+ 0x1F, /* Core i7 and i5 Processor - Nehalem */
+ 0x25, /* Westmere */
+ 0x27, /* Medfield Atom */
+ 0x2A, /* SNB */
+ 0x2C, /* Westmere */
+ 0x2D, /* SNB Xeon */
+ 0x2E, /* Nehalem-EX Xeon */
+ 0x2F, /* Westmere-EX Xeon */
+ 0x37, /* BYT-M */
+ 0x3A, /* IVB */
+ 0x3C, /* HSW */
+ 0x3D, /* BDW */
+ 0x3E, /* IVB Xeon */
+ 0x3F, /* HSX */
+ 0x45, /* HSW-ULT */
+ 0x46, /* HSW-G */
+ 0x47, /* BDW-H */
+ 0x4C, /* BSW */
+ 0x4D, /* AVN */
+ 0x4F, /* BDX */
+ 0x4E, /* SKY */
+ 0x55, /* SKY-X */
+ 0x56, /* BDX-DE */
+ 0x5C, /* BXT-P */
+ 0x5E, /* SKY */
+ 0x5F, /* DNV */
+ 0x66, /* CNL-U/Y */
+ 0x6A, /* ICL_X*/
+ 0x7A, /* GLK */
+ 0x7D, /* ICL_DESKTOP */
+ 0x7E, /* ICL_MOBILE */
+ 0x8A, /* LKF */
+ 0x8C, /* TGL_MOBILE */
+ 0x8D, /* TGL_DESKTOP */
+ 0x8E, /* KBL_MOBILE */
+ 0X8F, /* SAPPHIRERAPIDS_X */
+ 0x96, /* EHL */
+ 0x97, /* ADL_DESKTOP */
+ 0x9A, /* ADL_MOBILE */
+ 0x9C, /* JSL */
+ 0x9D, /* ICL_NNPI */
+ 0x9E, /* KBL_DESKTOP */
+ 0xA5, /* CML_DESKTOP */
+ 0xA6, /* CML_MOBILE */
+ 0xA7, /* RKL_DESKTOP */
+ 0xAA, /* MTL_MOBILE */
+ 0xAC, /* MTL_DESKTOP */
+ 0xB7, /* RPL_DESKTOP */
+ 0xBA, /* RPL_P */
+ 0xBE, /* ADL_N */
+ 0xBF, /* RPL_S */
+ 0 /* last entry must be zero */
+};
+
+static int intel_pstate_driver_loaded = -1;
+
+int is_supported_intel_cpu(int model, int cpu)
+{
+ int i;
+ uint64_t msr;
+
+ for (i = 0; intel_cpu_models[i] != 0; i++)
+ if (model == intel_cpu_models[i])
+ if (cpu < 0 || read_msr(cpu, MSR_APERF, &msr) >= 0)
+ return 1;
+
+ return 0;
+}
+
+int is_intel_pstate_driver_loaded()
+{
+ const char *filename = "/sys/devices/system/cpu/cpu0/cpufreq/scaling_driver";
+ const string intel_pstate("intel_pstate");
+ char line[32] = { '\0' };
+ ifstream file;
+
+ if (intel_pstate_driver_loaded > -1)
+ return intel_pstate_driver_loaded;
+
+ file.open(filename, ios::in);
+
+ if (!file)
+ return -1;
+
+ file.getline(line, sizeof(line)-1);
+ file.close();
+
+ const string scaling_driver(line);
+ if (scaling_driver == intel_pstate) {
+ intel_pstate_driver_loaded = 1;
+ } else {
+ intel_pstate_driver_loaded = 0;
+ }
+
+ return intel_pstate_driver_loaded;
+}
+
+static uint64_t get_msr(int cpu, uint64_t offset)
+{
+ ssize_t retval;
+ uint64_t msr;
+
+ retval = read_msr(cpu, offset, &msr);
+ if (retval < 0) {
+ reset_display();
+ fprintf(stderr, _("read_msr cpu%d 0x%llx : "), cpu, (unsigned long long)offset);
+ fprintf(stderr, "%s\n", strerror(errno));
+ exit(-2);
+ }
+
+ return msr;
+}
+
+intel_util::intel_util()
+{
+ byt_ahci_support=0;
+}
+
+void intel_util::byt_has_ahci()
+{
+ dir = opendir("/sys/bus/pci/devices/0000:00:13.0");
+ if (!dir)
+ byt_ahci_support=0;
+ else {
+ byt_ahci_support=1;
+ closedir(dir);
+ }
+}
+
+int intel_util::get_byt_ahci_support()
+{
+ return byt_ahci_support;
+}
+
+nhm_core::nhm_core(int model)
+{
+ has_c7_res = 0;
+
+ switch(model) {
+ case 0x2A: /* SNB */
+ case 0x2D: /* SNB Xeon */
+ case 0x3A: /* IVB */
+ case 0x3C: /* HSW */
+ case 0x3D: /* BDW */
+ case 0x3E: /* IVB Xeon */
+ case 0x45: /* HSW-ULT */
+ case 0x4E: /* SKY */
+ case 0x55: /* SKY-X */
+ case 0x5E: /* SKY */
+ case 0x5F: /* DNV */
+ case 0x5C: /* BXT-P */
+ case 0x66: /* CNL-U/Y */
+ case 0x6A: /* ICL_X*/
+ case 0x7A: /* GLK */
+ case 0x7D: /* ICL_DESKTOP */
+ case 0x7E: /* ICL_MOBILE */
+ case 0x8A: /* LKF */
+ case 0x8C: /* TGL_MOBILE */
+ case 0x8D: /* TGL_DESKTOP */
+ case 0x8E: /* KBL_MOBILE */
+ case 0x8F: /* SAPPHIRERAPIDS_X */
+ case 0x96: /* EHL */
+ case 0x97: /* ADL_DESKTOP */
+ case 0x9A: /* ADL_MOBILE */
+ case 0x9C: /* JSL */
+ case 0x9D: /* ICL_NNPI */
+ case 0x9E: /* KBL_DESKTOP */
+ case 0xA5: /* CML_DESKTOP */
+ case 0xA6: /* CML_MOBILE */
+ case 0xA7: /* RKL_DESKTOP */
+ case 0xAA: /* MTL_MOBILE */
+ case 0xAC: /* MTL_DESKTOP */
+ case 0xB7: /* RPL_DESKTOP */
+ case 0xBA: /* RPL_P */
+ case 0xBE: /* ADL_N */
+ case 0xBF: /* RPL_S */
+ has_c7_res = 1;
+ }
+
+ has_c3_res = 1;
+ has_c1_res = 0;
+
+ switch (model) {
+ case 0x37: /* BYT-M does not support C3/C4 */
+ case 0x4C: /* BSW does not support C3 */
+ has_c3_res = 0;
+ has_c1_res = 1;
+ }
+
+}
+
+void nhm_core::measurement_start(void)
+{
+ ifstream file;
+ char filename[PATH_MAX];
+
+ /* the abstract function needs to be first since it clears all state */
+ abstract_cpu::measurement_start();
+
+ last_stamp = 0;
+
+ if (this->has_c1_res)
+ c1_before = get_msr(first_cpu, MSR_CORE_C1_RESIDENCY);
+ if (this->has_c3_res)
+ c3_before = get_msr(first_cpu, MSR_CORE_C3_RESIDENCY);
+ c6_before = get_msr(first_cpu, MSR_CORE_C6_RESIDENCY);
+ if (this->has_c7_res)
+ c7_before = get_msr(first_cpu, MSR_CORE_C7_RESIDENCY);
+ tsc_before = get_msr(first_cpu, MSR_TSC);
+
+ if (this->has_c1_res)
+ insert_cstate("core c1", "C1 (cc1)", 0, c1_before, 1);
+ if (this->has_c3_res)
+ insert_cstate("core c3", "C3 (cc3)", 0, c3_before, 1);
+ insert_cstate("core c6", "C6 (cc6)", 0, c6_before, 1);
+ if (this->has_c7_res) {
+ insert_cstate("core c7", "C7 (cc7)", 0, c7_before, 1);
+ }
+
+
+ snprintf(filename, sizeof(filename), "/sys/devices/system/cpu/cpu%i/cpufreq/stats/time_in_state", first_cpu);
+
+ file.open(filename, ios::in);
+
+ if (file) {
+ char line[1024];
+
+ while (file) {
+ uint64_t f;
+ file.getline(line, 1024);
+ f = strtoull(line, NULL, 10);
+ account_freq(f, 0);
+ }
+ file.close();
+ }
+ account_freq(0, 0);
+
+}
+
+void nhm_core::measurement_end(void)
+{
+ unsigned int i;
+ uint64_t time_delta;
+ double ratio;
+
+ if (this->has_c1_res)
+ c1_after = get_msr(first_cpu, MSR_CORE_C1_RESIDENCY);
+ if (this->has_c3_res)
+ c3_after = get_msr(first_cpu, MSR_CORE_C3_RESIDENCY);
+ c6_after = get_msr(first_cpu, MSR_CORE_C6_RESIDENCY);
+ if (this->has_c7_res)
+ c7_after = get_msr(first_cpu, MSR_CORE_C7_RESIDENCY);
+ tsc_after = get_msr(first_cpu, MSR_TSC);
+
+ if (this->has_c1_res)
+ finalize_cstate("core c1", 0, c1_after, 1);
+ if (this->has_c3_res)
+ finalize_cstate("core c3", 0, c3_after, 1);
+ finalize_cstate("core c6", 0, c6_after, 1);
+ if (this->has_c7_res)
+ finalize_cstate("core c7", 0, c7_after, 1);
+
+ gettimeofday(&stamp_after, NULL);
+
+ time_factor = 1000000.0 * (stamp_after.tv_sec - stamp_before.tv_sec) + stamp_after.tv_usec - stamp_before.tv_usec;
+
+ for (i = 0; i < children.size(); i++)
+ if (children[i]) {
+ children[i]->measurement_end();
+ children[i]->wiggle();
+ }
+
+ time_delta = 1000000 * (stamp_after.tv_sec - stamp_before.tv_sec) + stamp_after.tv_usec - stamp_before.tv_usec;
+
+ ratio = 1.0 * time_delta / (tsc_after - tsc_before);
+
+ for (i = 0; i < cstates.size(); i++) {
+ struct idle_state *state = cstates[i];
+
+ if (state->after_count == 0)
+ continue;
+
+ if (state->after_count != state->before_count)
+ continue;
+
+ state->usage_delta = ratio * (state->usage_after - state->usage_before) / state->after_count;
+ state->duration_delta = ratio * (state->duration_after - state->duration_before) / state->after_count;
+ }
+
+#if 0
+ for (i = 0; i < children.size(); i++)
+ if (children[i]) {
+ for (j = 0; j < children[i]->pstates.size(); j++) {
+ struct frequency *state;
+ state = children[i]->pstates[j];
+ if (!state)
+ continue;
+
+ update_pstate( state->freq, state->human_name, state->time_before, state->before_count);
+ finalize_pstate(state->freq, state->time_after, state->after_count);
+ }
+ }
+#endif
+ total_stamp = 0;
+}
+
+char * nhm_core::fill_pstate_line(int line_nr, char *buffer)
+{
+ const int intel_pstate = is_intel_pstate_driver_loaded();
+ buffer[0] = 0;
+ unsigned int i;
+
+ if (!intel_pstate && total_stamp ==0) {
+ for (i = 0; i < pstates.size(); i++)
+ total_stamp += pstates[i]->time_after;
+ if (total_stamp == 0)
+ total_stamp = 1;
+ }
+
+ if (line_nr == LEVEL_HEADER) {
+ sprintf(buffer,_(" Core"));
+ return buffer;
+ }
+
+ if (intel_pstate > 0 || line_nr >= (int)pstates.size() || line_nr < 0)
+ return buffer;
+
+ sprintf(buffer," %5.1f%% ", percentage(1.0* (pstates[line_nr]->time_after) / total_stamp));
+
+ return buffer;
+}
+
+nhm_package::nhm_package(int model)
+{
+ has_c8c9c10_res = 0;
+ has_c2c6_res = 0;
+ has_c7_res = 0;
+ has_c6c_res = 0;
+
+ switch(model) {
+ case 0x2A: /* SNB */
+ case 0x2D: /* SNB Xeon */
+ case 0x3A: /* IVB */
+ case 0x3C: /* HSW */
+ case 0x3D: /* BDW */
+ case 0x3E: /* IVB Xeon */
+ case 0x45: /* HSW-ULT */
+ case 0x4E: /* SKY */
+ case 0x55: /* SKY-X */
+ case 0x5C: /* BXT-P */
+ case 0x5E: /* SKY */
+ case 0x5F: /* DNV */
+ case 0x66: /* CNL-U/Y */
+ case 0x6A: /* ICL_X*/
+ case 0x7A: /* GLK */
+ case 0x7D: /* ICL_DESKTOP */
+ case 0x7E: /* ICL_MOBILE */
+ case 0x8A: /* LKF */
+ case 0x8C: /* TGL_MOBILE */
+ case 0x8D: /* TGL_DESKTOP */
+ case 0x8E: /* KBL_MOBILE */
+ case 0x8F: /* SAPPHIRERAPIDS_X */
+ case 0x96: /* EHL */
+ case 0x97: /* ADL_DESKTOP */
+ case 0X9A: /* ADL_MOBILE */
+ case 0x9C: /* JSL */
+ case 0x9D: /* ICL_NNPI */
+ case 0x9E: /* KBL_DESKTOP */
+ case 0xA5: /* CML_DESKTOP */
+ case 0xA6: /* CML_MOBILE */
+ case 0xA7: /* RKL_DESKTOP */
+ case 0xAA: /* MTL_MOBILE */
+ case 0xAC: /* MTL_DESKTOP */
+ case 0xB7: /* RPL_DESKTOP */
+ case 0xBA: /* RPL_P */
+ case 0xBE: /* ADL_N */
+ case 0xBF: /* RPL_S */
+ has_c2c6_res=1;
+ has_c7_res = 1;
+ }
+
+ has_c3_res = 1;
+
+ switch(model) {
+ /* BYT-M doesn't have C3 or C7 */
+ /* BYT-T doesn't have C3 but it has C7 */
+ case 0x37:
+ has_c2c6_res=1;
+ this->byt_has_ahci();
+ if ((this->get_byt_ahci_support()) == 0)
+ has_c7_res = 1;/*BYT-T PC7 <- S0iX*/
+ else
+ has_c7_res = 0;
+ break;
+ case 0x4C: /* BSW doesn't have C3 */
+ has_c3_res = 0;
+ has_c6c_res = 1; /* BSW only exposes package C6 */
+ break;
+ }
+
+ /*Has C8/9/10*/
+ switch(model) {
+ case 0x3D: /* BDW */
+ case 0x45: /* HSW */
+ case 0x4E: /* SKY */
+ case 0x5C: /* BXT-P */
+ case 0x5E: /* SKY */
+ case 0x5F: /* DNV */
+ case 0x66: /* CNL-U/Y */
+ case 0x7A: /* GLK */
+ case 0x7D: /* ICL_DESKTOP */
+ case 0x7E: /* ICL_MOBILE */
+ case 0x8A: /* LKF */
+ case 0x8C: /* TGL_MOBILE */
+ case 0x8D: /* TGL_DESKTOP */
+ case 0x8E: /* KBL_MOBILE */
+ case 0x96: /* EHL */
+ case 0x97: /* ADL_DESKTOP */
+ case 0x9A: /* ADL_MOBILE */
+ case 0x9C: /* JSL */
+ case 0x9D: /* ICL_NNPI */
+ case 0x9E: /* KBL_DESKTOP */
+ case 0xA5: /* CML_DESKTOP */
+ case 0xA6: /* CML_MOBILE */
+ case 0xA7: /* RKL_DESKTOP */
+ case 0xAA: /* MTL_MOBILE */
+ case 0xAC: /* MTL_DESKTOP */
+ case 0xB7: /* RPL_DESKTOP */
+ case 0xBA: /* RPL_P */
+ case 0xBE: /* ADL_N */
+ case 0xBF: /* RPL_S */
+ has_c8c9c10_res = 1;
+ break;
+ }
+}
+
+char * nhm_package::fill_pstate_line(int line_nr, char *buffer)
+{
+ const int intel_pstate = is_intel_pstate_driver_loaded();
+ buffer[0] = 0;
+ unsigned int i;
+
+ if (!intel_pstate && total_stamp ==0) {
+ for (i = 0; i < pstates.size(); i++)
+ total_stamp += pstates[i]->time_after;
+ if (total_stamp == 0)
+ total_stamp = 1;
+ }
+
+
+ if (line_nr == LEVEL_HEADER) {
+ sprintf(buffer,_(" Package"));
+ return buffer;
+ }
+
+ if (intel_pstate > 0 || line_nr >= (int)pstates.size() || line_nr < 0)
+ return buffer;
+
+ sprintf(buffer," %5.1f%% ", percentage(1.0* (pstates[line_nr]->time_after) / total_stamp));
+
+ return buffer;
+}
+
+
+
+void nhm_package::measurement_start(void)
+{
+ abstract_cpu::measurement_start();
+
+ last_stamp = 0;
+
+ if (this->has_c2c6_res)
+ c2_before = get_msr(number, MSR_PKG_C2_RESIDENCY);
+
+ if (this->has_c3_res)
+ c3_before = get_msr(number, MSR_PKG_C3_RESIDENCY);
+
+ /*
+ * Hack for Braswell where C7 MSR is actually BSW C6
+ */
+ if (this->has_c6c_res)
+ c6_before = get_msr(number, MSR_PKG_C7_RESIDENCY);
+ else
+ c6_before = get_msr(number, MSR_PKG_C6_RESIDENCY);
+
+ if (this->has_c7_res)
+ c7_before = get_msr(number, MSR_PKG_C7_RESIDENCY);
+ if (this->has_c8c9c10_res) {
+ c8_before = get_msr(number, MSR_PKG_C8_RESIDENCY);
+ c9_before = get_msr(number, MSR_PKG_C9_RESIDENCY);
+ c10_before = get_msr(number, MSR_PKG_C10_RESIDENCY);
+ }
+ tsc_before = get_msr(first_cpu, MSR_TSC);
+
+ if (this->has_c2c6_res)
+ insert_cstate("pkg c2", "C2 (pc2)", 0, c2_before, 1);
+
+ if (this->has_c3_res)
+ insert_cstate("pkg c3", "C3 (pc3)", 0, c3_before, 1);
+ insert_cstate("pkg c6", "C6 (pc6)", 0, c6_before, 1);
+ if (this->has_c7_res)
+ insert_cstate("pkg c7", "C7 (pc7)", 0, c7_before, 1);
+ if (this->has_c8c9c10_res) {
+ insert_cstate("pkg c8", "C8 (pc8)", 0, c8_before, 1);
+ insert_cstate("pkg c9", "C9 (pc9)", 0, c9_before, 1);
+ insert_cstate("pkg c10", "C10 (pc10)", 0, c10_before, 1);
+ }
+}
+
+void nhm_package::measurement_end(void)
+{
+ uint64_t time_delta;
+ double ratio;
+ unsigned int i, j;
+
+ for (i = 0; i < children.size(); i++)
+ if (children[i])
+ children[i]->wiggle();
+
+
+ if (this->has_c2c6_res)
+ c2_after = get_msr(number, MSR_PKG_C2_RESIDENCY);
+
+ if (this->has_c3_res)
+ c3_after = get_msr(number, MSR_PKG_C3_RESIDENCY);
+
+ if (this->has_c6c_res)
+ c6_after = get_msr(number, MSR_PKG_C7_RESIDENCY);
+ else
+ c6_after = get_msr(number, MSR_PKG_C6_RESIDENCY);
+
+ if (this->has_c7_res)
+ c7_after = get_msr(number, MSR_PKG_C7_RESIDENCY);
+ if (has_c8c9c10_res) {
+ c8_after = get_msr(number, MSR_PKG_C8_RESIDENCY);
+ c9_after = get_msr(number, MSR_PKG_C9_RESIDENCY);
+ c10_after = get_msr(number, MSR_PKG_C10_RESIDENCY);
+ }
+ tsc_after = get_msr(first_cpu, MSR_TSC);
+
+ gettimeofday(&stamp_after, NULL);
+
+ time_factor = 1000000.0 * (stamp_after.tv_sec - stamp_before.tv_sec) + stamp_after.tv_usec - stamp_before.tv_usec;
+
+
+ if (this->has_c2c6_res)
+ finalize_cstate("pkg c2", 0, c2_after, 1);
+
+ if (this->has_c3_res)
+ finalize_cstate("pkg c3", 0, c3_after, 1);
+ finalize_cstate("pkg c6", 0, c6_after, 1);
+ if (this->has_c7_res)
+ finalize_cstate("pkg c7", 0, c7_after, 1);
+ if (has_c8c9c10_res) {
+ finalize_cstate("pkg c8", 0, c8_after, 1);
+ finalize_cstate("pkg c9", 0, c9_after, 1);
+ finalize_cstate("pkg c10", 0, c10_after, 1);
+ }
+
+ for (i = 0; i < children.size(); i++)
+ if (children[i])
+ children[i]->measurement_end();
+
+ time_delta = 1000000 * (stamp_after.tv_sec - stamp_before.tv_sec) + stamp_after.tv_usec - stamp_before.tv_usec;
+
+ ratio = 1.0 * time_delta / (tsc_after - tsc_before);
+
+
+ for (i = 0; i < cstates.size(); i++) {
+ struct idle_state *state = cstates[i];
+
+ if (state->after_count == 0)
+ continue;
+
+ if (state->after_count != state->before_count)
+ continue;
+
+ state->usage_delta = ratio * (state->usage_after - state->usage_before) / state->after_count;
+ state->duration_delta = ratio * (state->duration_after - state->duration_before) / state->after_count;
+ }
+ for (i = 0; i < children.size(); i++)
+ if (children[i]) {
+ for (j = 0; j < children[i]->pstates.size(); j++) {
+ struct frequency *state;
+ state = children[i]->pstates[j];
+ if (!state)
+ continue;
+
+ update_pstate( state->freq, state->human_name, state->time_before, state->before_count);
+ finalize_pstate(state->freq, state->time_after, state->after_count);
+ }
+ }
+ total_stamp = 0;
+
+}
+
+void nhm_cpu::measurement_start(void)
+{
+ ifstream file;
+ char filename[PATH_MAX];
+
+ cpu_linux::measurement_start();
+
+ last_stamp = 0;
+
+ aperf_before = get_msr(number, MSR_APERF);
+ mperf_before = get_msr(number, MSR_MPERF);
+ tsc_before = get_msr(number, MSR_TSC);
+
+ insert_cstate("active", _("C0 active"), 0, aperf_before, 1);
+
+ snprintf(filename, sizeof(filename), "/sys/devices/system/cpu/cpu%i/cpufreq/stats/time_in_state", first_cpu);
+
+ file.open(filename, ios::in);
+
+ if (file) {
+ char line[1024];
+
+ while (file) {
+ uint64_t f;
+ file.getline(line, sizeof(line));
+ f = strtoull(line, NULL, 10);
+ account_freq(f, 0);
+ }
+ file.close();
+ }
+ account_freq(0, 0);
+}
+
+void nhm_cpu::measurement_end(void)
+{
+ uint64_t time_delta;
+ double ratio;
+ unsigned int i;
+
+ aperf_after = get_msr(number, MSR_APERF);
+ mperf_after = get_msr(number, MSR_MPERF);
+ tsc_after = get_msr(number, MSR_TSC);
+
+
+
+ finalize_cstate("active", 0, aperf_after, 1);
+
+
+ cpu_linux::measurement_end();
+
+ time_delta = 1000000 * (stamp_after.tv_sec - stamp_before.tv_sec) + stamp_after.tv_usec - stamp_before.tv_usec;
+
+ ratio = 1.0 * time_delta / (tsc_after - tsc_before);
+
+
+ for (i = 0; i < cstates.size(); i++) {
+ struct idle_state *state = cstates[i];
+ if (state->line_level != LEVEL_C0)
+ continue;
+
+ state->usage_delta = ratio * (state->usage_after - state->usage_before) / state->after_count;
+ state->duration_delta = ratio * (state->duration_after - state->duration_before) / state->after_count;
+ }
+
+ total_stamp = 0;
+
+}
+
+char * nhm_cpu::fill_pstate_name(int line_nr, char *buffer)
+{
+ if (line_nr == LEVEL_C0) {
+ sprintf(buffer, _("Average"));
+ return buffer;
+ }
+ return cpu_linux::fill_pstate_name(line_nr, buffer);
+}
+
+char * nhm_cpu::fill_pstate_line(int line_nr, char *buffer)
+{
+ const int intel_pstate = is_intel_pstate_driver_loaded();
+
+ if (!intel_pstate && total_stamp ==0) {
+ unsigned int i;
+ for (i = 0; i < pstates.size(); i++)
+ total_stamp += pstates[i]->time_after;
+ if (total_stamp == 0)
+ total_stamp = 1;
+ }
+
+ if (line_nr == LEVEL_HEADER) {
+ sprintf(buffer,_(" CPU %i"), number);
+ return buffer;
+ }
+
+ if (line_nr == LEVEL_C0) {
+ double F;
+ F = 1.0 * (tsc_after - tsc_before) * (aperf_after - aperf_before) / (mperf_after - mperf_before) / time_factor * 1000;
+ hz_to_human(F, buffer, 1);
+ return buffer;
+ }
+ if (intel_pstate > 0 || line_nr >= (int)pstates.size() || line_nr < 0)
+ return buffer;
+
+ sprintf(buffer," %5.1f%% ", percentage(1.0* (pstates[line_nr]->time_after) / total_stamp));
+
+ return buffer;
+}
+
+
+int nhm_cpu::has_pstate_level(int level)
+{
+ if (level == LEVEL_C0)
+ return 1;
+ return cpu_linux::has_pstate_level(level);
+}
diff --git a/src/cpu/intel_cpus.h b/src/cpu/intel_cpus.h
new file mode 100644
index 0000000..79afb98
--- /dev/null
+++ b/src/cpu/intel_cpus.h
@@ -0,0 +1,180 @@
+#ifndef PowerTop_INTEL_CPUS_H_84F09FB4F519470FA914AA9B02453221
+#define PowerTop_INTEL_CPUS_H_84F09FB4F519470FA914AA9B02453221
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <stdint.h>
+#include <sys/time.h>
+#include <dirent.h>
+
+#include "cpu.h"
+
+
+#define MSR_TSC 0x10
+#define MSR_NEHALEM_PLATFORM_INFO 0xCE
+#define MSR_NEHALEM_TURBO_RATIO_LIMIT 0x1AD
+#define MSR_APERF 0xE8
+#define MSR_MPERF 0xE7
+#define MSR_PKG_C2_RESIDENCY 0x60D
+#define MSR_PKG_C3_RESIDENCY 0x3F8
+#define MSR_PKG_C6_RESIDENCY 0x3F9
+#define MSR_PKG_C7_RESIDENCY 0x3FA
+#define MSR_PKG_C8_RESIDENCY 0x630
+#define MSR_PKG_C9_RESIDENCY 0x631
+#define MSR_PKG_C10_RESIDENCY 0x632
+#define MSR_CORE_C1_RESIDENCY 0x660
+#define MSR_CORE_C3_RESIDENCY 0x3FC
+#define MSR_CORE_C6_RESIDENCY 0x3FD
+#define MSR_CORE_C7_RESIDENCY 0x3FE
+
+class intel_util
+{
+protected:
+ int byt_ahci_support;
+ DIR *dir;
+public:
+ intel_util();
+ virtual void byt_has_ahci();
+ virtual int get_byt_ahci_support();
+};
+
+class nhm_package: public cpu_package, public intel_util
+{
+private:
+ uint64_t c2_before, c2_after;
+ uint64_t c3_before, c3_after;
+ uint64_t c6_before, c6_after;
+ uint64_t c7_before, c7_after;
+ uint64_t c8_before, c8_after;
+ uint64_t c9_before, c9_after;
+ uint64_t c10_before, c10_after;
+ uint64_t tsc_before, tsc_after;
+
+ uint64_t last_stamp;
+ uint64_t total_stamp;
+public:
+ int has_c7_res;
+ int has_c2c6_res;
+ int has_c3_res;
+ int has_c6c_res; /* BSW */
+ int has_c8c9c10_res;
+ nhm_package(int model);
+ virtual void measurement_start(void);
+ virtual void measurement_end(void);
+ virtual int can_collapse(void) { return 0;};
+
+ virtual char * fill_pstate_line(int line_nr, char *buffer);
+};
+
+class nhm_core: public cpu_core, public intel_util
+{
+private:
+ uint64_t c1_before, c1_after;
+ uint64_t c3_before, c3_after;
+ uint64_t c6_before, c6_after;
+ uint64_t c7_before, c7_after;
+ uint64_t tsc_before, tsc_after;
+
+ uint64_t last_stamp;
+ uint64_t total_stamp;
+public:
+ int has_c1_res;
+ int has_c7_res;
+ int has_c3_res;
+ nhm_core(int model);
+ virtual void measurement_start(void);
+ virtual void measurement_end(void);
+ virtual int can_collapse(void) { return 0;};
+
+ virtual char * fill_pstate_line(int line_nr, char *buffer);
+};
+
+class nhm_cpu: public cpu_linux, public intel_util
+{
+private:
+ uint64_t aperf_before;
+ uint64_t aperf_after;
+ uint64_t mperf_before;
+ uint64_t mperf_after;
+ uint64_t tsc_before, tsc_after;
+
+ uint64_t last_stamp;
+ uint64_t total_stamp;
+public:
+ virtual void measurement_start(void);
+ virtual void measurement_end(void);
+ virtual int can_collapse(void) { return 0;};
+
+ virtual char * fill_pstate_name(int line_nr, char *buffer);
+ virtual char * fill_pstate_line(int line_nr, char *buffer);
+ virtual int has_pstate_level(int level);
+};
+
+class atom_package: public cpu_package
+{
+public:
+ virtual void measurement_start(void);
+ virtual void measurement_end(void);
+
+};
+
+class atom_core: public cpu_core
+{
+public:
+ virtual void measurement_start(void);
+ virtual void measurement_end(void);
+
+};
+
+
+class i965_core: public cpu_core
+{
+private:
+ uint64_t rc6_before, rc6_after;
+ uint64_t rc6p_before, rc6p_after;
+ uint64_t rc6pp_before, rc6pp_after;
+
+ struct timeval before;
+ struct timeval after;
+
+public:
+ virtual void measurement_start(void);
+ virtual void measurement_end(void);
+ virtual int can_collapse(void) { return 0;};
+
+ virtual char * fill_pstate_line(int line_nr, char *buffer);
+ virtual char * fill_pstate_name(int line_nr, char *buffer);
+ virtual char * fill_cstate_line(int line_nr, char *buffer, const char *separator);
+ virtual int has_pstate_level(int level) { return 0; };
+ virtual int has_pstates(void) { return 0; };
+ virtual void wiggle(void) { };
+
+};
+
+int is_supported_intel_cpu(int model, int cpu);
+int byt_has_ahci();
+
+int is_intel_pstate_driver_loaded();
+
+#endif
diff --git a/src/cpu/intel_gpu.cpp b/src/cpu/intel_gpu.cpp
new file mode 100644
index 0000000..e0f4ac2
--- /dev/null
+++ b/src/cpu/intel_gpu.cpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2012, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include "intel_cpus.h"
+#include <iostream>
+#include <fstream>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "../lib.h"
+#include "../parameters/parameters.h"
+#include "../display.h"
+
+void i965_core::measurement_start(void)
+{
+ ifstream file;
+
+ gettimeofday(&before, NULL);
+ rc6_before = read_sysfs("/sys/class/drm/card0/power/rc6_residency_ms", NULL);
+ rc6p_before = read_sysfs("/sys/class/drm/card0/power/rc6p_residency_ms", NULL);
+ rc6pp_before = read_sysfs("/sys/class/drm/card0/power/rc6pp_residency_ms", NULL);
+
+ update_cstate("gpu c0", "Powered On", 0, 0, 1, 0);
+ update_cstate("gpu rc6", "RC6", 0, rc6_before, 1, 1);
+ update_cstate("gpu rc6p", "RC6p", 0, rc6p_before, 1, 2);
+ update_cstate("gpu rc6pp", "RC6pp", 0, rc6pp_before, 1, 3);
+}
+
+char * i965_core::fill_cstate_line(int line_nr, char *buffer, const char *separator)
+{
+ buffer[0] = 0;
+ double ratio, d = -1.0, time_delta;
+
+ if (line_nr == LEVEL_HEADER) {
+ sprintf(buffer,_(" GPU "));
+ return buffer;
+ }
+
+ buffer[0] = 0;
+
+ time_delta = 1000000 * (after.tv_sec - before.tv_sec) + after.tv_usec - before.tv_usec;
+ ratio = 100000.0/time_delta;
+
+ switch (line_nr) {
+ case 0:
+ d = 100.0 - ratio * (rc6_after + rc6p_after + rc6pp_after - rc6_before - rc6p_before - rc6pp_before);
+ break;
+ case 1:
+ d = ratio * (rc6_after - rc6_before);
+ break;
+ case 2:
+ d = ratio * (rc6p_after - rc6p_before);
+ break;
+ case 3:
+ d = ratio * (rc6pp_after - rc6pp_before);
+ break;
+ default:
+ return buffer;
+ }
+
+ /* cope with rounding errors due to the measurement interval */
+ if (d < 0.0)
+ d = 0.0;
+ if (d > 100.0)
+ d = 100.0;
+
+ sprintf(buffer,"%5.1f%%", d);
+
+ return buffer;
+}
+
+
+void i965_core::measurement_end(void)
+{
+ gettimeofday(&after, NULL);
+
+ rc6_after = read_sysfs("/sys/class/drm/card0/power/rc6_residency_ms", NULL);
+ rc6p_after = read_sysfs("/sys/class/drm/card0/power/rc6p_residency_ms", NULL);
+ rc6pp_after = read_sysfs("/sys/class/drm/card0/power/rc6pp_residency_ms", NULL);
+}
+
+char * i965_core::fill_pstate_line(int line_nr, char *buffer)
+{
+ buffer[0] = 0;
+ return buffer;
+}
+
+char * i965_core::fill_pstate_name(int line_nr, char *buffer)
+{
+ buffer[0] = 0;
+ return buffer;
+}
+
diff --git a/src/cpu/rapl/rapl_interface.cpp b/src/cpu/rapl/rapl_interface.cpp
new file mode 100644
index 0000000..d6bd4c8
--- /dev/null
+++ b/src/cpu/rapl/rapl_interface.cpp
@@ -0,0 +1,699 @@
+/* rapl_interface.cpp: rapl interface for power top implementation
+ *
+ * Copyright (C) 2012 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ *
+ * Author Name <Srinivas.Pandruvada@linux.intel.com>
+ *
+ */
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <math.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include "lib.h"
+#include "rapl_interface.h"
+
+#ifdef DEBUG
+#define RAPL_DBG_PRINT printf
+#define RAPL_ERROR_PRINT printf
+#else
+#define RAPL_DBG_PRINT(...) ((void) 0)
+#define RAPL_ERROR_PRINT(...) ((void) 0)
+#endif
+#define RAPL_INFO_PRINT(format, m) fprintf(stderr, format, m)
+
+#define MAX_TEMP_STR_SIZE 20
+
+// RAPL interface
+#define MSR_RAPL_POWER_UNIT 0x606
+#define MSR_PKG_POWER_LIMIT 0x610
+
+#define MSR_PKG_ENERY_STATUS 0x611
+#define MSR_PKG_POWER_INFO 0x614
+#define MSR_PKG_PERF_STATUS 0x613
+
+#define MSR_DRAM_POWER_LIMIT 0x618
+#define MSR_DRAM_ENERY_STATUS 0x619
+#define MSR_DRAM_PERF_STATUS 0x61B
+#define MSR_DRAM_POWER_INFO 0x61c
+
+#define MSR_PP0_POWER_LIMIT 0x638
+#define MSR_PP0_ENERY_STATUS 0x639
+#define MSR_PP0_POLICY 0x63A
+#define MSR_PP0_PERF_STATUS 0x63B
+
+#define MSR_PP1_POWER_LIMIT 0x640
+#define MSR_PP1_ENERY_STATUS 0x641
+#define MSR_PP1_POLICY 0x642
+
+#define PKG_DOMAIN_PRESENT 0x01
+#define DRAM_DOMAIN_PRESENT 0x02
+#define PP0_DOMAIN_PRESENT 0x04
+#define PP1_DOMAIN_PRESENT 0x08
+
+c_rapl_interface::c_rapl_interface(const char *dev_name, int cpu) :
+ powercap_sysfs_present(false),
+ powercap_core_path(),
+ powercap_uncore_path(),
+ powercap_dram_path(),
+ first_cpu(cpu),
+ measurment_interval(def_sampling_interval),
+ last_pkg_energy_status(0.0),
+ last_dram_energy_status(0.0),
+ last_pp0_energy_status(0.0),
+ last_pp1_energy_status(0.0)
+{
+ uint64_t value;
+ int ret;
+ string package_path;
+ DIR *dir;
+ struct dirent *entry;
+
+ RAPL_INFO_PRINT("RAPL device for cpu %d\n", cpu);
+
+ rapl_domains = 0;
+
+ if (dev_name) {
+ string base_path = "/sys/class/powercap/intel-rapl/";
+ if ((dir = opendir(base_path.c_str())) != NULL) {
+ while ((entry = readdir(dir)) != NULL) {
+ string path = base_path + entry->d_name + "/name";
+ string str = read_sysfs_string(path);
+ if (str.length() > 0) {
+ if (str == dev_name) {
+ package_path = base_path + entry->d_name + "/";
+ powercap_sysfs_present = true;
+ rapl_domains |= PKG_DOMAIN_PRESENT;
+ break;
+ }
+ }
+ }
+ closedir(dir);
+ }
+ }
+
+ if (powercap_sysfs_present) {
+ if ((dir = opendir(package_path.c_str())) != NULL) {
+ while ((entry = readdir(dir)) != NULL) {
+ string path = package_path + entry->d_name;
+ string str = read_sysfs_string(path + "/name");
+ if (str.length() > 0) {
+ if (str == "core") {
+ rapl_domains |= PP0_DOMAIN_PRESENT;
+ powercap_core_path = path + "/";
+ }
+ else if (str == "dram") {
+ rapl_domains |= DRAM_DOMAIN_PRESENT;
+ powercap_dram_path = path + "/";
+ }
+ else if (str == "uncore") {
+ rapl_domains |= PP1_DOMAIN_PRESENT;
+ powercap_uncore_path = path + "/";
+ }
+ }
+ }
+ closedir(dir);
+ }
+
+ RAPL_INFO_PRINT("RAPL Using PowerCap Sysfs : Domain Mask %x\n", rapl_domains);
+ return;
+ }
+
+ // Fallback to using MSRs
+
+ // presence of each domain
+ // Check presence of PKG domain
+ ret = read_msr(first_cpu, MSR_PKG_ENERY_STATUS, &value);
+ if (ret > 0) {
+ rapl_domains |= PKG_DOMAIN_PRESENT;
+ RAPL_DBG_PRINT("Domain : PKG present\n");
+ } else {
+ RAPL_DBG_PRINT("Domain : PKG Not present\n");
+ }
+
+ // Check presence of DRAM domain
+ ret = read_msr(first_cpu, MSR_DRAM_ENERY_STATUS, &value);
+ if (ret > 0) {
+ rapl_domains |= DRAM_DOMAIN_PRESENT;
+ RAPL_DBG_PRINT("Domain : DRAM present\n");
+ } else {
+ RAPL_DBG_PRINT("Domain : DRAM Not present\n");
+ }
+
+ // Check presence of PP0 domain
+ ret = read_msr(first_cpu, MSR_PP0_ENERY_STATUS, &value);
+ if (ret > 0) {
+ rapl_domains |= PP0_DOMAIN_PRESENT;
+ RAPL_DBG_PRINT("Domain : PP0 present\n");
+ } else {
+ RAPL_DBG_PRINT("Domain : PP0 Not present\n");
+ }
+
+ // Check presence of PP1 domain
+ ret = read_msr(first_cpu, MSR_PP1_ENERY_STATUS, &value);
+ if (ret > 0) {
+ rapl_domains |= PP1_DOMAIN_PRESENT;
+ RAPL_DBG_PRINT("Domain : PP1 present\n");
+ } else {
+ RAPL_DBG_PRINT("Domain : PP1 Not present\n");
+ }
+
+ power_units = get_power_unit();
+ energy_status_units = get_energy_status_unit();
+ time_units = get_time_unit();
+
+ RAPL_DBG_PRINT("RAPL Domain mask: %x\n", rapl_domains);
+}
+
+bool c_rapl_interface::pkg_domain_present()
+{
+ if ((rapl_domains & PKG_DOMAIN_PRESENT)) {
+ return true;
+ }
+
+ return false;
+}
+
+bool c_rapl_interface::dram_domain_present()
+{
+ if ((rapl_domains & DRAM_DOMAIN_PRESENT)) {
+ return true;
+ }
+
+ return false;
+}
+
+bool c_rapl_interface::pp0_domain_present()
+{
+ if ((rapl_domains & PP0_DOMAIN_PRESENT)) {
+ return true;
+ }
+
+ return false;
+}
+
+bool c_rapl_interface::pp1_domain_present()
+{
+ if ((rapl_domains & PP1_DOMAIN_PRESENT)) {
+ return true;
+ }
+
+ return false;
+}
+
+int c_rapl_interface::read_msr(int cpu, unsigned int idx, uint64_t *val)
+{
+ return ::read_msr(cpu, idx, val);
+}
+
+int c_rapl_interface::write_msr(int cpu, unsigned int idx, uint64_t val)
+{
+ return ::write_msr(cpu, idx, val);
+}
+
+int c_rapl_interface::get_rapl_power_unit(uint64_t *value)
+{
+ int ret;
+
+ ret = read_msr(first_cpu, MSR_RAPL_POWER_UNIT, value);
+
+ return ret;
+}
+
+double c_rapl_interface::get_power_unit()
+{
+ int ret;
+ uint64_t value;
+
+ ret = get_rapl_power_unit(&value);
+ if(ret < 0)
+ {
+ return ret;
+ }
+
+ return (double) 1/pow((double)2, (double)(value & 0xf));
+}
+
+double c_rapl_interface::get_energy_status_unit()
+{
+ int ret;
+ uint64_t value;
+
+ ret = get_rapl_power_unit(&value);
+ if(ret < 0)
+ {
+ return ret;
+ }
+
+ return (double)1/ pow((double)2, (double)((value & 0x1f00) >> 8));
+}
+
+double c_rapl_interface::get_time_unit()
+{
+ int ret;
+ uint64_t value;
+
+ ret = get_rapl_power_unit(&value);
+ if(ret < 0)
+ {
+ return ret;
+ }
+
+ return (double)1 / pow((double)2, (double)((value & 0xf0000) >> 16));
+}
+
+int c_rapl_interface::get_pkg_energy_status(double *status)
+{
+ int ret;
+ uint64_t value;
+
+ if (!pkg_domain_present()) {
+ return -1;
+ }
+
+ ret = read_msr(first_cpu, MSR_PKG_ENERY_STATUS, &value);
+ if(ret < 0)
+ {
+ RAPL_ERROR_PRINT("get_pkg_energy_status failed\n");
+ return ret;
+ }
+
+ *status = (double) (value & 0xffffffff) * get_energy_status_unit();
+
+ return ret;
+}
+
+int c_rapl_interface::get_pkg_power_info(double *thermal_spec_power,
+ double *max_power, double *min_power, double *max_time_window)
+{
+ int ret;
+ uint64_t value;
+
+ if (!pkg_domain_present()) {
+ return -1;
+ }
+ ret = read_msr(first_cpu, MSR_PKG_POWER_INFO, &value);
+ if(ret < 0)
+ {
+ RAPL_ERROR_PRINT("get_pkg_power_info failed\n");
+ return ret;
+ }
+ *thermal_spec_power = (value & 0x7FFF) * power_units;
+ *min_power = ((value & 0x7FFF0000) >> 16) * power_units;
+ *max_power = ((value & 0x7FFF00000000) >> 32) * power_units;
+ *max_time_window = ((value & 0x3f000000000000)>>48) * time_units;
+
+ return ret;
+}
+
+int c_rapl_interface::get_pkg_power_limit(uint64_t *value)
+{
+ int ret;
+
+ if (!pkg_domain_present()) {
+ return -1;
+ }
+
+ ret = read_msr(first_cpu, MSR_PKG_POWER_LIMIT, value);
+ if(ret < 0)
+ {
+ RAPL_ERROR_PRINT("get_pkg_power_limit failed\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+int c_rapl_interface::set_pkg_power_limit(uint64_t value)
+{
+ int ret;
+
+ if (!pkg_domain_present()) {
+ return -1;
+ }
+
+ ret = write_msr(first_cpu, MSR_PKG_POWER_LIMIT, value);
+ if(ret < 0)
+ {
+ RAPL_ERROR_PRINT("set_pkg_power_limit failed\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+int c_rapl_interface::get_dram_energy_status(double *status)
+{
+ int ret;
+ uint64_t value;
+
+ if (!dram_domain_present()) {
+ return -1;
+ }
+
+ if (powercap_sysfs_present) {
+ string str = read_sysfs_string(powercap_dram_path + "energy_uj");
+ if (str.length() > 0) {
+ *status = atof(str.c_str()) / 1000000; // uj to Js
+ return 0;
+ }
+
+ return -EINVAL;
+ }
+
+ ret = read_msr(first_cpu, MSR_DRAM_ENERY_STATUS, &value);
+ if(ret < 0)
+ {
+ RAPL_ERROR_PRINT("get_dram_energy_status failed\n");
+ return ret;
+ }
+
+ *status = (double) (value & 0xffffffff) * get_energy_status_unit();
+
+ return ret;
+}
+
+int c_rapl_interface::get_dram_power_info(double *thermal_spec_power,
+ double *max_power, double *min_power, double *max_time_window)
+{
+ int ret;
+ uint64_t value;
+
+ if (!dram_domain_present()) {
+ return -1;
+ }
+ ret = read_msr(first_cpu, MSR_DRAM_POWER_INFO, &value);
+ if(ret < 0)
+ {
+ RAPL_ERROR_PRINT("get_dram_power_info failed\n");
+ return ret;
+ }
+
+ *thermal_spec_power = (value & 0x7FFF) * power_units;
+ *min_power = ((value & 0x7FFF0000) >> 16) * power_units;
+ *max_power = ((value & 0x7FFF00000000) >> 32) * power_units;
+ *max_time_window = ((value & 0x3f000000000000)>>48) * time_units;
+
+ return ret;
+}
+
+int c_rapl_interface::get_dram_power_limit(uint64_t *value)
+{
+ int ret;
+
+ if (!dram_domain_present()) {
+ return -1;
+ }
+
+ ret = read_msr(first_cpu, MSR_DRAM_POWER_LIMIT, value);
+ if(ret < 0)
+ {
+ RAPL_ERROR_PRINT("get_dram_power_limit failed\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+int c_rapl_interface::set_dram_power_limit(uint64_t value)
+{
+ int ret;
+
+ if (!dram_domain_present()) {
+ return -1;
+ }
+
+ ret = write_msr(first_cpu, MSR_DRAM_POWER_LIMIT, value);
+ if(ret < 0)
+ {
+ RAPL_ERROR_PRINT("set_dram_power_limit failed\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+int c_rapl_interface::get_pp0_energy_status(double *status)
+{
+ int ret;
+ uint64_t value;
+
+ if (!pp0_domain_present()) {
+ return -1;
+ }
+
+ if (powercap_sysfs_present) {
+ string str = read_sysfs_string(powercap_core_path + "energy_uj");
+ if (str.length() > 0) {
+ *status = atof(str.c_str()) / 1000000; // uj to Js
+ return 0;
+ }
+
+ return -EINVAL;
+ }
+
+ ret = read_msr(first_cpu, MSR_PP0_ENERY_STATUS, &value);
+ if(ret < 0)
+ {
+ RAPL_ERROR_PRINT("get_pp0_energy_status failed\n");
+ return ret;
+ }
+
+ *status = (double) (value & 0xffffffff) * get_energy_status_unit();
+
+ return ret;
+}
+
+int c_rapl_interface::get_pp0_power_limit(uint64_t *value)
+{
+ int ret;
+
+ if (!pp0_domain_present()) {
+ return -1;
+ }
+
+ ret = read_msr(first_cpu, MSR_PP0_POWER_LIMIT, value);
+ if(ret < 0)
+ {
+ RAPL_ERROR_PRINT("get_pp0_power_limit failed\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+int c_rapl_interface::set_pp0_power_limit(uint64_t value)
+{
+ int ret;
+
+ if (!pp0_domain_present()) {
+ return -1;
+ }
+
+ ret = write_msr(first_cpu, MSR_PP0_POWER_LIMIT, value);
+ if(ret < 0)
+ {
+ RAPL_ERROR_PRINT("set_pp0_power_limit failed\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+int c_rapl_interface::get_pp0_power_policy(unsigned int *pp0_power_policy)
+{
+ int ret;
+ uint64_t value;
+
+ if (!pp0_domain_present()) {
+ return -1;
+ }
+
+ ret = read_msr(first_cpu, MSR_PP0_POLICY, &value);
+ if(ret < 0)
+ {
+ RAPL_ERROR_PRINT("get_pp0_power_policy failed\n");
+ return ret;
+ }
+
+ *pp0_power_policy = value & 0x0f;
+
+ return ret;
+}
+
+int c_rapl_interface::get_pp1_energy_status(double *status)
+{
+ int ret;
+ uint64_t value;
+
+ if (!pp1_domain_present()) {
+ return -1;
+ }
+
+ if (powercap_sysfs_present) {
+ string str = read_sysfs_string(powercap_uncore_path + "energy_uj");
+ if (str.length() > 0) {
+ *status = atof(str.c_str()) / 1000000; // uj to Js
+ return 0;
+ }
+
+ return -EINVAL;
+ }
+
+ ret = read_msr(first_cpu, MSR_PP1_ENERY_STATUS, &value);
+ if(ret < 0)
+ {
+ RAPL_ERROR_PRINT("get_pp1_energy_status failed\n");
+ return ret;
+ }
+
+ *status = (double) (value & 0xffffffff) * get_energy_status_unit();
+
+ return ret;
+}
+
+int c_rapl_interface::get_pp1_power_limit(uint64_t *value)
+{
+ int ret;
+
+ if (!pp1_domain_present()) {
+ return -1;
+ }
+
+ ret = read_msr(first_cpu, MSR_PP1_POWER_LIMIT, value);
+ if(ret < 0)
+ {
+ RAPL_ERROR_PRINT("get_pp1_power_info failed\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+int c_rapl_interface::set_pp1_power_limit(uint64_t value)
+{
+ int ret;
+
+ if (!pp1_domain_present()) {
+ return -1;
+ }
+
+ ret = write_msr(first_cpu, MSR_PP1_POWER_LIMIT, value);
+ if(ret < 0)
+ {
+ RAPL_ERROR_PRINT("set_pp1_power_limit failed\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+int c_rapl_interface::get_pp1_power_policy(unsigned int *pp1_power_policy)
+{
+ int ret;
+ uint64_t value;
+
+ if (!pp1_domain_present()) {
+ return -1;
+ }
+
+ ret = read_msr(first_cpu, MSR_PP1_POLICY, &value);
+ if(ret < 0)
+ {
+ RAPL_ERROR_PRINT("get_pp1_power_policy failed\n");
+ return ret;
+ }
+
+ *pp1_power_policy = value & 0x0f;
+
+ return ret;
+}
+
+void c_rapl_interface::rapl_measure_energy()
+{
+#ifdef RAPL_TEST_MODE
+ int ret;
+ double energy_status;
+ double thermal_spec_power;
+ double max_power;
+ double min_power;
+ double max_time_window;
+ double pkg_watts = 0;
+ double dram_watts = 0;
+ double pp0_watts = 0;
+ double pp1_watts = 0;
+ double pkg_joules = 0;
+ double dram_joules = 0;
+ double pp0_joules = 0;
+ double pp1_joules = 0;
+
+ get_pkg_power_info(&thermal_spec_power, &max_power, &min_power, &max_time_window);
+ RAPL_DBG_PRINT("Pkg Power Info: Thermal spec %f watts, max %f watts, min %f watts, max time window %f seconds\n", thermal_spec_power, max_power, min_power, max_time_window);
+ get_dram_power_info(&thermal_spec_power, &max_power, &min_power, &max_time_window);
+ RAPL_DBG_PRINT("DRAM Power Info: Thermal spec %f watts, max %f watts, min %f watts, max time window %f seconds\n", thermal_spec_power, max_power, min_power, max_time_window);
+
+ for (;;) {
+ if (pkg_domain_present()) {
+ ret = get_pkg_energy_status(&energy_status);
+ if (last_pkg_energy_status == 0)
+ last_pkg_energy_status = energy_status;
+ if (ret > 0) {
+ pkg_joules = energy_status;
+ pkg_watts = (energy_status-last_pkg_energy_status)/measurment_interval;
+ }
+ last_pkg_energy_status = energy_status;
+ }
+ if (dram_domain_present()) {
+ ret = get_dram_energy_status(&energy_status);
+ if (last_dram_energy_status == 0)
+ last_dram_energy_status = energy_status;
+ if (ret > 0){
+ dram_joules = energy_status;
+ dram_watts = (energy_status-last_dram_energy_status)/measurment_interval;
+ }
+ last_dram_energy_status = energy_status;
+ }
+ if (pp0_domain_present()) {
+ ret = get_pp0_energy_status(&energy_status);
+ if (last_pp0_energy_status == 0)
+ last_pp0_energy_status = energy_status;
+ if (ret > 0){
+ pp0_joules = energy_status;
+ pp0_watts = (energy_status-last_pp0_energy_status)/measurment_interval;
+ }
+ last_pp0_energy_status = energy_status;
+ }
+ if (pp1_domain_present()) {
+ ret = get_pp1_energy_status(&energy_status);
+ if (last_pp1_energy_status == 0)
+ last_pp1_energy_status = energy_status;
+ if (ret > 0){
+ pp1_joules = energy_status;
+ pp1_watts = (energy_status-last_pp1_energy_status)/measurment_interval;
+ }
+ last_pp1_energy_status = energy_status;
+ }
+ RAPL_DBG_PRINT("%f, %f, %f, %f\n", pkg_watts, dram_watts, pp0_watts, pp1_watts);
+ sleep(measurment_interval);
+ }
+#endif
+}
diff --git a/src/cpu/rapl/rapl_interface.h b/src/cpu/rapl/rapl_interface.h
new file mode 100644
index 0000000..c8e9683
--- /dev/null
+++ b/src/cpu/rapl/rapl_interface.h
@@ -0,0 +1,91 @@
+/* rapl_interface.h: rapl interface for power top
+ *
+ * Copyright (C) 2012 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ *
+ * Author Name <Srinivas.Pandruvada@linux.intel.com>
+ *
+ */
+
+#ifndef RAPL_INTERFACE_H
+#define RAPL_INTERFACE_H
+
+class c_rapl_interface
+{
+private:
+ static const int def_sampling_interval = 1; //In seconds
+ bool powercap_sysfs_present;
+ string powercap_core_path;
+ string powercap_uncore_path;
+ string powercap_dram_path;
+
+ unsigned char rapl_domains;
+ int first_cpu;
+
+ double power_units;
+ double energy_status_units;
+ double time_units;
+
+ int read_msr(int cpu, unsigned int idx, uint64_t *val);
+ int write_msr(int cpu, unsigned int idx, uint64_t val);
+
+protected:
+ int measurment_interval;
+ double last_pkg_energy_status;
+ double last_dram_energy_status;
+ double last_pp0_energy_status;
+ double last_pp1_energy_status;
+
+public:
+ c_rapl_interface(const char *dev_name = "package-0", int cpu = 0);
+
+ int get_rapl_power_unit(uint64_t *value);
+ double get_power_unit();
+ double get_energy_status_unit();
+ double get_time_unit();
+
+ int get_pkg_energy_status(double *status);
+ int get_pkg_power_info(double *thermal_spec_power,
+ double *max_power, double *min_power, double *max_time_window);
+ int get_pkg_power_limit(uint64_t *value);
+ int set_pkg_power_limit(uint64_t value);
+
+ int get_dram_energy_status(double *status);
+ int get_dram_power_info(double *thermal_spec_power,
+ double *max_power, double *min_power, double *max_time_window);
+ int get_dram_power_limit(uint64_t *value);
+ int set_dram_power_limit(uint64_t value);
+
+ int get_pp0_energy_status(double *status);
+ int get_pp0_power_limit(uint64_t *value);
+ int set_pp0_power_limit(uint64_t value);
+ int get_pp0_power_policy(unsigned int *pp0_power_policy);
+
+ int get_pp1_energy_status(double *status);
+ int get_pp1_power_limit(uint64_t *value);
+ int set_pp1_power_limit(uint64_t value);
+ int get_pp1_power_policy(unsigned int *pp1_power_policy);
+
+ bool pkg_domain_present();
+ bool dram_domain_present();
+ bool pp0_domain_present();
+ bool pp1_domain_present();
+
+ void rapl_measure_energy();
+};
+
+#endif
diff --git a/src/csstoh.sh b/src/csstoh.sh
new file mode 100755
index 0000000..681e6a5
--- /dev/null
+++ b/src/csstoh.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+#
+# This program file 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; version 2 of the License.
+#
+# This program 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 in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+# or just google for it.
+#
+# Written by Igor Zhbanov <i.zhbanov at samsung.com>
+
+if [ $# -ne 2 ]; then
+ echo "Usage: csstoh.sh cssfile header.h" >&2
+ exit 1
+fi
+if [ ! -f "$1" ]; then
+ echo "$1: no such file or directory" >&2
+ exit 1
+fi
+# redirect stdout to a file
+exec 1> "$2" || exit $?
+
+# header
+cat <<HERE || exit $?
+#ifndef __INCLUDE_GUARD_CCS_H
+#define __INCLUDE_GUARD_CCS_H
+
+const char css[] =
+HERE
+# body
+sed -r 's/^[ \t]*//; s/^(.*)$/\t\"\1\\n\"/' "$1" || exit $?
+# footer
+cat <<HERE || exit $?
+;
+#endif
+HERE
+
+# close output file
+exec 1>&-
+# return status of output file write
+exit $?
diff --git a/src/devices/ahci.cpp b/src/devices/ahci.cpp
new file mode 100644
index 0000000..efa66b3
--- /dev/null
+++ b/src/devices/ahci.cpp
@@ -0,0 +1,428 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <iostream>
+#include <fstream>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <limits.h>
+
+
+using namespace std;
+
+#include "device.h"
+#include "report/report.h"
+#include "report/report-maker.h"
+#include "ahci.h"
+#include "../parameters/parameters.h"
+#include "report/report-data-html.h"
+#include <string.h>
+
+vector <class ahci *> links;
+
+static string disk_name(char *path, char *target, char *shortname)
+{
+
+ DIR *dir;
+ struct dirent *dirent;
+ char pathname[PATH_MAX];
+ string diskname = "";
+
+ snprintf(pathname, sizeof(pathname), "%s/%s", path, target);
+ dir = opendir(pathname);
+ if (!dir)
+ return diskname;
+
+ while ((dirent = readdir(dir))) {
+ char line[4096], *c;
+ FILE *file;
+ if (dirent->d_name[0]=='.')
+ continue;
+
+ if (!strchr(dirent->d_name, ':'))
+ continue;
+
+ snprintf(line, sizeof(line), "%s/%s/model", pathname, dirent->d_name);
+ file = fopen(line, "r");
+ if (file) {
+ if (fgets(line, sizeof(line), file) == NULL) {
+ fclose(file);
+ break;
+ }
+ fclose(file);
+ c = strchr(line, '\n');
+ if (c)
+ *c = 0;
+ diskname = line;
+ break;
+ }
+ }
+ closedir(dir);
+
+ return diskname;
+}
+
+static string model_name(char *path, char *shortname)
+{
+
+ DIR *dir;
+ struct dirent *dirent;
+ char pathname[PATH_MAX];
+
+ snprintf(pathname, sizeof(pathname), "%s/device", path);
+
+ dir = opendir(pathname);
+ if (!dir)
+ return strdup(shortname);
+
+ while ((dirent = readdir(dir))) {
+ if (dirent->d_name[0]=='.')
+ continue;
+
+ if (!strchr(dirent->d_name, ':'))
+ continue;
+ if (!strstr(dirent->d_name, "target"))
+ continue;
+ return disk_name(pathname, dirent->d_name, shortname);
+ }
+ closedir(dir);
+
+ return "";
+}
+
+ahci::ahci(char *_name, char *path): device()
+{
+ char buffer[4096];
+ char devname[128];
+ string diskname;
+
+ end_active = 0;
+ end_slumber = 0;
+ end_devslp = 0;
+ end_partial = 0;
+ start_active = 0;
+ start_slumber = 0;
+ start_devslp = 0;
+ start_partial = 0;
+ pt_strcpy(sysfs_path, path);
+
+ register_sysfs_path(sysfs_path);
+
+ snprintf(devname, sizeof(devname), "ahci:%s", _name);
+ pt_strcpy(name, devname);
+ active_index = get_param_index("ahci-link-power-active");
+ partial_index = get_param_index("ahci-link-power-partial");
+
+ snprintf(buffer, sizeof(buffer), "%s-active", name);
+ active_rindex = get_result_index(buffer);
+
+ snprintf(buffer, sizeof(buffer), "%s-partial", name);
+ partial_rindex = get_result_index(buffer);
+
+ snprintf(buffer, sizeof(buffer), "%s-slumber", name);
+ slumber_rindex = get_result_index(buffer);
+
+ snprintf(buffer, sizeof(buffer), "%s-devslp", name);
+ devslp_rindex = get_result_index(buffer);
+
+ diskname = model_name(path, _name);
+
+ if (strlen(diskname.c_str()) == 0)
+ snprintf(humanname, sizeof(humanname), _("SATA link: %s"), _name);
+ else
+ snprintf(humanname, sizeof(humanname), _("SATA disk: %s"), diskname.c_str());
+}
+
+void ahci::start_measurement(void)
+{
+ char filename[PATH_MAX];
+ ifstream file;
+
+ snprintf(filename, sizeof(filename), "%s/ahci_alpm_active", sysfs_path);
+ try {
+ file.open(filename, ios::in);
+ if (file) {
+ file >> start_active;
+ }
+ file.close();
+ snprintf(filename, sizeof(filename), "%s/ahci_alpm_partial", sysfs_path);
+ file.open(filename, ios::in);
+
+ if (file) {
+ file >> start_partial;
+ }
+ file.close();
+ snprintf(filename, sizeof(filename), "%s/ahci_alpm_slumber", sysfs_path);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> start_slumber;
+ }
+ file.close();
+ snprintf(filename, sizeof(filename), "%s/ahci_alpm_devslp", sysfs_path);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> start_devslp;
+ }
+ file.close();
+ }
+ catch (std::ios_base::failure &c) {
+ fprintf(stderr, "%s\n", c.what());
+ }
+
+}
+
+void ahci::end_measurement(void)
+{
+ char filename[PATH_MAX];
+ char powername[4096];
+ ifstream file;
+ double p;
+ double total;
+
+ try {
+ snprintf(filename, sizeof(filename), "%s/ahci_alpm_active", sysfs_path);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> end_active;
+ }
+ file.close();
+ snprintf(filename, sizeof(filename), "%s/ahci_alpm_partial", sysfs_path);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> end_partial;
+ }
+ file.close();
+ snprintf(filename, sizeof(filename), "%s/ahci_alpm_slumber", sysfs_path);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> end_slumber;
+ }
+ file.close();
+ snprintf(filename, sizeof(filename), "%s/ahci_alpm_devslp", sysfs_path);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> end_devslp;
+ }
+ file.close();
+ }
+ catch (std::ios_base::failure &c) {
+ fprintf(stderr, "%s\n", c.what());
+ }
+ if (end_active < start_active)
+ end_active = start_active;
+ if (end_partial < start_partial)
+ end_partial = start_partial;
+ if (end_slumber < start_slumber)
+ end_slumber = start_slumber;
+
+ total = 0.001 + end_active + end_partial + end_slumber + end_devslp -
+ start_active - start_partial - start_slumber - start_devslp;
+
+ /* percent in active */
+ p = (end_active - start_active) / total * 100.0;
+ if (p < 0)
+ p = 0;
+ snprintf(powername, sizeof(powername), "%s-active", name);
+ report_utilization(powername, p);
+
+ /* percent in partial */
+ p = (end_partial - start_partial) / total * 100.0;
+ if (p < 0)
+ p = 0;
+ snprintf(powername, sizeof(powername), "%s-partial", name);
+ report_utilization(powername, p);
+
+ /* percent in slumber */
+ p = (end_slumber - start_slumber) / total * 100.0;
+ if (p < 0)
+ p = 0;
+ snprintf(powername, sizeof(powername), "%s-slumber", name);
+ report_utilization(powername, p);
+
+ /* percent in devslp */
+ p = (end_devslp - start_devslp) / total * 100.0;
+ if (p < 0)
+ p = 0;
+ snprintf(powername, sizeof(powername), "%s-devslp", name);
+ report_utilization(powername, p);
+}
+
+
+double ahci::utilization(void)
+{
+ double p;
+
+ p = (end_partial - start_partial + end_active - start_active) / (0.001 + end_active + end_partial + end_slumber + end_devslp - start_active - start_partial - start_slumber - start_devslp) * 100.0;
+
+ if (p < 0)
+ p = 0;
+
+ return p;
+}
+
+const char * ahci::device_name(void)
+{
+ return name;
+}
+
+void create_all_ahcis(void)
+{
+ struct dirent *entry;
+ DIR *dir;
+ char filename[PATH_MAX];
+
+ dir = opendir("/sys/class/scsi_host/");
+ if (!dir)
+ return;
+ while (1) {
+ class ahci *bl;
+ ofstream file;
+ ifstream check_file;
+ entry = readdir(dir);
+ if (!entry)
+ break;
+ if (entry->d_name[0] == '.')
+ continue;
+ snprintf(filename, sizeof(filename), "/sys/class/scsi_host/%s/ahci_alpm_accounting", entry->d_name);
+
+ check_file.open(filename, ios::in);
+ check_file.get();
+ check_file.close();
+ if (check_file.bad())
+ continue;
+
+ file.open(filename, ios::in);
+ if (!file)
+ continue;
+ file << 1 ;
+ file.close();
+ snprintf(filename, sizeof(filename), "/sys/class/scsi_host/%s", entry->d_name);
+
+ bl = new class ahci(entry->d_name, filename);
+ all_devices.push_back(bl);
+ register_parameter("ahci-link-power-active", 0.6); /* active sata link takes about 0.6 W */
+ register_parameter("ahci-link-power-partial");
+ links.push_back(bl);
+ }
+ closedir(dir);
+
+}
+
+
+
+double ahci::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ double power;
+ double factor;
+ double util;
+
+ power = 0;
+
+ factor = get_parameter_value(active_index, bundle);
+ util = get_result_value(active_rindex, result);
+ power += util * factor / 100.0;
+
+
+ factor = get_parameter_value(partial_index, bundle);
+ util = get_result_value(partial_rindex, result);
+ power += util * factor / 100.0;
+
+ return power;
+}
+
+void ahci_create_device_stats_table(void)
+{
+ unsigned int i;
+ int cols=0;
+ int rows=0;
+
+ /* div attr css_class and css_id */
+ tag_attr div_attr;
+ init_div(&div_attr, "clear_block", "ahci");
+
+ /* Set Title attributes */
+ tag_attr title_attr;
+ init_title_attr(&title_attr);
+
+ /* Add section */
+ report.add_div(&div_attr);
+
+ if (links.size() == 0) {
+ report.add_title(&title_attr, __("AHCI ALPM Residency Statistics - Not supported on this macine"));
+ report.end_div();
+ return;
+ }
+
+ /* Set Table attributes, rows, and cols */
+ table_attributes std_table_css;
+ cols=5;
+ rows=links.size()+1;
+ init_std_side_table_attr(&std_table_css, rows, cols);
+
+
+
+ /* Set array of data in row Major order */
+ string *ahci_data = new string[cols * rows];
+ ahci_data[0]=__("Link");
+ ahci_data[1]=__("Active");
+ ahci_data[2]=__("Partial");
+ ahci_data[3]=__("Slumber");
+ ahci_data[4]=__("Devslp");
+
+ /* traverse list of all devices and put their residency in the table */
+ for (i = 0; i < links.size(); i++){
+ links[i]->report_device_stats(ahci_data, i);
+ }
+ report.add_title(&title_attr, __("AHCI ALPM Residency Statistics"));
+ report.add_table(ahci_data, &std_table_css);
+ report.end_div();
+ delete [] ahci_data;
+}
+
+void ahci::report_device_stats(string *ahci_data, int idx)
+{
+ int offset=(idx*5+5);
+ char util[128];
+ double active_util = get_result_value(active_rindex, &all_results);
+ double partial_util = get_result_value(partial_rindex, &all_results);
+ double slumber_util = get_result_value(slumber_rindex, &all_results);
+ double devslp_util = get_result_value(devslp_rindex, &all_results);
+
+ snprintf(util, sizeof(util), "%5.1f", active_util);
+ ahci_data[offset]= util;
+ offset +=1;
+
+ snprintf(util, sizeof(util), "%5.1f", partial_util);
+ ahci_data[offset]= util;
+ offset +=1;
+
+ snprintf(util, sizeof(util), "%5.1f", slumber_util);
+ ahci_data[offset]= util;
+ offset +=1;
+
+ snprintf(util, sizeof(util), "%5.1f", devslp_util);
+ ahci_data[offset]= util;
+}
diff --git a/src/devices/ahci.h b/src/devices/ahci.h
new file mode 100644
index 0000000..7431fb5
--- /dev/null
+++ b/src/devices/ahci.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_AHCI_H
+#define _INCLUDE_GUARD_AHCI_H
+
+
+#include <string>
+#include <limits.h>
+#include "device.h"
+#include "../parameters/parameters.h"
+#include <stdint.h>
+
+class ahci: public device {
+ uint64_t start_active, end_active;
+ uint64_t start_partial, end_partial;
+ uint64_t start_slumber, end_slumber;
+ uint64_t start_devslp, end_devslp;
+ char sysfs_path[PATH_MAX];
+ char name[4096];
+ int partial_rindex;
+ int active_rindex;
+ int slumber_rindex;
+ int devslp_rindex;
+ int partial_index;
+ int active_index;
+ char humanname[4096];
+public:
+
+ ahci(char *_name, char *path);
+
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+ virtual double utilization(void); /* percentage */
+
+ virtual const char * class_name(void) { return "ahci";};
+
+ virtual const char * device_name(void);
+ virtual const char * human_name(void) { return humanname;};
+ virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
+ virtual int power_valid(void) { return utilization_power_valid(partial_rindex) + utilization_power_valid(active_rindex);};
+ virtual int grouping_prio(void) { return 1; };
+ virtual void report_device_stats(string *ahci_data, int idx);
+};
+
+extern void create_all_ahcis(void);
+extern void ahci_create_device_stats_table(void);
+
+
+#endif
diff --git a/src/devices/alsa.cpp b/src/devices/alsa.cpp
new file mode 100644
index 0000000..7e22975
--- /dev/null
+++ b/src/devices/alsa.cpp
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <iostream>
+#include <fstream>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+using namespace std;
+
+#include "device.h"
+#include "alsa.h"
+#include "../parameters/parameters.h"
+
+#include "../devlist.h"
+
+#include <string.h>
+#include <unistd.h>
+
+alsa::alsa(const char *_name, const char *path): device()
+{
+ ifstream file;
+
+ char devname[4096];
+ char model[4096];
+ char vendor[4096];
+ end_active = 0;
+ start_active = 0;
+ end_inactive = 0;
+ start_inactive = 0;
+ pt_strcpy(sysfs_path, path);
+
+ snprintf(devname, sizeof(devname), "alsa:%s", _name);
+ snprintf(humanname, sizeof(humanname), "alsa:%s", _name);
+ pt_strcpy(name, devname);
+ rindex = get_result_index(name);
+
+ guilty[0] = 0;
+ model[0] = 0;
+ vendor[0] = 0;
+ snprintf(devname, sizeof(devname), "%s/modelname", path);
+ file.open(devname);
+ if (file) {
+ file.getline(model, sizeof(model));
+ file.close();
+ }
+ snprintf(devname, sizeof(devname), "%s/vendor_name", path);
+ file.open(devname);
+ if (file) {
+ file.getline(vendor, sizeof(vendor));
+ file.close();
+ }
+ if (strlen(model) && strlen(vendor))
+ snprintf(humanname, sizeof(humanname), _("Audio codec %s: %s (%s)"), name, model, vendor);
+ else if (strlen(model))
+ snprintf(humanname, sizeof(humanname), _("Audio codec %s: %s"), _name, model);
+ else if (strlen(vendor))
+ snprintf(humanname, sizeof(humanname), _("Audio codec %s: %s"), _name, vendor);
+}
+
+void alsa::start_measurement(void)
+{
+ char filename[PATH_MAX];
+ ifstream file;
+
+ snprintf(filename, sizeof(filename), "%s/power_off_acct", sysfs_path);
+ try {
+ file.open(filename, ios::in);
+ if (file) {
+ file >> start_inactive;
+ }
+ file.close();
+ snprintf(filename, sizeof(filename), "%s/power_on_acct", sysfs_path);
+ file.open(filename, ios::in);
+
+ if (file) {
+ file >> start_active;
+ }
+ file.close();
+ }
+ catch (std::ios_base::failure &c) {
+ fprintf(stderr, "%s\n", c.what());
+ }
+}
+
+void alsa::end_measurement(void)
+{
+ char filename[PATH_MAX];
+ ifstream file;
+ double p;
+
+ snprintf(filename, sizeof(filename), "%s/power_off_acct", sysfs_path);
+ try {
+ file.open(filename, ios::in);
+ if (file) {
+ file >> end_inactive;
+ }
+ file.close();
+ snprintf(filename, sizeof(filename), "%s/power_on_acct", sysfs_path);
+ file.open(filename, ios::in);
+
+ if (file) {
+ file >> end_active;
+ }
+ file.close();
+ }
+ catch (std::ios_base::failure &c) {
+ fprintf(stderr, "%s\n", c.what());
+ }
+
+ p = (end_active - start_active) / (0.001 + end_active + end_inactive - start_active - start_inactive) * 100.0;
+ report_utilization(name, p);
+}
+
+
+double alsa::utilization(void)
+{
+ double p;
+
+ p = (end_active - start_active) / (0.001 + end_active - start_active + end_inactive - start_inactive) * 100.0;
+
+ return p;
+}
+
+const char * alsa::device_name(void)
+{
+ return name;
+}
+
+static void create_all_alsa_callback(const char *d_name)
+{
+ char filename[PATH_MAX];
+ class alsa *bl;
+
+ if (strncmp(d_name, "hwC", 3) != 0)
+ return;
+
+ snprintf(filename, sizeof(filename), "/sys/class/sound/%s/power_on_acct", d_name);
+ if (access(filename, R_OK) != 0)
+ return;
+
+ snprintf(filename, sizeof(filename), "/sys/class/sound/%s", d_name);
+ bl = new class alsa(d_name, filename);
+ all_devices.push_back(bl);
+ register_parameter("alsa-codec-power", 0.5);
+}
+
+void create_all_alsa(void)
+{
+ process_directory("/sys/class/sound/", create_all_alsa_callback);
+}
+
+double alsa::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ double power;
+ double factor;
+ double util;
+ static int index = 0;
+
+ power = 0;
+ if (!index)
+ index = get_param_index("alsa-codec-power");
+
+ factor = get_parameter_value(index, bundle);
+
+ util = get_result_value(rindex, result);
+
+ power += util * factor / 100.0;
+
+ return power;
+}
+
+void alsa::register_power_with_devlist(struct result_bundle *results, struct parameter_bundle *bundle)
+{
+ register_devpower(&name[7], power_usage(results, bundle), this);
+}
+
+const char * alsa::human_name(void)
+{
+ pt_strcpy(temp_buf, humanname);
+ if (strlen(guilty) > 0)
+ snprintf(temp_buf, sizeof(temp_buf), "%s (%s)", humanname, guilty);
+ return temp_buf;
+}
diff --git a/src/devices/alsa.h b/src/devices/alsa.h
new file mode 100644
index 0000000..b68203f
--- /dev/null
+++ b/src/devices/alsa.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_ALSA_H
+#define _INCLUDE_GUARD_ALSA_H
+
+
+#include "device.h"
+#include "../parameters/parameters.h"
+
+#include <stdint.h>
+#include <limits.h>
+
+class alsa: public device {
+ uint64_t start_active, end_active;
+ uint64_t start_inactive, end_inactive;
+ char sysfs_path[PATH_MAX];
+ char name[4096];
+ char humanname[4096];
+ char temp_buf[4096];
+ int rindex;
+public:
+
+ alsa(const char *_name, const char *path);
+
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+ virtual double utilization(void); /* percentage */
+
+ virtual const char * class_name(void) { return "alsa";};
+
+ virtual const char * device_name(void);
+ virtual const char * human_name(void);
+ virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
+ virtual int power_valid(void) { return utilization_power_valid(rindex);};
+
+ virtual void register_power_with_devlist(struct result_bundle *results, struct parameter_bundle *bundle);
+ virtual int grouping_prio(void) { return 0; };
+
+};
+
+extern void create_all_alsa(void);
+
+
+#endif
diff --git a/src/devices/backlight.cpp b/src/devices/backlight.cpp
new file mode 100644
index 0000000..c73e4c9
--- /dev/null
+++ b/src/devices/backlight.cpp
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <iostream>
+#include <fstream>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <limits.h>
+
+
+using namespace std;
+
+#include "device.h"
+#include "backlight.h"
+#include "../parameters/parameters.h"
+
+#include <string.h>
+
+
+backlight::backlight(const char *_name, const char *path): device()
+{
+ min_level = 0;
+ max_level = 0;
+ start_level = 0;
+ end_level = 0;
+ pt_strcpy(sysfs_path, path);
+ register_sysfs_path(sysfs_path);
+ snprintf(name, sizeof(name) - 1, "backlight:%s", _name);
+ r_index = get_result_index(name);
+ r_index_power = 0;
+}
+
+void backlight::start_measurement(void)
+{
+ char filename[PATH_MAX];
+ ifstream file;
+
+ snprintf(filename, sizeof(filename), "%s/max_brightness", sysfs_path);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> max_level;
+ }
+ file.close();
+
+ snprintf(filename, sizeof(filename), "%s/actual_brightness", sysfs_path);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> start_level;
+ file.close();
+ }
+}
+
+static int dpms_screen_on(void)
+{
+ DIR *dir;
+ struct dirent *entry;
+ char filename[PATH_MAX];
+ char line[4096];
+ ifstream file;
+
+ dir = opendir("/sys/class/drm/card0");
+ if (!dir)
+ return 1;
+ while (1) {
+ entry = readdir(dir);
+ if (!entry)
+ break;
+
+ if (strncmp(entry->d_name, "card", 4) != 0)
+ continue;
+ snprintf(filename, sizeof(filename), "/sys/class/drm/card0/%s/enabled", entry->d_name);
+ file.open(filename, ios::in);
+ if (!file)
+ continue;
+ file.getline(line, sizeof(line));
+ file.close();
+ if (strcmp(line, "enabled") != 0)
+ continue;
+ snprintf(filename, sizeof(filename), "/sys/class/drm/card0/%s/dpms", entry->d_name);
+ file.open(filename, ios::in);
+ if (!file)
+ continue;
+ file.getline(line, sizeof(line));
+ file.close();
+ if (strcmp(line, "On") == 0) {
+ closedir(dir);
+ return 1;
+ }
+ }
+ closedir(dir);
+ return 0;
+}
+
+void backlight::end_measurement(void)
+{
+ char filename[PATH_MAX];
+ char powername[4096];
+ ifstream file;
+ double p;
+ int _backlight = 0;
+
+ snprintf(filename, sizeof(filename), "%s/actual_brightness", sysfs_path);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> end_level;
+ }
+ file.close();
+
+ if (dpms_screen_on()) {
+ p = 100.0 * (end_level + start_level) / 2 / max_level;
+ _backlight = 100;
+ } else {
+ p = 0;
+ }
+
+ report_utilization(name, p);
+ snprintf(powername, sizeof(powername), "%s-power", name);
+ report_utilization(powername, _backlight);
+}
+
+
+double backlight::utilization(void)
+{
+ double p;
+
+ p = 100.0 * (end_level + start_level) / 2 / max_level;
+ return p;
+}
+
+const char * backlight::device_name(void)
+{
+ return name;
+}
+
+static void create_all_backlights_callback(const char *d_name)
+{
+ class backlight *bl;
+ char filename[PATH_MAX];
+ snprintf(filename, sizeof(filename), "/sys/class/backlight/%s", d_name);
+ bl = new class backlight(d_name, filename);
+ all_devices.push_back(bl);
+}
+
+void create_all_backlights(void)
+{
+ process_directory("/sys/class/backlight/", create_all_backlights_callback);
+ register_parameter("backlight");
+ register_parameter("backlight-power");
+ register_parameter("backlight-boost-40", 0, 0.5);
+ register_parameter("backlight-boost-80", 0, 0.5);
+ register_parameter("backlight-boost-100", 0, 0.5);
+}
+
+double backlight::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ double power;
+ double factor;
+ double _utilization;
+ char powername[4096];
+ static int bl_index = 0, blp_index = 0, bl_boost_index40 = 0, bl_boost_index80, bl_boost_index100;
+
+ if (!bl_index)
+ bl_index = get_param_index("backlight");
+ if (!blp_index)
+ blp_index = get_param_index("backlight-power");
+ if (!bl_boost_index40)
+ bl_boost_index40 = get_param_index("backlight-boost-40");
+ if (!bl_boost_index80)
+ bl_boost_index80 = get_param_index("backlight-boost-80");
+ if (!bl_boost_index100)
+ bl_boost_index100 = get_param_index("backlight-boost-100");
+
+ power = 0;
+ factor = get_parameter_value(bl_index, bundle);
+ _utilization = get_result_value(r_index, result);
+
+ power += _utilization * factor / 100.0;
+
+ /*
+ * most machines have a non-linear backlight scale. to compensate, add a fixed value
+ * once the brightness hits 40% and 80%
+ */
+
+ if (_utilization >=99)
+ power += get_parameter_value(bl_boost_index100, bundle);
+ else if (_utilization >=80)
+ power += get_parameter_value(bl_boost_index80, bundle);
+ else if (_utilization >=40)
+ power += get_parameter_value(bl_boost_index40, bundle);
+
+ factor = get_parameter_value(blp_index, bundle);
+
+ if (!r_index_power) {
+ sprintf(powername, "%s-power", name);
+ r_index_power = get_result_index(powername);
+ }
+ _utilization = get_result_value(r_index_power, result);
+
+ power += _utilization * factor / 100.0;
+
+ return power;
+}
diff --git a/src/devices/backlight.h b/src/devices/backlight.h
new file mode 100644
index 0000000..1dac778
--- /dev/null
+++ b/src/devices/backlight.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_BACKLIGHT_H
+#define _INCLUDE_GUARD_BACKLIGHT_H
+
+#include <limits.h>
+
+#include "device.h"
+
+class backlight: public device {
+ int min_level, max_level;
+ int start_level, end_level;
+ char sysfs_path[PATH_MAX];
+ char name[4096];
+ int r_index;
+ int r_index_power;
+public:
+
+ backlight(const char *_name, const char *path);
+
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+ virtual double utilization(void); /* percentage */
+
+ virtual const char * class_name(void) { return "backlight";};
+
+ virtual const char * device_name(void);
+ virtual const char * human_name(void) { return "Display backlight";};
+ virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
+ virtual int grouping_prio(void) { return 10; };
+};
+
+extern void create_all_backlights(void);
+
+
+#endif
diff --git a/src/devices/devfreq.cpp b/src/devices/devfreq.cpp
new file mode 100644
index 0000000..b194ac4
--- /dev/null
+++ b/src/devices/devfreq.cpp
@@ -0,0 +1,334 @@
+/*
+ * Copyright 2012, Linaro
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Rajagopal Venkat <rajagopal.venkat@linaro.org>
+ */
+
+#include <iostream>
+#include <fstream>
+
+#include <dirent.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "device.h"
+#include "devfreq.h"
+#include "../display.h"
+#include "../cpu/cpu.h"
+#include "../report/report.h"
+#include "../report/report-maker.h"
+
+static bool is_enabled = true;
+static DIR *dir = NULL;
+
+static vector<class devfreq *> all_devfreq;
+
+devfreq::devfreq(const char* dpath): device()
+{
+ pt_strcpy(dir_name, dpath);
+}
+
+uint64_t devfreq::parse_freq_time(char* pchr)
+{
+ char *cptr, *pptr = pchr;
+ uint64_t ctime;
+
+ cptr = strtok(pchr, " :");
+ while (cptr != NULL) {
+ cptr = strtok(NULL, " :");
+ if (cptr )
+ pptr = cptr;
+ }
+
+ ctime = strtoull(pptr, NULL, 10);
+ return ctime;
+}
+
+void devfreq::process_time_stamps()
+{
+ unsigned int i;
+ uint64_t active_time = 0;
+
+ sample_time = (1000000.0 * (stamp_after.tv_sec - stamp_before.tv_sec))
+ + ((stamp_after.tv_usec - stamp_before.tv_usec) );
+
+ for (i=0; i < dstates.size()-1; i++) {
+ struct frequency *state = dstates[i];
+ state->time_after = 1000 * (state->time_after - state->time_before);
+ active_time += state->time_after;
+ }
+ /* Compute idle time for the device */
+ dstates[i]->time_after = sample_time - active_time;
+}
+
+void devfreq::add_devfreq_freq_state(uint64_t freq, uint64_t time)
+{
+ struct frequency *state;
+
+ state = new(std::nothrow) struct frequency;
+ if (!state)
+ return;
+
+ memset(state, 0, sizeof(*state));
+ dstates.push_back(state);
+
+ state->freq = freq;
+ if (freq == 0)
+ strcpy(state->human_name, "Idle");
+ else
+ hz_to_human(freq, state->human_name);
+ state->time_before = time;
+}
+
+void devfreq::update_devfreq_freq_state(uint64_t freq, uint64_t time)
+{
+ unsigned int i;
+ struct frequency *state = NULL;
+
+ for(i=0; i < dstates.size(); i++) {
+ if (freq == dstates[i]->freq)
+ state = dstates[i];
+ }
+
+ if (state == NULL) {
+ add_devfreq_freq_state(freq, time);
+ return;
+ }
+
+ state->time_after = time;
+}
+
+void devfreq::parse_devfreq_trans_stat(char *dname)
+{
+ ifstream file;
+ char filename[256];
+
+ snprintf(filename, sizeof(filename), "/sys/class/devfreq/%s/trans_stat", dir_name);
+ file.open(filename);
+
+ if (!file)
+ return;
+
+ char line[1024];
+ char *c;
+
+ while (file) {
+ uint64_t freq;
+ uint64_t time;
+ char *pchr;
+
+ memset(line, 0, sizeof(line));
+ file.getline(line, sizeof(line));
+
+ pchr = strchr(line, '*');
+ pchr = (pchr != NULL) ? pchr+1 : line;
+
+ freq = strtoull(pchr, &c, 10);
+ if (!freq)
+ continue;
+
+ time = parse_freq_time(pchr);
+ update_devfreq_freq_state(freq, time);
+ }
+ file.close();
+}
+
+void devfreq::start_measurement(void)
+{
+ unsigned int i;
+
+ for (i=0; i < dstates.size(); i++)
+ delete dstates[i];
+ dstates.resize(0);
+ sample_time = 0;
+
+ gettimeofday(&stamp_before, NULL);
+ parse_devfreq_trans_stat(dir_name);
+ /* add device idle state */
+ update_devfreq_freq_state(0, 0);
+}
+
+void devfreq::end_measurement(void)
+{
+ parse_devfreq_trans_stat(dir_name);
+ gettimeofday(&stamp_after, NULL);
+ process_time_stamps();
+}
+
+double devfreq::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ return 0;
+}
+
+double devfreq::utilization(void)
+{
+ return 0;
+}
+
+void devfreq::fill_freq_utilization(unsigned int idx, char *buf)
+{
+ buf[0] = 0;
+
+ if (idx < dstates.size() && dstates[idx]) {
+ struct frequency *state = dstates[idx];
+ sprintf(buf, " %5.1f%% ", percentage(1.0 * state->time_after / sample_time));
+ }
+}
+
+void devfreq::fill_freq_name(unsigned int idx, char *buf)
+{
+ buf[0] = 0;
+
+ if (idx < dstates.size() && dstates[idx]) {
+ sprintf(buf, "%-15s", dstates[idx]->human_name);
+ }
+}
+
+void start_devfreq_measurement(void)
+{
+ unsigned int i;
+
+ for (i=0; i<all_devfreq.size(); i++)
+ all_devfreq[i]->start_measurement();
+}
+
+void end_devfreq_measurement(void)
+{
+ unsigned int i;
+
+ for (i=0; i<all_devfreq.size(); i++)
+ all_devfreq[i]->end_measurement();
+}
+
+static void devfreq_dev_callback(const char *d_name)
+{
+ devfreq *df = new(std::nothrow) class devfreq(d_name);
+ if (df)
+ all_devfreq.push_back(df);
+}
+
+void create_all_devfreq_devices(void)
+{
+ int num = 0;
+
+ std::string p = "/sys/class/devfreq/";
+ dir = opendir(p.c_str());
+ if (dir == NULL) {
+ fprintf(stderr, "Devfreq not enabled\n");
+ is_enabled = false;
+ return;
+ }
+
+ while(readdir(dir) != NULL)
+ num++;
+
+ if (num == 2) {
+ fprintf(stderr, "Devfreq not enabled\n");
+ is_enabled = false;
+ closedir(dir);
+ dir = NULL;
+ return;
+ }
+
+ callback fn = &devfreq_dev_callback;
+ process_directory(p.c_str(), fn);
+}
+
+void initialize_devfreq(void)
+{
+ if (is_enabled)
+ create_tab("Device Freq stats", _("Device Freq stats"));
+}
+
+void display_devfreq_devices(void)
+{
+ unsigned int i, j;
+ WINDOW *win;
+ char fline[1024];
+ char buf[128];
+
+ win = get_ncurses_win("Device Freq stats");
+ if (!win)
+ return;
+
+ wclear(win);
+ wmove(win, 2,0);
+
+ if (!is_enabled) {
+ wprintw(win, _(" Devfreq is not enabled"));
+ return;
+ }
+
+ if (!all_devfreq.size()) {
+ wprintw(win, _(" No devfreq devices available"));
+ return;
+ }
+
+ for (i=0; i<all_devfreq.size(); i++) {
+
+ class devfreq *df = all_devfreq[i];
+ wprintw(win, "\n%s\n", df->device_name());
+
+ for(j=0; j < df->dstates.size(); j++) {
+ memset(fline, 0, sizeof(fline));
+ strcpy(fline, "\t");
+ df->fill_freq_name(j, buf);
+ strcat(fline, buf);
+ df->fill_freq_utilization(j, buf);
+ strcat(fline, buf);
+ strcat(fline, "\n");
+ wprintw(win, "%s", fline);
+ }
+ wprintw(win, "\n");
+ }
+}
+
+void report_devfreq_devices(void)
+{
+ if (!is_enabled) {
+ return;
+ }
+
+/* todo: adapt to new report format */
+
+}
+
+void clear_all_devfreq()
+{
+ unsigned int i, j;
+
+ for (i=0; i < all_devfreq.size(); i++) {
+ class devfreq *df = all_devfreq[i];
+
+ for(j=0; j < df->dstates.size(); j++)
+ delete df->dstates[j];
+
+ delete df;
+ }
+ all_devfreq.clear();
+ /* close /sys/class/devfreq */
+ if (dir != NULL) {
+ closedir(dir);
+ dir = NULL;
+ }
+}
diff --git a/src/devices/devfreq.h b/src/devices/devfreq.h
new file mode 100644
index 0000000..4a8983b
--- /dev/null
+++ b/src/devices/devfreq.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2012, Linaro
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Rajagopal Venkat <rajagopal.venkat@linaro.org>
+ */
+#ifndef _INCLUDE_GUARD_DEVFREQ_H
+#define _INCLUDE_GUARD_DEVFREQ_H
+
+#include "device.h"
+#include "../parameters/parameters.h"
+#include <sys/time.h>
+
+struct frequency;
+
+class devfreq: public device {
+ char dir_name[128];
+ struct timeval stamp_before, stamp_after;
+ double sample_time;
+
+ uint64_t parse_freq_time(char *ptr);
+ void add_devfreq_freq_state(uint64_t freq, uint64_t time);
+ void update_devfreq_freq_state(uint64_t freq, uint64_t time);
+ void parse_devfreq_trans_stat(char *dname);
+ void process_time_stamps();
+
+public:
+
+ vector<struct frequency *> dstates;
+
+ devfreq(const char *c);
+ void fill_freq_utilization(unsigned int idx, char *buf);
+ void fill_freq_name(unsigned int idx, char *buf);
+
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+ virtual double utilization(void); /* percentage */
+
+ virtual const char * class_name(void) { return "devfreq";};
+
+ virtual const char * device_name(void) { return dir_name;};
+ virtual const char * human_name(void) { return "devfreq";};
+ virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
+ virtual const char * util_units(void) { return " rpm"; };
+ virtual int power_valid(void) { return 0; /*utilization_power_valid(r_index);*/};
+ virtual int grouping_prio(void) { return 1; };
+};
+
+extern void create_all_devfreq_devices(void);
+extern void clear_all_devfreq(void);
+extern void display_devfreq_devices(void);
+extern void report_devfreq_devices(void);
+extern void initialize_devfreq(void);
+extern void start_devfreq_measurement(void);
+extern void end_devfreq_measurement(void);
+
+#endif
diff --git a/src/devices/device.cpp b/src/devices/device.cpp
new file mode 100644
index 0000000..f191072
--- /dev/null
+++ b/src/devices/device.cpp
@@ -0,0 +1,345 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+
+#include "device.h"
+#include <vector>
+#include <algorithm>
+#include <stdio.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+using namespace std;
+
+#include "backlight.h"
+#include "usb.h"
+#include "ahci.h"
+#include "alsa.h"
+#include "rfkill.h"
+#include "i915-gpu.h"
+#include "thinkpad-fan.h"
+#include "thinkpad-light.h"
+#include "network.h"
+#include "runtime_pm.h"
+
+#include "../parameters/parameters.h"
+#include "../display.h"
+#include "../lib.h"
+#include "../report/report.h"
+#include "../report/report-maker.h"
+#include "../report/report-data-html.h"
+#include "../measurement/measurement.h"
+#include "../devlist.h"
+#include <unistd.h>
+
+device::device(void)
+{
+ cached_valid = 0;
+ hide = 0;
+
+ memset(guilty, 0, sizeof(guilty));
+ memset(real_path, 0, sizeof(real_path));
+}
+
+
+void device::register_sysfs_path(const char *path)
+{
+ char current_path[PATH_MAX + 1];
+ int iter = 0;
+ pt_strcpy(current_path, path);
+
+ while (iter++ < 10) {
+ char test_path[PATH_MAX + 1];
+ snprintf(test_path, sizeof(test_path), "%s/device", current_path);
+ if (access(test_path, R_OK) == 0)
+ strcpy(current_path, test_path);
+ else
+ break;
+ }
+
+ if (!realpath(current_path, real_path))
+ real_path[0] = 0;
+}
+
+void device::start_measurement(void)
+{
+ hide = false;
+}
+
+void device::end_measurement(void)
+{
+}
+
+double device::utilization(void)
+{
+ return 0.0;
+}
+
+
+
+vector<class device *> all_devices;
+
+
+void devices_start_measurement(void)
+{
+ unsigned int i;
+ for (i = 0; i < all_devices.size(); i++)
+ all_devices[i]->start_measurement();
+}
+
+void devices_end_measurement(void)
+{
+ unsigned int i;
+ for (i = 0; i < all_devices.size(); i++)
+ all_devices[i]->end_measurement();
+
+ clear_devpower();
+
+ for (i = 0; i < all_devices.size(); i++) {
+ all_devices[i]->hide = false;
+ all_devices[i]->register_power_with_devlist(&all_results, &all_parameters);
+ }
+}
+
+static bool power_device_sort(class device * i, class device * j)
+{
+ double pI, pJ;
+ pI = i->power_usage(&all_results, &all_parameters);
+ pJ = j->power_usage(&all_results, &all_parameters);
+
+ if (equals(pI, pJ)) {
+ int vI, vJ;
+ vI = i->power_valid();
+ vJ = j->power_valid();
+
+ if (vI != vJ)
+ return vI > vJ;
+
+ return i->utilization() > j->utilization();
+ }
+ return pI > pJ;
+}
+
+
+void report_devices(void)
+{
+ WINDOW *win;
+ unsigned int i;
+ int show_power;
+ double pw;
+
+ char util[128];
+ char power[128];
+
+ win = get_ncurses_win("Device stats");
+ if (!win)
+ return;
+
+ show_power = global_power_valid();
+
+ wclear(win);
+ wmove(win, 2,0);
+
+ sort(all_devices.begin(), all_devices.end(), power_device_sort);
+
+
+
+ pw = global_power();
+ if (pw > 0.0001) {
+ char buf[32];
+ wprintw(win, _("The battery reports a discharge rate of %sW\n"),
+ fmt_prefix(pw, buf));
+ wprintw(win, _("The energy consumed was %sJ\n"),
+ fmt_prefix(global_joules(), buf));
+ }
+
+ if (show_power) {
+ char buf[32];
+ wprintw(win, _("System baseline power is estimated at %sW\n"),
+ fmt_prefix(get_parameter_value("base power"), buf));
+ }
+
+ if (pw > 0.0001 || show_power)
+ wprintw(win, "\n");
+ if (show_power)
+ wprintw(win, _("Power est. Usage Device name\n"));
+ else
+ wprintw(win, _(" Usage Device name\n"));
+
+ for (i = 0; i < all_devices.size(); i++) {
+ double P;
+
+ util[0] = 0;
+
+ if (all_devices[i]->util_units()) {
+ if (all_devices[i]->utilization() < 1000)
+ sprintf(util, "%5.1f%s", all_devices[i]->utilization(), all_devices[i]->util_units());
+ else
+ sprintf(util, "%5i%s", (int)all_devices[i]->utilization(), all_devices[i]->util_units());
+ }
+ while (strlen(util) < 13) strcat(util, " ");
+
+ P = all_devices[i]->power_usage(&all_results, &all_parameters);
+
+ format_watts(P, power, 11);
+
+ if (!show_power || !all_devices[i]->power_valid())
+ strcpy(power, " ");
+
+
+ wprintw(win, "%s %s %s\n",
+ power,
+ util,
+ all_devices[i]->human_name()
+ );
+ }
+}
+
+void show_report_devices(void)
+{
+ unsigned int i;
+ int show_power, cols, rows, idx;
+ double pw;
+
+ show_power = global_power_valid();
+ sort(all_devices.begin(), all_devices.end(), power_device_sort);
+
+ /* div attr css_class and css_id */
+ tag_attr div_attr;
+ init_div(&div_attr, "clear_block", "devinfo");
+
+ /* Set Table attributes, rows, and cols */
+ table_attributes std_table_css;
+ cols=2;
+ if (show_power)
+ cols=3;
+
+ idx = cols;
+ rows= all_devices.size() + 1;
+ init_std_side_table_attr(&std_table_css, rows, cols);
+
+ /* Set Title attributes */
+ tag_attr title_attr;
+ init_title_attr(&title_attr);
+
+ /* Add section */
+ report.add_div(&div_attr);
+
+ /* Device Summary */
+ int summary_size=2;
+ string *summary = new string[summary_size];
+ pw = global_power();
+ char buf[32];
+ if (pw > 0.0001) {
+ summary[0]= __("The battery reports a discharge rate of: ");
+ summary[1]=string(fmt_prefix(pw, buf));
+ summary[1].append(" W");
+ report.add_summary_list(summary, summary_size);
+
+ summary[0]= __("The energy consumed was : ");
+ summary[1]=string(fmt_prefix(global_joules(), buf));
+ summary[1].append(" J");
+ report.add_summary_list(summary, summary_size);
+ }
+
+ if (show_power) {
+ summary[0]=__("The system baseline power is estimated at: ");
+ summary[1]=string(fmt_prefix(get_parameter_value("base power"), buf));
+ summary[1].append(" W");
+ report.add_summary_list(summary, summary_size);
+ }
+ delete [] summary;
+
+ /* Set array of data in row Major order */
+ string *device_data = new string[cols * rows];
+ device_data[0]= __("Usage");
+ device_data[1]= __("Device Name");
+ if (show_power)
+ device_data[2]= __("PW Estimate");
+
+ for (i = 0; i < all_devices.size(); i++) {
+ double P;
+ char util[128];
+ char power[128];
+
+ util[0] = 0;
+ if (all_devices[i]->util_units()) {
+ if (all_devices[i]->utilization() < 1000)
+ sprintf(util, "%5.1f%s",
+ all_devices[i]->utilization(),
+ all_devices[i]->util_units());
+ else
+ sprintf(util, "%5i%s",
+ (int)all_devices[i]->utilization(),
+ all_devices[i]->util_units());
+ }
+
+ P = all_devices[i]->power_usage(&all_results, &all_parameters);
+ format_watts(P, power, 11);
+
+ if (!show_power || !all_devices[i]->power_valid())
+ strcpy(power, " ");
+
+ device_data[idx]= string(util);
+ idx+=1;
+
+ device_data[idx]= string(all_devices[i]->human_name());
+ idx+=1;
+
+ if (show_power) {
+ device_data[idx]= string(power);
+ idx+=1;
+ }
+ }
+ /* Report Output */
+ report.add_title(&title_attr, __("Device Power Report"));
+ report.add_table(device_data, &std_table_css);
+ delete [] device_data;
+}
+
+
+void create_all_devices(void)
+{
+ create_all_backlights();
+ create_all_usb_devices();
+ create_all_ahcis();
+ create_all_alsa();
+ create_all_rfkills();
+ create_i915_gpu();
+ create_thinkpad_fan();
+ create_thinkpad_light();
+ create_all_nics();
+ create_all_runtime_pm_devices();
+}
+
+
+void clear_all_devices(void)
+{
+ unsigned int i;
+ for (i = 0; i < all_devices.size(); i++) {
+ delete all_devices[i];
+ }
+ all_devices.clear();
+}
diff --git a/src/devices/device.h b/src/devices/device.h
new file mode 100644
index 0000000..a373875
--- /dev/null
+++ b/src/devices/device.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_DEVICE_H
+#define _INCLUDE_GUARD_DEVICE_H
+
+
+#include <vector>
+#include <limits.h>
+
+struct parameter_bundle;
+struct result_bundle;
+
+class device {
+public:
+ int cached_valid;
+ bool hide;
+
+ char guilty[4096];
+ char real_path[PATH_MAX+1];
+
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+ device(void);
+
+ virtual ~device() {};
+
+ void register_sysfs_path(const char *path);
+
+ virtual double utilization(void); /* percentage */
+
+ virtual const char * util_units(void) { return "%"; };
+
+ virtual const char * class_name(void) { return "abstract device";};
+ virtual const char * device_name(void) { return "abstract device";};
+
+ virtual const char * human_name(void) { return device_name(); };
+
+ virtual double power_usage(struct result_bundle *results, struct parameter_bundle *bundle) { return 0.0; };
+
+ virtual bool show_in_list(void) {return !hide;};
+
+ virtual int power_valid(void) { return 1;};
+
+ virtual void register_power_with_devlist(struct result_bundle *results, struct parameter_bundle *bundle) { ; };
+
+ virtual int grouping_prio(void) { return 0; }; /* priority of this device class if multiple classes match to the same underlying device. 0 is lowest */
+};
+
+using namespace std;
+
+extern vector<class device *> all_devices;
+
+extern void devices_start_measurement(void);
+extern void devices_end_measurement(void);
+extern void show_report_devices(void);
+extern void report_devices(void);
+
+
+extern void create_all_devices(void);
+extern void clear_all_devices(void);
+
+#endif
diff --git a/src/devices/gpu_rapl_device.cpp b/src/devices/gpu_rapl_device.cpp
new file mode 100644
index 0000000..71d71a0
--- /dev/null
+++ b/src/devices/gpu_rapl_device.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Srinivas Pandruvada<Srinivas.Pandruvada@linux.intel.com>
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "../parameters/parameters.h"
+#include "gpu_rapl_device.h"
+
+gpu_rapl_device::gpu_rapl_device(i915gpu *parent)
+ : i915gpu(),
+ device_valid(false)
+{
+ last_time = time(NULL);
+ if (rapl.pp1_domain_present()) {
+ device_valid = true;
+ parent->add_child(this);
+ rapl.get_pp1_energy_status(&last_energy);
+ }
+}
+
+void gpu_rapl_device::start_measurement(void)
+{
+ last_time = time(NULL);
+
+ rapl.get_pp1_energy_status(&last_energy);
+}
+
+void gpu_rapl_device::end_measurement(void)
+{
+ time_t curr_time = time(NULL);
+ double energy;
+
+ consumed_power = 0.0;
+ if ((curr_time - last_time) > 0) {
+ rapl.get_pp1_energy_status(&energy);
+ consumed_power = (energy-last_energy)/(curr_time-last_time);
+ last_energy = energy;
+ last_time = curr_time;
+ }
+}
+
+double gpu_rapl_device::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ if (rapl.pp1_domain_present())
+ return consumed_power;
+ else
+ return 0.0;
+}
diff --git a/src/devices/gpu_rapl_device.h b/src/devices/gpu_rapl_device.h
new file mode 100644
index 0000000..fbde246
--- /dev/null
+++ b/src/devices/gpu_rapl_device.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Srinivas Pandruvada <Srinivas.Pandruvada@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_GPU_RAPL_DEVICE_H
+#define _INCLUDE_GUARD_GPU_RAPL_DEVICE_H
+
+#include <vector>
+#include <string>
+
+using namespace std;
+
+#include <sys/time.h>
+#include "i915-gpu.h"
+#include "cpu/rapl/rapl_interface.h"
+
+class gpu_rapl_device: public i915gpu {
+
+ c_rapl_interface rapl;
+ time_t last_time;
+ double last_energy;
+ double consumed_power;
+ bool device_valid;
+
+public:
+ gpu_rapl_device(i915gpu *parent);
+ virtual const char * class_name(void) { return "GPU core";};
+ virtual const char * device_name(void) { return "GPU core";};
+ bool device_present() { return device_valid;}
+ virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+};
+
+
+#endif
diff --git a/src/devices/i915-gpu.cpp b/src/devices/i915-gpu.cpp
new file mode 100644
index 0000000..d0f1d69
--- /dev/null
+++ b/src/devices/i915-gpu.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <iostream>
+#include <fstream>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <limits.h>
+#include "../lib.h"
+
+using namespace std;
+
+#include "device.h"
+#include "i915-gpu.h"
+#include "../parameters/parameters.h"
+#include "../process/powerconsumer.h"
+#include "gpu_rapl_device.h"
+
+#include <string.h>
+#include <unistd.h>
+
+i915gpu::i915gpu(): device()
+{
+ index = get_param_index("gpu-operations");
+ rindex = get_result_index("gpu-operations");
+}
+
+const char * i915gpu::device_name(void)
+{
+ if (child_devices.size())
+ return "GPU misc";
+ else
+ return "GPU";
+}
+
+void i915gpu::start_measurement(void)
+{
+}
+
+void i915gpu::end_measurement(void)
+{
+}
+
+
+double i915gpu::utilization(void)
+{
+ return get_result_value(rindex);
+
+}
+
+void create_i915_gpu(void)
+{
+ char filename[PATH_MAX];
+ class i915gpu *gpu;
+ gpu_rapl_device *rapl_dev;
+
+ pt_strcpy(filename, "/sys/kernel/debug/tracing/events/i915/i915_gem_ring_dispatch/format");
+
+ if (access(filename, R_OK) !=0) {
+ /* try an older tracepoint */
+ pt_strcpy(filename, "/sys/kernel/debug/tracing/events/i915/i915_gem_request_submit/format");
+ if (access(filename, R_OK) != 0)
+ return;
+ }
+
+ register_parameter("gpu-operations");
+
+ gpu = new class i915gpu();
+ all_devices.push_back(gpu);
+
+ rapl_dev = new class gpu_rapl_device(gpu);
+ if (rapl_dev->device_present())
+ all_devices.push_back(rapl_dev);
+}
+
+
+
+double i915gpu::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ double power;
+ double factor;
+ double util;
+ double child_power;
+
+ power = 0;
+ factor = get_parameter_value(index, bundle);
+ util = get_result_value(rindex, result);
+
+ power += util * factor / 100.0;
+ for (unsigned int i = 0; i < child_devices.size(); ++i) {
+ child_power = child_devices[i]->power_usage(result, bundle);
+ if ((power - child_power) > 0.0)
+ power -= child_power;
+ }
+
+ return power;
+}
diff --git a/src/devices/i915-gpu.h b/src/devices/i915-gpu.h
new file mode 100644
index 0000000..7653b94
--- /dev/null
+++ b/src/devices/i915-gpu.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_i915_GPU_H
+#define _INCLUDE_GUARD_i915_GPU_H
+
+
+#include "device.h"
+
+class i915gpu: public device {
+ int index;
+ int rindex;
+ vector<device *>child_devices;
+
+public:
+
+ i915gpu();
+
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+ virtual double utilization(void); /* percentage */
+
+ virtual const char * class_name(void) { return "GPU";};
+
+ virtual const char * device_name(void);
+ virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
+ virtual bool show_in_list(void) {return false;};
+ virtual const char * util_units(void) { return " ops/s"; };
+
+ virtual void add_child(device *dev_ptr) { child_devices.push_back(dev_ptr);}
+};
+
+extern void create_i915_gpu(void);
+
+
+#endif \ No newline at end of file
diff --git a/src/devices/network.cpp b/src/devices/network.cpp
new file mode 100644
index 0000000..8087b7f
--- /dev/null
+++ b/src/devices/network.cpp
@@ -0,0 +1,441 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <iostream>
+#include <fstream>
+#include <vector>
+#include <string>
+#include <map>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <libgen.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <linux/ethtool.h>
+
+using namespace std;
+
+#include "device.h"
+#include "network.h"
+#include "../lib.h"
+#include "../parameters/parameters.h"
+#include "../process/process.h"
+extern "C" {
+#include "../tuning/iw.h"
+}
+
+#include <string.h>
+#include <net/if.h>
+#include <linux/sockios.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+static map<string, class network *> nics;
+
+#ifdef DISABLE_TRYCATCH
+
+static inline void ethtool_cmd_speed_set(struct ethtool_cmd *ep,
+ __u32 speed)
+{
+
+ ep->speed = (__u16)speed;
+ ep->speed_hi = (__u16)(speed >> 16);
+}
+
+static inline __u32 ethtool_cmd_speed(struct ethtool_cmd *ep)
+{
+ return (ep->speed_hi << 16) | ep->speed;
+}
+
+#endif
+
+static void do_proc_net_dev(void)
+{
+ static time_t last_time;
+ class network *dev;
+ ifstream file;
+ char line[4096];
+ char *c, *c2;
+
+ if (time(NULL) == last_time)
+ return;
+
+ last_time = time(NULL);
+
+ file.open("/proc/net/dev", ios::in);
+ if (!file)
+ return;
+
+ file.getline(line, 4096);
+ file.getline(line, 4096);
+
+ while (file) {
+ int i = 0;
+ unsigned long val = 0;
+ uint64_t pkt = 0;
+ file.getline(line, 4096);
+ c = strchr(line, ':');
+ if (!c)
+ continue;
+ *c = 0;
+ c2 = c +1;
+ c = line; while (c && *c == ' ') c++;
+ /* c now points to the name of the nic */
+
+ dev = nics[c];
+ if (!dev)
+ continue;
+
+ c = c2++;
+ while (c != c2 && strlen(c) > 0) {
+ c2 = c;
+ val = strtoull(c, &c, 10);
+ i++;
+ if (i == 2 || i == 10)
+ pkt += val;
+
+ }
+ dev->pkts = pkt;
+ }
+ file.close();
+}
+
+
+network::network(const char *_name, const char *path): device()
+{
+ char line[4096];
+ std::string filename(path);
+ char devname[128];
+ start_up = 0;
+ end_up = 0;
+ start_speed = 0;
+ end_speed = 0;
+ start_pkts = 0;
+ end_pkts = 0;
+ pkts = 0;
+ valid_100 = -1;
+ valid_1000 = -1;
+ valid_high = -1;
+ valid_powerunsave = -1;
+
+ pt_strcpy(sysfs_path, path);
+ register_sysfs_path(sysfs_path);
+ pt_strcpy(devname, _name);
+ sprintf(humanname, "nic:%s", _name);
+ pt_strcpy(name, devname);
+
+ snprintf(devname, sizeof(devname), "%s-up", _name);
+ index_up = get_param_index(devname);
+ rindex_up = get_result_index(devname);
+
+ snprintf(devname, sizeof(devname), "%s-powerunsave", _name);
+ index_powerunsave = get_param_index(devname);
+ rindex_powerunsave = get_result_index(devname);
+
+ snprintf(devname, sizeof(devname), "%s-link-100", _name);
+ index_link_100 = get_param_index(devname);
+ rindex_link_100 = get_result_index(devname);
+
+ snprintf(devname, sizeof(devname), "%s-link-1000", _name);
+ index_link_1000 = get_param_index(devname);
+ rindex_link_1000 = get_result_index(devname);
+
+ snprintf(devname, sizeof(devname), "%s-link-high", _name);
+ index_link_high = get_param_index(devname);
+ rindex_link_high = get_result_index(devname);
+
+ snprintf(devname, sizeof(devname), "%s-packets", _name);
+ index_pkts = get_param_index(devname);
+ rindex_pkts = get_result_index(devname);
+
+ memset(line, 0, 4096);
+ filename.append("/device/driver");
+ if (readlink(filename.c_str(), line, 4096) > 0) {
+ snprintf(humanname, sizeof(humanname), _("Network interface: %s (%s)"), _name, basename(line));
+ };
+}
+
+static int net_iface_up(const char *iface)
+{
+ int sock;
+ struct ifreq ifr;
+ int ret;
+
+ memset(&ifr, 0, sizeof(struct ifreq));
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock<0)
+ return 0;
+
+ pt_strcpy(ifr.ifr_name, iface);
+
+ /* Check if the interface is up */
+ ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
+ if (ret<0) {
+ close(sock);
+ return 0;
+ }
+
+ if (ifr.ifr_flags & (IFF_UP | IFF_RUNNING)) {
+ close(sock);
+ return 1;
+ }
+
+ close(sock);
+
+ return 0;
+}
+
+static int iface_link(const char *name)
+{
+ int sock;
+ struct ifreq ifr;
+ struct ethtool_value cmd;
+ int link;
+
+ memset(&ifr, 0, sizeof(struct ifreq));
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock<0)
+ return 0;
+
+ pt_strcpy(ifr.ifr_name, name);
+
+ memset(&cmd, 0, sizeof(cmd));
+
+ cmd.cmd = ETHTOOL_GLINK;
+ ifr.ifr_data = (caddr_t)&cmd;
+ ioctl(sock, SIOCETHTOOL, &ifr);
+ close(sock);
+
+ link = cmd.data;
+
+ return link;
+}
+
+
+static int iface_speed(const char *name)
+{
+ int sock;
+ struct ifreq ifr;
+ struct ethtool_cmd cmd;
+ int speed;
+
+ memset(&ifr, 0, sizeof(struct ifreq));
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock<0)
+ return 0;
+
+ pt_strcpy(ifr.ifr_name, name);
+
+ memset(&cmd, 0, sizeof(cmd));
+
+ cmd.cmd = ETHTOOL_GSET;
+ ifr.ifr_data = (caddr_t)&cmd;
+ ioctl(sock, SIOCETHTOOL, &ifr);
+ close(sock);
+
+ speed = ethtool_cmd_speed(&cmd);
+
+
+ if (speed > 0 && speed <= 100)
+ speed = 100;
+ if (speed > 100 && speed <= 1000)
+ speed = 1000;
+ if (speed == 65535 || !iface_link(name))
+ speed = 0; /* no link */
+
+ return speed;
+}
+
+void network::start_measurement(void)
+{
+ start_up = 1;
+ start_speed = 0;
+ end_up = 1;
+ end_speed = 0;
+
+ start_speed = iface_speed(name);
+
+ start_up = net_iface_up(name);
+
+ do_proc_net_dev();
+ start_pkts = pkts;
+
+ gettimeofday(&before, NULL);
+}
+
+
+void network::end_measurement(void)
+{
+ int u_100, u_1000, u_high, u_powerunsave;
+
+ gettimeofday(&after, NULL);
+
+ end_speed = iface_speed(name);
+ end_up = net_iface_up(name);
+ do_proc_net_dev();
+ end_pkts = pkts;
+
+ duration = (after.tv_sec - before.tv_sec) + (after.tv_usec - before.tv_usec) / 1000000.0;
+
+ u_100 = 0;
+ u_1000 = 0;
+ u_high = 0;
+
+ if (start_speed == 100)
+ u_100 += 50;
+ if (start_speed == 1000)
+ u_1000 += 50;
+ if (start_speed > 1000)
+ u_high += 50;
+ if (end_speed == 100)
+ u_100 += 50;
+ if (end_speed == 1000)
+ u_1000 += 50;
+ if (end_speed > 1000)
+ u_high += 50;
+
+ if (start_pkts > end_pkts)
+ end_pkts = start_pkts;
+
+ u_powerunsave = 100 - 100 * get_wifi_power_saving(name);
+
+ report_utilization(rindex_link_100, u_100);
+ report_utilization(rindex_link_1000, u_1000);
+ report_utilization(rindex_link_high, u_high);
+ report_utilization(rindex_up, (start_up+end_up) / 2.0);
+ report_utilization(rindex_pkts, (end_pkts - start_pkts)/(duration + 0.001));
+ report_utilization(rindex_powerunsave, u_powerunsave);
+}
+
+
+double network::utilization(void)
+{
+ return (end_pkts - start_pkts) / (duration + 0.001);
+}
+
+const char * network::device_name(void)
+{
+ return name;
+}
+
+static void netdev_callback(const char *d_name)
+{
+ char devname[128];
+
+ std::string f_name("/sys/class/net/");
+ if (strcmp(d_name, "lo") == 0)
+ return;
+
+ f_name.append(d_name);
+
+ snprintf(devname, sizeof(devname), "%s-up", d_name);
+ register_parameter(devname);
+
+ snprintf(devname, sizeof(devname), "%s-powerunsave", d_name);
+ register_parameter(devname);
+
+ snprintf(devname, sizeof(devname), "%s-link-100", d_name);
+ register_parameter(devname);
+
+ snprintf(devname, sizeof(devname), "%s-link-1000", d_name);
+ register_parameter(devname);
+
+ snprintf(devname, sizeof(devname), "%s-link-high", d_name);
+ register_parameter(devname);
+
+ snprintf(devname, sizeof(devname), "%s-packets", d_name);
+ register_parameter(devname);
+
+ network *bl = new(std::nothrow) class network(d_name, f_name.c_str());
+ if (bl) {
+ all_devices.push_back(bl);
+ nics[d_name] = bl;
+ }
+}
+
+void create_all_nics(callback fn)
+{
+ if (!fn)
+ fn = &netdev_callback;
+ process_directory("/sys/class/net/", fn);
+}
+
+double network::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ double power;
+ double factor;
+ double util;
+
+ power = 0;
+ factor = get_parameter_value(index_up, bundle);
+ util = get_result_value(rindex_up, result);
+
+ power += util * factor;
+
+ if (valid_100 == -1) {
+ valid_100 = utilization_power_valid(rindex_link_100);
+ valid_1000 = utilization_power_valid(rindex_link_1000);
+ valid_high = utilization_power_valid(rindex_link_high);
+ valid_powerunsave = utilization_power_valid(rindex_powerunsave);
+ }
+
+ if (valid_100 > 0) {
+ factor = get_parameter_value(index_link_100, bundle);
+ util = get_result_value(rindex_link_100, result);
+ power += util * factor / 100;
+ }
+
+
+ if (valid_1000 > 0) {
+ factor = get_parameter_value(index_link_1000, bundle);
+ util = get_result_value(rindex_link_1000, result);
+ power += util * factor / 100;
+ }
+
+ if (valid_high > 0) {
+ factor = get_parameter_value(index_link_high, bundle);
+ util = get_result_value(rindex_link_high, result);
+ power += util * factor / 100;
+ }
+
+ if (valid_powerunsave > 0) {
+ factor = get_parameter_value(index_powerunsave, bundle);
+ util = get_result_value(rindex_powerunsave, result);
+ power += util * factor / 100;
+ }
+
+ factor = get_parameter_value(index_pkts, bundle);
+ util = get_result_value(rindex_pkts, result);
+ if (util > 5000)
+ util = 5000;
+
+ power += util * factor / 100;
+
+ return power;
+}
diff --git a/src/devices/network.h b/src/devices/network.h
new file mode 100644
index 0000000..7fb4cc6
--- /dev/null
+++ b/src/devices/network.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_NETWORK_H
+#define _INCLUDE_GUARD_NETWORK_H
+
+#include <sys/time.h>
+#include <limits.h>
+
+#include "device.h"
+#include "../parameters/parameters.h"
+
+class network: public device {
+ int start_up, end_up;
+ uint64_t start_pkts, end_pkts;
+ struct timeval before, after;
+
+ int start_speed; /* 0 is "no link" */
+ int end_speed; /* 0 is "no link" */
+
+ char sysfs_path[PATH_MAX];
+ char name[4096];
+ char humanname[4096];
+ int index_up;
+ int rindex_up;
+ int index_link_100;
+ int rindex_link_100;
+ int index_link_1000;
+ int rindex_link_1000;
+ int index_link_high;
+ int rindex_link_high;
+ int index_pkts;
+ int rindex_pkts;
+ int index_powerunsave;
+ int rindex_powerunsave;
+
+ int valid_100;
+ int valid_1000;
+ int valid_high;
+ int valid_powerunsave;
+public:
+ uint64_t pkts;
+ double duration;
+
+ network(const char *_name, const char *path);
+
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+ virtual double utilization(void);
+ virtual const char * util_units(void) { return " pkts/s"; };
+
+ virtual const char * class_name(void) { return "ethernet";};
+
+ virtual const char * device_name(void);
+ virtual const char * human_name(void) { return humanname; };
+ virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
+ virtual int power_valid(void) { return utilization_power_valid(rindex_up) + utilization_power_valid(rindex_link_100) + utilization_power_valid(rindex_link_1000) + utilization_power_valid(rindex_link_high);};
+ virtual int grouping_prio(void) { return 10; };
+};
+
+extern void create_all_nics(callback fn = NULL);
+
+#endif
diff --git a/src/devices/rfkill.cpp b/src/devices/rfkill.cpp
new file mode 100644
index 0000000..99a652f
--- /dev/null
+++ b/src/devices/rfkill.cpp
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <iostream>
+#include <fstream>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <libgen.h>
+#include <unistd.h>
+#include <limits.h>
+
+
+using namespace std;
+
+#include "device.h"
+#include "rfkill.h"
+#include "../parameters/parameters.h"
+
+#include <string.h>
+#include <unistd.h>
+
+rfkill::rfkill(char *_name, char *path): device()
+{
+ char line[4096];
+ char filename[PATH_MAX];
+ char devname[128];
+ start_soft = 0;
+ start_hard = 0;
+ end_soft = 0;
+ end_hard = 0;
+ pt_strcpy(sysfs_path, path);
+ register_sysfs_path(sysfs_path);
+ snprintf(devname, sizeof(devname), "radio:%s", _name);
+ snprintf(humanname, sizeof(humanname), "radio:%s", _name);
+ pt_strcpy(name, devname);
+ register_parameter(devname);
+ index = get_param_index(devname);
+ rindex = get_result_index(name);
+
+ memset(line, 0, 4096);
+ snprintf(filename, sizeof(filename), "%s/device/driver", path);
+ if (readlink(filename, line, sizeof(line)) > 0) {
+ snprintf(humanname, sizeof(humanname), _("Radio device: %s"), basename(line));
+ }
+ snprintf(filename, sizeof(filename), "%s/device/device/driver", path);
+ if (readlink(filename, line, sizeof(line)) > 0) {
+ snprintf(humanname, sizeof(humanname), _("Radio device: %s"), basename(line));
+ }
+}
+
+void rfkill::start_measurement(void)
+{
+ char filename[PATH_MAX];
+ ifstream file;
+
+ start_hard = 1;
+ start_soft = 1;
+ end_hard = 1;
+ end_soft = 1;
+
+ snprintf(filename, sizeof(filename), "%s/hard", sysfs_path);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> start_hard;
+ }
+ file.close();
+
+ snprintf(filename, sizeof(filename), "%s/soft", sysfs_path);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> start_soft;
+ }
+ file.close();
+}
+
+void rfkill::end_measurement(void)
+{
+ char filename[PATH_MAX];
+ ifstream file;
+
+ snprintf(filename, sizeof(filename), "%s/hard", sysfs_path);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> end_hard;
+ }
+ file.close();
+ snprintf(filename, sizeof(filename), "%s/soft", sysfs_path);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> end_soft;
+ }
+ file.close();
+
+ report_utilization(name, utilization());
+}
+
+
+double rfkill::utilization(void)
+{
+ double p;
+ int rfk;
+
+ rfk = start_soft+end_soft;
+ if (rfk < start_hard+end_hard)
+ rfk = start_hard+end_hard;
+
+ p = 100 - 50.0 * rfk;
+
+ return p;
+}
+
+const char * rfkill::device_name(void)
+{
+ return name;
+}
+
+static void create_all_rfkills_callback(const char *d_name)
+{
+ char filename[PATH_MAX];
+ char name[4096] = {0};
+ class rfkill *bl;
+ ifstream file;
+
+ snprintf(filename, sizeof(filename), "/sys/class/rfkill/%s/name", d_name);
+ strncpy(name, d_name, sizeof(name) - 1);
+ file.open(filename, ios::in);
+ if (file) {
+ file.getline(name, 100);
+ file.close();
+ }
+
+ snprintf(filename, sizeof(filename), "/sys/class/rfkill/%s", d_name);
+ bl = new class rfkill(name, filename);
+ all_devices.push_back(bl);
+}
+
+void create_all_rfkills(void)
+{
+ process_directory("/sys/class/rfkill/", create_all_rfkills_callback);
+}
+
+double rfkill::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ double power;
+ double factor;
+ double util;
+
+ power = 0;
+ factor = get_parameter_value(index, bundle);
+ util = get_result_value(rindex, result);
+
+ power += util * factor / 100.0;
+
+ return power;
+}
diff --git a/src/devices/rfkill.h b/src/devices/rfkill.h
new file mode 100644
index 0000000..429ba18
--- /dev/null
+++ b/src/devices/rfkill.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_RFKILL_H
+#define _INCLUDE_GUARD_RFKILL_H
+
+#include <limits.h>
+
+#include "device.h"
+#include "../parameters/parameters.h"
+
+class rfkill: public device {
+ int start_soft, end_soft;
+ int start_hard, end_hard;
+ char sysfs_path[PATH_MAX];
+ char name[4096];
+ char humanname[4096];
+ int index;
+ int rindex;
+public:
+
+ rfkill(char *_name, char *path);
+
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+ virtual double utilization(void); /* percentage */
+
+ virtual const char * class_name(void) { return "radio";};
+
+ virtual const char * device_name(void);
+ virtual const char * human_name(void) { return humanname; };
+ virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
+ virtual int power_valid(void) { return utilization_power_valid(rindex);};
+ virtual int grouping_prio(void) { return 5; };
+};
+
+extern void create_all_rfkills(void);
+
+
+#endif \ No newline at end of file
diff --git a/src/devices/runtime_pm.cpp b/src/devices/runtime_pm.cpp
new file mode 100644
index 0000000..26f9d32
--- /dev/null
+++ b/src/devices/runtime_pm.cpp
@@ -0,0 +1,257 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include "runtime_pm.h"
+
+#include <string.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <limits.h>
+
+#include "../parameters/parameters.h"
+#include "../lib.h"
+
+#include <iostream>
+#include <fstream>
+
+runtime_pmdevice::runtime_pmdevice(const char *_name, const char *path) : device()
+{
+ pt_strcpy(sysfs_path, path);
+ register_sysfs_path(sysfs_path);
+ pt_strcpy(name, _name);
+ snprintf(humanname, sizeof(humanname), "runtime-%s", _name);
+
+ index = get_param_index(humanname);
+ r_index = get_result_index(humanname);
+
+ before_suspended_time = 0;
+ before_active_time = 0;
+ after_suspended_time = 0;
+ after_active_time = 0;
+
+ register_parameter(humanname);
+}
+
+void runtime_pmdevice::start_measurement(void)
+{
+ char filename[PATH_MAX];
+ ifstream file;
+
+ before_suspended_time = 0;
+ before_active_time = 0;
+ after_suspended_time = 0;
+ after_active_time = 0;
+
+ snprintf(filename, sizeof(filename), "%s/power/runtime_suspended_time", sysfs_path);
+ file.open(filename, ios::in);
+ if (!file)
+ return;
+ file >> before_suspended_time;
+ file.close();
+
+ snprintf(filename, sizeof(filename), "%s/power/runtime_active_time", sysfs_path);
+ file.open(filename, ios::in);
+ if (!file)
+ return;
+ file >> before_active_time;
+ file.close();
+}
+
+void runtime_pmdevice::end_measurement(void)
+{
+ char filename[PATH_MAX];
+ ifstream file;
+
+ snprintf(filename, sizeof(filename), "%s/power/runtime_suspended_time", sysfs_path);
+ file.open(filename, ios::in);
+ if (!file)
+ return;
+ file >> after_suspended_time;
+ file.close();
+
+ snprintf(filename, sizeof(filename), "%s/power/runtime_active_time", sysfs_path);
+ file.open(filename, ios::in);
+ if (!file)
+ return;
+ file >> after_active_time;
+ file.close();
+}
+
+double runtime_pmdevice::utilization(void) /* percentage */
+{
+ double d;
+ d = 100 * (after_active_time - before_active_time) / (0.0001 + after_active_time - before_active_time + after_suspended_time - before_suspended_time);
+
+ if (d < 0.00)
+ d = 0.0;
+ if (d > 99.9)
+ d = 100.0;
+ return d;
+}
+
+const char * runtime_pmdevice::device_name(void)
+{
+ return name;
+}
+
+const char * runtime_pmdevice::human_name(void)
+{
+ return humanname;
+}
+
+
+double runtime_pmdevice::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ double power;
+ double factor;
+ double util;
+
+ power = 0;
+
+ factor = get_parameter_value(index, bundle);
+ util = get_result_value(r_index, result);
+ power += util * factor / 100.0;
+
+ return power;
+}
+
+void runtime_pmdevice::set_human_name(char *_name)
+{
+ pt_strcpy(humanname, _name);
+}
+
+
+int device_has_runtime_pm(const char *sysfs_path)
+{
+ char filename[PATH_MAX];
+ ifstream file;
+ unsigned long value;
+
+ snprintf(filename, sizeof(filename), "%s/power/runtime_suspended_time", sysfs_path);
+ file.open(filename, ios::in);
+ if (!file)
+ return 0;
+ file >> value;
+ file.close();
+ if (value)
+ return 1;
+
+ snprintf(filename, sizeof(filename), "%s/power/runtime_active_time", sysfs_path);
+ file.open(filename, ios::in);
+ if (!file)
+ return 0;
+ file >> value;
+ file.close();
+ if (value)
+ return 1;
+
+ return 0;
+}
+
+static void do_bus(const char *bus)
+{
+ /* /sys/bus/pci/devices/0000\:00\:1f.0/power/runtime_suspended_time */
+
+ struct dirent *entry;
+ DIR *dir;
+ char filename[PATH_MAX];
+
+ snprintf(filename, sizeof(filename), "/sys/bus/%s/devices/", bus);
+ dir = opendir(filename);
+ if (!dir)
+ return;
+ while (1) {
+ ifstream file;
+ class runtime_pmdevice *dev;
+ entry = readdir(dir);
+
+ if (!entry)
+ break;
+ if (entry->d_name[0] == '.')
+ continue;
+
+ snprintf(filename, sizeof(filename), "/sys/bus/%s/devices/%s", bus, entry->d_name);
+ dev = new class runtime_pmdevice(entry->d_name, filename);
+
+ if (strcmp(bus, "i2c") == 0) {
+ string devname;
+ char dev_name[4096];
+ bool is_adapter = false;
+
+ snprintf(filename, sizeof(filename), "/sys/bus/%s/devices/%s/new_device", bus, entry->d_name);
+ if (access(filename, W_OK) == 0)
+ is_adapter = true;
+
+ snprintf(filename, sizeof(filename), "/sys/bus/%s/devices/%s/name", bus, entry->d_name);
+ file.open(filename, ios::in);
+ if (file) {
+ getline(file, devname);
+ file.close();
+ }
+
+ snprintf(dev_name, sizeof(dev_name), _("I2C %s (%s): %s"), (is_adapter ? _("Adapter") : _("Device")), entry->d_name, devname.c_str());
+ dev->set_human_name(dev_name);
+ }
+
+ if (strcmp(bus, "pci") == 0) {
+ uint16_t vendor = 0, device = 0;
+
+ snprintf(filename, sizeof(filename), "/sys/bus/%s/devices/%s/vendor", bus, entry->d_name);
+
+ file.open(filename, ios::in);
+ if (file) {
+ file >> hex >> vendor;
+ file.close();
+ }
+
+
+ snprintf(filename, sizeof(filename), "/sys/bus/%s/devices/%s/device", bus, entry->d_name);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> hex >> device;
+ file.close();
+ }
+
+ if (vendor && device) {
+ char devname[4096];
+ snprintf(devname, sizeof(devname), _("PCI Device: %s"),
+ pci_id_to_name(vendor, device, filename, 4095));
+ dev->set_human_name(devname);
+ }
+ }
+ all_devices.push_back(dev);
+ }
+ closedir(dir);
+}
+
+void create_all_runtime_pm_devices(void)
+{
+ do_bus("pci");
+ do_bus("spi");
+ do_bus("platform");
+ do_bus("i2c");
+}
diff --git a/src/devices/runtime_pm.h b/src/devices/runtime_pm.h
new file mode 100644
index 0000000..77bf398
--- /dev/null
+++ b/src/devices/runtime_pm.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_RUNTIMEPM_H
+#define _INCLUDE_GUARD_RUNTIMEPM_H
+
+#include <limits.h>
+
+#include "device.h"
+#include "../parameters/parameters.h"
+
+class runtime_pmdevice: public device {
+ uint64_t before_suspended_time, before_active_time;
+ uint64_t after_suspended_time, after_active_time;
+ char sysfs_path[PATH_MAX];
+ char name[4096];
+ char humanname[4096];
+ int index;
+ int r_index;
+public:
+
+ runtime_pmdevice(const char *_name, const char *path);
+
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+ virtual double utilization(void); /* percentage */
+
+ virtual const char * class_name(void) { return "runtime_pm";};
+
+ virtual const char * device_name(void);
+ virtual const char * human_name(void);
+ virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
+ virtual int power_valid(void) { return utilization_power_valid(r_index);};
+
+ void set_human_name(char *name);
+ virtual int grouping_prio(void) { return 1; };
+};
+
+extern void create_all_runtime_pm_devices(void);
+
+extern int device_has_runtime_pm(const char *sysfs_path);
+
+
+#endif \ No newline at end of file
diff --git a/src/devices/thinkpad-fan.cpp b/src/devices/thinkpad-fan.cpp
new file mode 100644
index 0000000..8e2ce53
--- /dev/null
+++ b/src/devices/thinkpad-fan.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <iostream>
+#include <fstream>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <math.h>
+#include <unistd.h>
+#include <limits.h>
+
+#include "../lib.h"
+
+
+#include "device.h"
+#include "thinkpad-fan.h"
+#include "../parameters/parameters.h"
+#include "../process/powerconsumer.h"
+
+#include <string.h>
+#include <unistd.h>
+
+thinkpad_fan::thinkpad_fan(): device()
+{
+ start_rate = 0;
+ end_rate = 0;
+ fan_index = get_param_index("thinkpad-fan");
+ fansqr_index = get_param_index("thinkpad-fan-sqr");
+ fancub_index = get_param_index("thinkpad-fan-cub");
+ r_index = get_result_index("thinkpad-fan");
+ register_sysfs_path("/sys/devices/platform/thinkpad_hwmon");
+}
+
+void thinkpad_fan::start_measurement(void)
+{
+ /* read the rpms of the fan */
+ start_rate = read_sysfs("/sys/devices/platform/thinkpad_hwmon/fan1_input");
+}
+
+void thinkpad_fan::end_measurement(void)
+{
+ end_rate = read_sysfs("/sys/devices/platform/thinkpad_hwmon/fan1_input");
+
+ report_utilization("thinkpad-fan", utilization());
+}
+
+
+double thinkpad_fan::utilization(void)
+{
+ return (start_rate+end_rate) / 2;
+}
+
+void create_thinkpad_fan(void)
+{
+ char filename[PATH_MAX];
+ class thinkpad_fan *fan;
+
+ pt_strcpy(filename, "/sys/devices/platform/thinkpad_hwmon/fan1_input");
+
+ if (access(filename, R_OK) !=0)
+ return;
+
+ register_parameter("thinkpad-fan", 10);
+ register_parameter("thinkpad-fan-sqr", 5);
+ register_parameter("thinkpad-fan-cub", 10);
+
+ fan = new class thinkpad_fan();
+ all_devices.push_back(fan);
+}
+
+
+
+double thinkpad_fan::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ double power;
+ double factor;
+ double util;
+
+
+ power = 0;
+ util = get_result_value(r_index, result);
+
+ if (util < 0)
+ util = 0;
+
+
+ /* physics dictact that fan power goes cubic with the rpms, but there's also a linear component for friction*/
+ factor = get_parameter_value(fancub_index, bundle);
+ power += factor * pow(util / 3600.0, 3);
+
+ factor = get_parameter_value(fansqr_index, bundle) - 5.0;
+ power += factor * pow(util / 3600.0, 2);
+
+ factor = get_parameter_value(fan_index, bundle) - 10.0;
+ power += util / 5000.0 * factor;
+
+ if (power <= 0.0)
+ power = 0.0;
+
+ return power;
+}
diff --git a/src/devices/thinkpad-fan.h b/src/devices/thinkpad-fan.h
new file mode 100644
index 0000000..34c4c43
--- /dev/null
+++ b/src/devices/thinkpad-fan.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_THINKPAD_FAN_H
+#define _INCLUDE_GUARD_THINKPAD_FAN_H
+
+
+#include "device.h"
+#include "../parameters/parameters.h"
+
+class thinkpad_fan: public device {
+ double start_rate, end_rate;
+ int fan_index, fansqr_index, fancub_index;
+ int r_index;
+public:
+
+ thinkpad_fan();
+
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+ virtual double utilization(void); /* percentage */
+
+ virtual const char * class_name(void) { return "fan";};
+
+ virtual const char * device_name(void) { return "Fan-1";};
+ virtual const char * human_name(void) { return "Laptop fan";};
+ virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
+ virtual const char * util_units(void) { return " rpm"; };
+ virtual int power_valid(void) { return utilization_power_valid(r_index);};
+ virtual int grouping_prio(void) { return 1; };
+};
+
+extern void create_thinkpad_fan(void);
+
+
+#endif \ No newline at end of file
diff --git a/src/devices/thinkpad-light.cpp b/src/devices/thinkpad-light.cpp
new file mode 100644
index 0000000..d047ab3
--- /dev/null
+++ b/src/devices/thinkpad-light.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <iostream>
+#include <fstream>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <math.h>
+#include <unistd.h>
+#include <limits.h>
+
+#include "../lib.h"
+
+
+#include "device.h"
+#include "thinkpad-light.h"
+#include "../parameters/parameters.h"
+#include "../process/powerconsumer.h"
+
+#include <string.h>
+#include <unistd.h>
+
+thinkpad_light::thinkpad_light(): device()
+{
+ start_rate = 0;
+ end_rate = 0;
+ light_index = get_param_index("thinkpad-light");
+ r_index = get_result_index("thinkpad-light");
+ register_sysfs_path("/sys/devices/platform/thinkpad_acpi/leds/tpacpi::thinklight");
+}
+
+void thinkpad_light::start_measurement(void)
+{
+ /* read the rpms of the light */
+ start_rate = read_sysfs("/sys/devices/platform/thinkpad_acpi/leds/tpacpi::thinklight/brightness");
+}
+
+void thinkpad_light::end_measurement(void)
+{
+ end_rate = read_sysfs("/sys/devices/platform/thinkpad_acpi/leds/tpacpi::thinklight/brightness");
+
+ report_utilization("thinkpad-light", utilization());
+}
+
+
+double thinkpad_light::utilization(void)
+{
+ return (start_rate+end_rate) / 2.55 / 2.0;
+}
+
+void create_thinkpad_light(void)
+{
+ char filename[PATH_MAX];
+ class thinkpad_light *light;
+
+ pt_strcpy(filename, "/sys/devices/platform/thinkpad_acpi/leds/tpacpi::thinklight/brightness");
+
+ if (access(filename, R_OK) !=0)
+ return;
+
+ register_parameter("thinkpad-light", 10);
+
+ light = new class thinkpad_light();
+ all_devices.push_back(light);
+}
+
+
+
+double thinkpad_light::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ double power;
+ double factor;
+ double util;
+
+
+ power = 0;
+ util = get_result_value(r_index, result);
+
+ if (util < 0)
+ util = 0;
+
+
+ factor = get_parameter_value(light_index, bundle) - 10.0;
+ power += util / 100.0 * factor;
+
+ if (power <= 0.0)
+ power = 0.0;
+
+ return power;
+}
diff --git a/src/devices/thinkpad-light.h b/src/devices/thinkpad-light.h
new file mode 100644
index 0000000..64a1789
--- /dev/null
+++ b/src/devices/thinkpad-light.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_THINKPAD_LIGHT_H
+#define _INCLUDE_GUARD_THINKPAD_LIGHT_H
+
+
+#include "device.h"
+#include "../parameters/parameters.h"
+
+class thinkpad_light: public device {
+ double start_rate, end_rate;
+ int light_index;
+ int r_index;
+public:
+
+ thinkpad_light();
+
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+ virtual double utilization(void); /* percentage */
+
+ virtual const char * class_name(void) { return "light";};
+
+ virtual const char * device_name(void) { return "Light-1";};
+ virtual const char * human_name(void) { return "Thinkpad light";};
+ virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
+ virtual const char * util_units(void) { return "%"; };
+ virtual int power_valid(void) { return utilization_power_valid(r_index);};
+ virtual int grouping_prio(void) { return 1; };
+};
+
+extern void create_thinkpad_light(void);
+
+
+#endif \ No newline at end of file
diff --git a/src/devices/usb.cpp b/src/devices/usb.cpp
new file mode 100644
index 0000000..5042699
--- /dev/null
+++ b/src/devices/usb.cpp
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include "usb.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <limits.h>
+
+#include "../lib.h"
+#include "../devlist.h"
+#include "../parameters/parameters.h"
+
+#include <iostream>
+#include <fstream>
+
+usbdevice::usbdevice(const char *_name, const char *path, const char *devid): device()
+{
+ ifstream file;
+ char filename[PATH_MAX];
+ char vendor[4096];
+ char product[4096];
+
+ pt_strcpy(sysfs_path, path);
+ register_sysfs_path(sysfs_path);
+ pt_strcpy(name, _name);
+ pt_strcpy(devname, devid);
+ snprintf(humanname, sizeof(humanname), _("USB device: %s"), pretty_print(devid, vendor, 4096));
+ active_before = 0;
+ active_after = 0;
+ connected_before = 0;
+ connected_after = 0;
+ busnum = 0;
+ devnum = 0;
+
+ index = get_param_index(devname);
+ r_index = get_result_index(name);
+ rootport = 0;
+ cached_valid = 0;
+
+
+ /* root ports and hubs should count as 0 power ... their activity is derived */
+ snprintf(filename, sizeof(filename), "%s/bDeviceClass", path);
+ file.open(filename, ios::in);
+ if (file) {
+ int dclass = 0;
+
+ file >> dclass;
+ file.close();
+ if (dclass == 9)
+ rootport = 1;
+ };
+
+ vendor[0] = 0;
+ product[0] = 0;
+ snprintf(filename, sizeof(filename), "%s/manufacturer", path);
+ file.open(filename, ios::in);
+ if (file) {
+ file.getline(vendor, 2047);
+ if (strstr(vendor, "Linux "))
+ vendor[0] = 0;
+ file.close();
+ };
+ snprintf(filename, sizeof(filename), "%s/product", path);
+ file.open(filename, ios::in);
+ if (file) {
+ file.getline(product, 2040);
+ file.close();
+ };
+ if (strlen(vendor) && strlen(product))
+ snprintf(humanname, sizeof(humanname), _("USB device: %s (%s)"), product, vendor);
+ else if (strlen(product))
+ snprintf(humanname, sizeof(humanname), _("USB device: %s"), product);
+ else if (strlen(vendor))
+ snprintf(humanname, sizeof(humanname), _("USB device: %s"), vendor);
+
+ /* For usbdevfs we need bus number and device number */
+ snprintf(filename, sizeof(filename), "%s/busnum", path);
+ file.open(filename, ios::in);
+ if (file) {
+
+ file >> busnum;
+ file.close();
+ };
+ snprintf(filename, sizeof(filename), "%s/devnum", path);
+ file.open(filename, ios::in);
+ if (file) {
+
+ file >> devnum;
+ file.close();
+ };
+}
+
+
+
+void usbdevice::start_measurement(void)
+{
+ ifstream file;
+ char fullpath[PATH_MAX];
+
+ active_before = 0;
+ active_after = 0;
+ connected_before = 0;
+ connected_after = 0;
+
+ snprintf(fullpath, sizeof(fullpath), "%s/power/active_duration", sysfs_path);
+ file.open(fullpath, ios::in);
+ if (file) {
+ file >> active_before;
+ }
+ file.close();
+
+ snprintf(fullpath, sizeof(fullpath), "%s/power/connected_duration", sysfs_path);
+ file.open(fullpath, ios::in);
+ if (file) {
+ file >> connected_before;
+ }
+ file.close();
+}
+
+void usbdevice::end_measurement(void)
+{
+ ifstream file;
+ char fullpath[PATH_MAX];
+
+ snprintf(fullpath, sizeof(fullpath), "%s/power/active_duration", sysfs_path);
+ file.open(fullpath, ios::in);
+ if (file) {
+ file >> active_after;
+ }
+ file.close();
+
+ snprintf(fullpath, sizeof(fullpath), "%s/power/connected_duration", sysfs_path);
+ file.open(fullpath, ios::in);
+ if (file) {
+ file >> connected_after;
+ }
+ file.close();
+ report_utilization(name, utilization());
+
+}
+
+double usbdevice::utilization(void) /* percentage */
+{
+ double d;
+ d = 100.0 * (active_after - active_before) / (0.01 + connected_after - connected_before);
+ if (d < 0.0)
+ d = 0.0;
+ if (d > 99.8)
+ d = 100.0;
+ return d;
+}
+
+const char * usbdevice::device_name(void)
+{
+ return name;
+}
+
+const char * usbdevice::human_name(void)
+{
+ return humanname;
+}
+
+void usbdevice::register_power_with_devlist(struct result_bundle *results, struct parameter_bundle *bundle)
+{
+ char devfs_name[1024];
+
+ snprintf(devfs_name, sizeof(devfs_name), "usb/%03d/%03d", busnum,
+ devnum);
+
+ register_devpower(devfs_name, power_usage(results, bundle), this);
+}
+
+double usbdevice::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ double power;
+ double factor;
+ double util;
+
+ if (rootport || !cached_valid)
+ return 0.0;
+
+
+ power = 0;
+ factor = get_parameter_value(index, bundle);
+ util = get_result_value(r_index, result);
+
+ power += util * factor / 100.0;
+
+ return power;
+}
+
+static void create_all_usb_devices_callback(const char *d_name)
+{
+ char filename[PATH_MAX];
+ ifstream file;
+ class usbdevice *usb;
+ char device_name[PATH_MAX];
+ char vendorid[64], devid[64];
+ char devid_name[4096];
+
+ snprintf(filename, sizeof(filename), "/sys/bus/usb/devices/%s", d_name);
+ snprintf(device_name, sizeof(device_name), "%s/power/active_duration", filename);
+ if (access(device_name, R_OK) != 0)
+ return;
+
+ snprintf(device_name, sizeof(device_name), "%s/idVendor", filename);
+ file.open(device_name, ios::in);
+ if (file)
+ file.getline(vendorid, 64);
+ file.close();
+ snprintf(device_name, sizeof(device_name), "%s/idProduct", filename);
+ file.open(device_name, ios::in);
+ if (file)
+ file.getline(devid, 64);
+ file.close();
+
+ snprintf(devid_name, sizeof(devid_name), "usb-device-%s-%s", vendorid, devid);
+ snprintf(device_name, sizeof(device_name), "usb-device-%s-%s-%s", d_name, vendorid, devid);
+ if (result_device_exists(device_name))
+ return;
+
+ usb = new class usbdevice(device_name, filename, devid_name);
+ all_devices.push_back(usb);
+ register_parameter(devid_name, 0.1);
+}
+
+void create_all_usb_devices(void)
+{
+ process_directory("/sys/bus/usb/devices/", create_all_usb_devices_callback);
+}
diff --git a/src/devices/usb.h b/src/devices/usb.h
new file mode 100644
index 0000000..7e76a55
--- /dev/null
+++ b/src/devices/usb.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_USB_H
+#define _INCLUDE_GUARD_USB_H
+
+#include <limits.h>
+
+#include "device.h"
+#include "../parameters/parameters.h"
+
+class usbdevice: public device {
+ int active_before, active_after;
+ int connected_before, connected_after;
+ char sysfs_path[PATH_MAX];
+ char name[4096];
+ char devname[4096];
+ char humanname[4096];
+ int index;
+ int r_index;
+ int rootport;
+ int busnum;
+ int devnum;
+public:
+
+ usbdevice(const char *_name, const char *path, const char *devid);
+
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+ virtual double utilization(void); /* percentage */
+
+ virtual const char * class_name(void) { return "usb";};
+
+ virtual const char * device_name(void);
+ virtual const char * human_name(void);
+ virtual void register_power_with_devlist(struct result_bundle *results, struct parameter_bundle *bundle);
+ virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
+ virtual int power_valid(void) { return utilization_power_valid(r_index);};
+ virtual int grouping_prio(void) { return 4; };
+};
+
+extern void create_all_usb_devices(void);
+
+
+#endif \ No newline at end of file
diff --git a/src/devlist.cpp b/src/devlist.cpp
new file mode 100644
index 0000000..70ae70e
--- /dev/null
+++ b/src/devlist.cpp
@@ -0,0 +1,351 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+
+/*
+ * Code to track centrally which process has what /dev files open
+ */
+#include <iostream>
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <vector>
+#include <algorithm>
+#include <unistd.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
+
+using namespace std;
+
+#include "devlist.h"
+#include "lib.h"
+#include "report/report.h"
+#include "report/report-maker.h"
+#include "report/report-data-html.h"
+
+#include "process/process.h"
+#include "devices/device.h"
+/*
+
+* collect list of processes that have devices open
+ (alternate between before and after lists)
+
+* charge a "surcharge" to a device (sub)string
+ - count how many openers
+ - add proprotion to each process that has it open
+
+* list of devices + power they use for processing
+
+*/
+
+static vector<struct devuser *> one;
+static vector<struct devuser *> two;
+static vector<struct devpower *> devpower;
+
+static int phase;
+/*
+ * 0 - one = before, two = after
+ * 1 - one = after, two = before
+ */
+
+void clean_open_devices()
+{
+ unsigned int i=0;
+
+ for (i = 0; i < one.size(); i++) {
+ free(one[i]);
+ }
+
+ for (i = 0; i < two.size(); i++) {
+ free(two[i]);
+ }
+
+ for (i = 0; i < devpower.size(); i++){
+ free(devpower[i]);
+ }
+}
+
+void collect_open_devices(void)
+{
+ struct dirent *entry;
+ DIR *dir;
+ char filename[PATH_MAX];
+ char link[PATH_MAX];
+ unsigned int i;
+ vector<struct devuser *> *target;
+
+ if (phase == 1)
+ target = &one;
+ else
+ target = &two;
+
+ for (i = 0; i < target->size(); i++) {
+ free((*target)[i]);
+ }
+ target->resize(0);
+
+
+ dir = opendir("/proc/");
+ if (!dir)
+ return;
+ while (1) {
+ struct dirent *entry2;
+ DIR *dir2;
+ entry = readdir(dir);
+
+ if (!entry)
+ break;
+ if (entry->d_name[0] == '.')
+ continue;
+ if (strcmp(entry->d_name, "self") == 0)
+ continue;
+
+ snprintf(filename, sizeof(filename), "/proc/%s/fd/", entry->d_name);
+
+ dir2 = opendir(filename);
+ if (!dir2)
+ continue;
+ while (1) {
+ int ret;
+ struct devuser * dev;
+ entry2 = readdir(dir2);
+ if (!entry2)
+ break;
+ if (!isdigit(entry2->d_name[0]))
+ continue;
+ snprintf(filename, sizeof(filename), "/proc/%s/fd/%s", entry->d_name, entry2->d_name);
+ memset(link, 0, sizeof(link));
+ ret = readlink(filename, link, sizeof(link) - 1);
+ if (ret < 0)
+ continue;
+
+ if (strcmp(link, "/dev/null") == 0)
+ continue;
+ if (strcmp(link, "/dev/.udev/queue.bin") == 0)
+ continue;
+ if (strcmp(link, "/dev/initctl") == 0)
+ continue;
+ if (strcmp(link, "/dev/ptmx") == 0)
+ continue;
+ if (strstr(link, "/dev/pts/"))
+ continue;
+ if (strstr(link, "/dev/shm/"))
+ continue;
+ if (strstr(link, "/dev/urandom"))
+ continue;
+ if (strstr(link, "/dev/tty"))
+ continue;
+
+ if (strncmp(link, "/dev", 4)==0) {
+ dev = (struct devuser *)malloc(sizeof(struct devuser));
+ if (!dev)
+ continue;
+ dev->pid = strtoull(entry->d_name, NULL, 10);
+ strncpy(dev->device, link, 251);
+ dev->device[251] = '\0';
+ strncpy(dev->comm, read_sysfs_string("/proc/%s/comm", entry->d_name).c_str(), 31);
+ dev->comm[31] = '\0';
+ target->push_back(dev);
+
+ }
+ }
+ closedir(dir2);
+ }
+ closedir(dir);
+
+ if (phase)
+ phase = 0;
+ else
+ phase = 1;
+}
+
+
+/* returns 0 if no process is identified as having the device open and a value > 0 otherwise */
+int charge_device_to_openers(const char *devstring, double power, class device *_dev)
+{
+ unsigned int i;
+ int openers = 0;
+ class process *proc;
+ /* 1. count the number of openers */
+
+ for (i = 0; i < one.size(); i++) {
+ if (strstr(one[i]->device, devstring))
+ openers++;
+ }
+ for (i = 0; i < two.size(); i++) {
+ if (strstr(two[i]->device, devstring))
+ openers++;
+ }
+
+
+ /* 2. divide power by this number */
+
+ if (!openers)
+ return 0;
+ power = power / openers;
+
+
+ /* 3. for each process that has it open, add the charge */
+
+ for (i = 0; i < one.size(); i++)
+ if (strstr(one[i]->device, devstring)) {
+ proc = find_create_process(one[i]->comm, one[i]->pid);
+ if (proc) {
+ proc->power_charge += power;
+ if (strlen(_dev->guilty) < 2000 && strstr(_dev->guilty, one[i]->comm) == NULL) {
+ strcat(_dev->guilty, one[i]->comm);
+ strcat(_dev->guilty, " ");
+ }
+ }
+ }
+
+ for (i = 0; i < two.size(); i++)
+ if (strstr(two[i]->device, devstring)) {
+ proc = find_create_process(two[i]->comm, two[i]->pid);
+ if (proc) {
+ proc->power_charge += power;
+ if (strlen(_dev->guilty) < 2000 && strstr(_dev->guilty, two[i]->comm) == NULL) {
+ strcat(_dev->guilty, two[i]->comm);
+ strcat(_dev->guilty, " ");
+ }
+ }
+ }
+
+
+
+ return openers;
+}
+
+void clear_devpower(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < devpower.size(); i++) {
+ devpower[i]->power = 0.0;
+ devpower[i]->dev->guilty[0] = 0;
+ }
+}
+
+void register_devpower(const char *devstring, double power, class device *_dev)
+{
+ unsigned int i;
+ struct devpower *dev = NULL;
+
+ for (i = 0; i < devpower.size(); i++)
+ if (strcmp(devstring, devpower[i]->device) == 0) {
+ dev = devpower[i];
+ }
+
+ if (!dev) {
+ dev = (struct devpower *)malloc(sizeof (struct devpower));
+ pt_strcpy(dev->device, devstring);
+ dev->power = 0.0;
+ devpower.push_back(dev);
+ }
+ dev->dev = _dev;
+ dev->power = power;
+}
+
+void run_devpower_list(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < devpower.size(); i++) {
+ int ret;
+ ret = charge_device_to_openers(devpower[i]->device, devpower[i]->power, devpower[i]->dev);
+ if (ret)
+ devpower[i]->dev->hide = true;
+ else
+ devpower[i]->dev->hide = false;
+
+ }
+
+}
+
+static bool devlist_sort(struct devuser * i, struct devuser * j)
+{
+ if (i->pid != j->pid)
+ return i->pid < j->pid;
+
+ return (strcmp(i->device, j->device)< 0);
+}
+
+void report_show_open_devices(void)
+{
+ vector<struct devuser *> *target;
+ unsigned int i;
+ char prev[128], proc[128];
+ int idx, cols, rows;
+
+ prev[0] = 0;
+ if (phase == 1)
+ target = &one;
+ else
+ target = &two;
+
+ if (target->size() == 0)
+ return;
+
+
+ /* Set Table attributes, rows, and cols */
+ table_attributes std_table_css;
+ cols = 2;
+ idx = cols;
+ rows= target->size() + 1;
+ init_std_table_attr(&std_table_css, rows, cols);
+
+ /* Set Title attributes */
+ tag_attr title_attr;
+ init_title_attr(&title_attr);
+
+ /* Set array of data in row Major order */
+ string *process_data = new string[cols * rows];
+
+ sort(target->begin(), target->end(), devlist_sort);
+ process_data[0]=__("Process");
+ process_data[1]=__("Device");
+
+ for (i = 0; i < target->size(); i++) {
+ proc[0] = 0;
+ if (strcmp(prev, (*target)[i]->comm) != 0)
+ snprintf(proc, sizeof(proc), "%s", (*target)[i]->comm);
+
+ process_data[idx]=string(proc);
+ idx+=1;
+ process_data[idx]=string((*target)[i]->device);
+ idx+=1;
+ snprintf(prev, sizeof(prev), "%s", (*target)[i]->comm);
+ }
+
+ /* Report Output */
+ /* No div attribute here inherits from device power report */
+ report.add_title(&title_attr, __("Process Device Activity"));
+ report.add_table(process_data, &std_table_css);
+ delete [] process_data;
+ report.end_div();
+}
diff --git a/src/devlist.h b/src/devlist.h
new file mode 100644
index 0000000..35dfd6c
--- /dev/null
+++ b/src/devlist.h
@@ -0,0 +1,27 @@
+#ifndef __INCLUDE_GUARD_DEVLIST_H__
+#define __INCLUDE_GUARD_DEVLIST_H__
+
+struct devuser {
+ unsigned int pid;
+ char comm[32];
+ char device[252];
+};
+
+class device;
+
+struct devpower {
+ char device[252];
+ double power;
+ class device *dev;
+};
+
+extern void clean_open_devices();
+extern void collect_open_devices(void);
+
+extern void clear_devpower(void);
+extern void register_devpower(const char *devstring, double power, class device *dev);
+extern void run_devpower_list(void);
+
+extern void report_show_open_devices(void);
+
+#endif
diff --git a/src/display.cpp b/src/display.cpp
new file mode 100644
index 0000000..cc03919
--- /dev/null
+++ b/src/display.cpp
@@ -0,0 +1,342 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include "display.h"
+#include "lib.h"
+
+#include <ncurses.h>
+
+
+#include <vector>
+#include <map>
+#include <string>
+#include <string.h>
+
+using namespace std;
+
+static int display = 0;
+
+vector<string> tab_names;
+map<string, class tab_window *> tab_windows;
+map<string, string> tab_translations;
+
+map<string, string> bottom_lines;
+
+void create_tab(const string &name, const string &translation, class tab_window *w, string bottom_line)
+{
+ if (!w)
+ w = new(class tab_window);
+
+ w->win = newpad(1000,1000);
+ tab_names.push_back(name);
+ tab_windows[name] = w;
+ tab_translations[name] = translation;
+ bottom_lines[name] = bottom_line;
+}
+
+
+void init_display(void)
+{
+ initscr();
+ start_color();
+
+ cbreak(); /* character at a time input */
+ noecho(); /* don't show the user input */
+ keypad(stdscr, TRUE); /* enable cursor/etc keys */
+
+ use_default_colors();
+
+ create_tab("Overview", _("Overview"));
+ create_tab("Idle stats", _("Idle stats"));
+ create_tab("Frequency stats", _("Frequency stats"));
+ create_tab("Device stats", _("Device stats"));
+
+ display = 1;
+}
+
+void reset_display(void)
+{
+ if (!display)
+ return;
+
+ keypad(stdscr, FALSE);
+ echo();
+ nocbreak();
+
+ resetterm();
+}
+
+
+WINDOW *tab_bar = NULL;
+WINDOW *bottom_line = NULL;
+
+static int current_tab;
+
+void show_tab(unsigned int tab)
+{
+ class tab_window *win;
+ unsigned int i;
+ int tab_pos = 17;
+ const char *c;
+
+ if (!display)
+ return;
+
+ if (tab_bar) {
+ delwin(tab_bar);
+ tab_bar = NULL;
+ }
+
+ if (bottom_line) {
+ delwin(bottom_line);
+ bottom_line = NULL;
+ }
+
+ tab_bar = newwin(1, 0, 0, 0);
+
+ wattrset(tab_bar, A_REVERSE);
+ mvwprintw(tab_bar, 0,0, "%120s", "");
+ mvwprintw(tab_bar, 0,0, "PowerTOP %s", PACKAGE_VERSION);
+
+ bottom_line = newwin(1, 0, LINES-1, 0);
+ wattrset(bottom_line, A_REVERSE);
+ mvwprintw(bottom_line, 0,0, "%120s", "");
+
+ c = bottom_lines[tab_names[tab]].c_str();
+ if (c && strlen(c) > 0)
+ mvwprintw(bottom_line, 0,0, "%s", c);
+ else
+ mvwprintw(bottom_line, 0, 0,
+ "<ESC> %s | <TAB> / <Shift + TAB> %s | ", _("Exit"),
+ _("Navigate"));
+
+
+ current_tab = tab;
+
+ for (i = 0; i < tab_names.size(); i++) {
+ if (i == tab)
+ wattrset(tab_bar, A_NORMAL);
+ else
+ wattrset(tab_bar, A_REVERSE);
+ mvwprintw(tab_bar, 0, tab_pos, " %s ", tab_translations[tab_names[i]].c_str());
+
+ tab_pos += 3 + tab_names[i].length();
+ }
+
+ wrefresh(tab_bar);
+ wrefresh(bottom_line);
+
+ win = tab_windows[tab_names[tab]];
+ if (!win)
+ return;
+
+ prefresh(win->win, win->ypad_pos, win->xpad_pos, 1, 0, LINES - 3, COLS - 1);
+}
+
+WINDOW *get_ncurses_win(const char *name)
+{
+ class tab_window *w;
+ WINDOW *win;
+
+ w= tab_windows[name];
+ if (!w)
+ return NULL;
+
+ win = w->win;
+
+ return win;
+}
+
+WINDOW *get_ncurses_win(int nr)
+{
+ class tab_window *w;
+ WINDOW *win;
+
+ w= tab_windows[tab_names[nr]];
+ if (!w)
+ return NULL;
+
+ win = w->win;
+
+ return win;
+}
+
+WINDOW *get_ncurses_win(const string &name)
+{
+ return get_ncurses_win(name.c_str());
+}
+
+void show_prev_tab(void)
+{
+ class tab_window *w;
+
+ if (!display)
+ return;
+ w = tab_windows[tab_names[current_tab]];
+ if (w)
+ w->hide();
+
+ current_tab --;
+ if (current_tab < 0)
+ current_tab = tab_names.size() - 1;
+
+ w = tab_windows[tab_names[current_tab]];
+ if (w)
+ w->expose();
+
+ show_tab(current_tab);
+}
+
+void show_next_tab(void)
+{
+ class tab_window *w;
+
+ if (!display)
+ return;
+
+ w = tab_windows[tab_names[current_tab]];
+ if (w)
+ w->hide();
+
+ current_tab ++;
+ if (current_tab >= (int)tab_names.size())
+ current_tab = 0;
+
+ w = tab_windows[tab_names[current_tab]];
+ if (w)
+ w->expose();
+
+ show_tab(current_tab);
+}
+
+void show_cur_tab(void)
+{
+ if (!display)
+ return;
+ show_tab(current_tab);
+}
+
+void cursor_down(void)
+{
+ class tab_window *w;
+
+ w = tab_windows[tab_names[current_tab]];
+ if (w) {
+ if (w->ypad_pos < 1000) {
+ if (tab_names[current_tab] == "Tunables" || tab_names[current_tab] == "WakeUp") {
+ if ((w->cursor_pos + 7) >= LINES) {
+ prefresh(w->win, ++w->ypad_pos, w->xpad_pos,
+ 1, 0, LINES - 3, COLS - 1);
+ }
+ w->cursor_down();
+ } else {
+ prefresh(w->win, ++w->ypad_pos, w->xpad_pos,
+ 1, 0, LINES - 3, COLS - 1);
+ }
+ }
+ }
+
+ show_cur_tab();
+}
+
+void cursor_up(void)
+{
+ class tab_window *w;
+
+ w = tab_windows[tab_names[current_tab]];
+
+ if (w) {
+ w->cursor_up();
+ if(w->ypad_pos > 0) {
+ prefresh(w->win, --w->ypad_pos, w->xpad_pos,
+ 1, 0, LINES - 3, COLS - 1);
+ }
+ }
+
+ show_cur_tab();
+}
+
+void cursor_left(void)
+{
+ class tab_window *w;
+
+ w = tab_windows[tab_names[current_tab]];
+
+ if (w) {
+ if (w->xpad_pos > 0) {
+ prefresh(w->win, w->ypad_pos,--w->xpad_pos,
+ 1, 0, LINES - 3, COLS - 1);
+ }
+ }
+}
+
+void cursor_right(void)
+{
+ class tab_window *w;
+
+ w = tab_windows[tab_names[current_tab]];
+
+ if (w) {
+ if (w->xpad_pos < 1000) {
+ prefresh(w->win, w->ypad_pos, ++w->xpad_pos,
+ 1, 0, LINES - 3, COLS - 1);
+ }
+ }
+}
+
+void cursor_enter(void)
+{
+ class tab_window *w;
+
+ w = tab_windows[tab_names[current_tab]];
+
+ if (w) {
+ w->cursor_enter();
+ w->repaint();
+ }
+ show_cur_tab();
+}
+
+void window_refresh()
+{
+ class tab_window *w;
+
+ w = tab_windows[tab_names[current_tab]];
+
+ if (w) {
+ w->ypad_pos = 0;
+ w->xpad_pos = 0;
+ w->window_refresh();
+ w->repaint();
+ }
+
+ show_cur_tab();
+}
+
+int ncurses_initialized(void)
+{
+ if (display)
+ return 1;
+ return 0;
+}
diff --git a/src/display.h b/src/display.h
new file mode 100644
index 0000000..9db87ec
--- /dev/null
+++ b/src/display.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef __INCLUDE_GUARD_DISPLAY_H_
+#define __INCLUDE_GUARD_DISPLAY_H_
+
+
+#include <map>
+#include <string>
+#include <ncurses.h>
+
+using namespace std;
+
+extern void init_display(void);
+extern void reset_display(void);
+extern int ncurses_initialized(void);
+extern void show_tab(unsigned int tab);
+extern void show_next_tab(void);
+extern void show_prev_tab(void);
+extern void show_cur_tab(void);
+extern void cursor_up(void);
+extern void cursor_down(void);
+extern void cursor_right(void);
+extern void cursor_left(void);
+extern void cursor_enter(void);
+extern void window_refresh(void);
+
+class tab_window {
+public:
+ int cursor_pos;
+ int cursor_max;
+ short int xpad_pos, ypad_pos;
+ WINDOW *win;
+
+ tab_window() {
+ cursor_pos = 0;
+ cursor_max = 0;
+ xpad_pos =0;
+ ypad_pos = 0;
+ win = NULL;
+ }
+
+ virtual void cursor_down(void) {
+ if (cursor_pos < cursor_max)
+ cursor_pos++;
+ repaint();
+ } ;
+ virtual void cursor_up(void) {
+ if (cursor_pos > 0)
+ cursor_pos--;
+ repaint();
+ };
+ virtual void cursor_left(void) { };
+ virtual void cursor_right(void) { };
+
+ virtual void cursor_enter(void) { };
+ virtual void window_refresh() { };
+
+ virtual void repaint(void) { };
+ virtual void expose(void) { cursor_pos = 0; repaint();};
+ virtual void hide(void) { };
+
+ virtual ~tab_window()
+ {
+ delwin(win);
+ win = NULL;
+ }
+};
+
+extern map<string, class tab_window *> tab_windows;
+
+WINDOW *get_ncurses_win(const char *name);
+WINDOW *get_ncurses_win(const string &name);
+WINDOW *get_ncurses_win(int nr);
+
+void create_tab(const string &name, const string &translation, class tab_window *w = NULL, string bottom_line = "");
+
+#endif
diff --git a/src/lib.cpp b/src/lib.cpp
new file mode 100644
index 0000000..5cd1c4a
--- /dev/null
+++ b/src/lib.cpp
@@ -0,0 +1,597 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ * Peter Anvin
+ */
+#include <map>
+#include <string.h>
+#include <iostream>
+#include <utility>
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <ctype.h>
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#include "lib.h"
+
+#ifndef HAVE_NO_PCI
+extern "C" {
+#include <pci/pci.h>
+}
+#endif
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <locale.h>
+#include <libintl.h>
+#include <limits>
+#include <math.h>
+#include <ncurses.h>
+#include <fcntl.h>
+#include <glob.h>
+
+static int kallsyms_read = 0;
+
+int is_turbo(uint64_t freq, uint64_t max, uint64_t maxmo)
+{
+ if (freq != max)
+ return 0;
+ if (maxmo + 1000 != max)
+ return 0;
+ return 1;
+}
+
+double percentage(double F)
+{
+ F = F * 100.0;
+// if (F > 100.0)
+// F = 100.0;
+ if (F < 0.0)
+ F = 0.0;
+ return F;
+}
+
+char *hz_to_human(unsigned long hz, char *buffer, int digits)
+{
+ unsigned long long Hz;
+
+ buffer[0] = 0;
+
+ Hz = hz;
+
+ /* default: just put the Number in */
+ sprintf(buffer,"%9lli", Hz);
+
+ if (Hz>1000) {
+ if (digits == 2)
+ sprintf(buffer, "%4lli MHz", (Hz+500)/1000);
+ else
+ sprintf(buffer, "%6lli MHz", (Hz+500)/1000);
+ }
+
+ if (Hz>1500000) {
+ if (digits == 2)
+ sprintf(buffer, "%4.2f GHz", (Hz+5000.0)/1000000);
+ else
+ sprintf(buffer, "%3.1f GHz", (Hz+5000.0)/1000000);
+ }
+
+ return buffer;
+}
+
+using namespace std;
+
+map<unsigned long, string> kallsyms;
+
+static void read_kallsyms(void)
+{
+ ifstream file;
+ char line[1024];
+ kallsyms_read = 1;
+
+ file.open("/proc/kallsyms", ios::in);
+
+ while (file) {
+ char *c = NULL, *c2 = NULL;
+ unsigned long address = 0;
+ memset(line, 0, 1024);
+ file.getline(line, 1024);
+ c = strchr(line, ' ');
+ if (!c)
+ continue;
+ *c = 0;
+ c2 = c + 1;
+ if (*c2) c2++;
+ if (*c2) c2++;
+
+ address = strtoull(line, NULL, 16);
+ c = strchr(c2, '\t');
+ if (c)
+ *c = 0;
+ if (address != 0)
+ kallsyms[address] = c2;
+ }
+ file.close();
+}
+
+const char *kernel_function(uint64_t address)
+{
+ const char *c;
+ if (!kallsyms_read)
+ read_kallsyms();
+
+ c = kallsyms[address].c_str();
+ if (!c)
+ return "";
+ return c;
+}
+
+static int _max_cpu;
+int get_max_cpu(void)
+{
+ return _max_cpu;
+}
+
+void set_max_cpu(int cpu)
+{
+ if (cpu > _max_cpu)
+ _max_cpu = cpu;
+}
+
+
+void write_sysfs(const string &filename, const string &value)
+{
+ ofstream file;
+
+ file.open(filename.c_str(), ios::out);
+ if (!file)
+ return;
+ try
+ {
+ file << value;
+ file.close();
+ } catch (std::exception &exc) {
+ return;
+ }
+}
+
+int read_sysfs(const string &filename, bool *ok)
+{
+ ifstream file;
+ int i;
+
+ file.open(filename.c_str(), ios::in);
+ if (!file) {
+ if (ok)
+ *ok = false;
+ return 0;
+ }
+ try
+ {
+ file >> i;
+ if (ok)
+ *ok = true;
+ } catch (std::exception &exc) {
+ if (ok)
+ *ok = false;
+ i = 0;
+ }
+ file.close();
+ return i;
+}
+
+string read_sysfs_string(const string &filename)
+{
+ ifstream file;
+ char content[4096];
+ char *c;
+
+ file.open(filename.c_str(), ios::in);
+ if (!file)
+ return "";
+ try
+ {
+ file.getline(content, 4096);
+ file.close();
+ c = strchr(content, '\n');
+ if (c)
+ *c = 0;
+ } catch (std::exception &exc) {
+ file.close();
+ return "";
+ }
+ return content;
+}
+
+string read_sysfs_string(const char *format, const char *param)
+{
+ ifstream file;
+ char content[4096];
+ char *c;
+ char filename[PATH_MAX];
+
+
+ snprintf(filename, sizeof(filename), format, param);
+
+ file.open(filename, ios::in);
+ if (!file)
+ return "";
+ try
+ {
+ file.getline(content, 4096);
+ file.close();
+ c = strchr(content, '\n');
+ if (c)
+ *c = 0;
+ } catch (std::exception &exc) {
+ file.close();
+ return "";
+ }
+ return content;
+}
+
+void align_string(char *buffer, size_t min_sz, size_t max_sz)
+{
+ size_t sz;
+
+ /** mbsrtowcs() allows NULL dst and zero sz,
+ * comparing to mbstowcs(), which causes undefined
+ * behaviour under given circumstances*/
+
+ /* start with mbsrtowcs() local mbstate_t * and
+ * NULL dst pointer*/
+ sz = mbsrtowcs(NULL, (const char **)&buffer, max_sz, NULL);
+ if (sz == (size_t)-1) {
+ buffer[min_sz] = 0x00;
+ return;
+ }
+ while (sz < min_sz) {
+ strcat(buffer, " ");
+ sz++;
+ }
+}
+
+void format_watts(double W, char *buffer, unsigned int len)
+{
+ buffer[0] = 0;
+ char buf[32];
+ sprintf(buffer, _("%7sW"), fmt_prefix(W, buf));
+
+ if (W < 0.0001)
+ sprintf(buffer, _(" 0 mW"));
+
+ align_string(buffer, len, len);
+}
+
+#ifndef HAVE_NO_PCI
+static struct pci_access *pci_access;
+
+char *pci_id_to_name(uint16_t vendor, uint16_t device, char *buffer, int len)
+{
+ char *ret;
+
+ buffer[0] = 0;
+
+ if (!pci_access) {
+ pci_access = pci_alloc();
+ pci_init(pci_access);
+ }
+
+ ret = pci_lookup_name(pci_access, buffer, len, PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE, vendor, device);
+
+ return ret;
+}
+
+void end_pci_access(void)
+{
+ if (pci_access)
+ pci_free_name_list(pci_access);
+}
+
+#else
+
+char *pci_id_to_name(uint16_t vendor, uint16_t device, char *buffer, int len)
+{
+ return NULL;
+}
+
+void end_pci_access(void)
+{
+}
+
+#endif /* HAVE_NO_PCI */
+
+int utf_ok = -1;
+
+
+
+/* pretty print numbers while limiting the precision */
+char *fmt_prefix(double n, char *buf)
+{
+ static const char prefixes[] = "yzafpnum kMGTPEZY";
+ char tmpbuf[16];
+ int omag, npfx;
+ char *p, *q, pfx, *c;
+ int i;
+
+ if (utf_ok == -1) {
+ char *g;
+ g = getenv("LANG");
+ if (g && strstr(g, "UTF-8"))
+ utf_ok = 1;
+ else
+ utf_ok = 0;
+ }
+
+ p = buf;
+
+ *p = ' ';
+ if (n < 0.0) {
+ *p = '-';
+ n = -n;
+ p++;
+ }
+
+ snprintf(tmpbuf, sizeof tmpbuf, "%.2e", n);
+ c = strchr(tmpbuf, 'e');
+ if (!c) {
+ sprintf(buf, "NaN");
+ return buf;
+ }
+ omag = atoi(c + 1);
+
+ npfx = ((omag + 27) / 3) - (27/3);
+ omag = (omag + 27) % 3;
+
+ q = tmpbuf;
+ if (omag == 2)
+ omag = -1;
+
+ for (i = 0; i < 3; i++) {
+ while (!isdigit(*q))
+ q++;
+ *p++ = *q++;
+ if (i == omag)
+ *p++ = '.';
+ }
+ *p++ = ' ';
+
+ pfx = prefixes[npfx + 8];
+
+ if (pfx == ' ') {
+ /* do nothing */
+ } else if (pfx == 'u' && utf_ok > 0) {
+ strcpy(p, "µ"); /* Mu is a multibyte sequence */
+ while (*p)
+ p++;
+ } else {
+ *p++ = pfx;
+ }
+ *p = '\0';
+
+ return buf;
+}
+
+static map<string, string> pretty_prints;
+static int pretty_print_init = 0;
+
+static void init_pretty_print(void)
+{
+ pretty_prints["[12] i8042"] = _("PS/2 Touchpad / Keyboard / Mouse");
+ pretty_prints["ahci"] = _("SATA controller");
+ pretty_prints["usb-device-8087-0020"] = _("Intel built in USB hub");
+
+ pretty_print_init = 1;
+}
+
+
+char *pretty_print(const char *str, char *buf, int len)
+{
+ const char *p;
+
+ if (!pretty_print_init)
+ init_pretty_print();
+
+ p = pretty_prints[str].c_str();
+
+ if (strlen(p) == 0)
+ p = str;
+
+ snprintf(buf, len, "%s", p);
+
+ if (len)
+ buf[len - 1] = 0;
+ return buf;
+}
+
+int equals(double a, double b)
+{
+ return fabs(a - b) <= std::numeric_limits<double>::epsilon();
+}
+
+void process_directory(const char *d_name, callback fn)
+{
+ struct dirent *entry;
+ DIR *dir;
+ dir = opendir(d_name);
+ if (!dir)
+ return;
+ while (1) {
+ entry = readdir(dir);
+ if (!entry)
+ break;
+ if (entry->d_name[0] == '.')
+ continue;
+ fn(entry->d_name);
+ }
+ closedir(dir);
+}
+
+void process_glob(const char *d_glob, callback fn)
+{
+ glob_t g;
+ size_t c;
+
+ switch (glob(d_glob, GLOB_ERR | GLOB_MARK | GLOB_NOSORT, NULL, &g)) {
+ case GLOB_NOSPACE:
+ fprintf(stderr,_("glob returned GLOB_NOSPACE\n"));
+ globfree(&g);
+ return;
+ case GLOB_ABORTED:
+ fprintf(stderr,_("glob returned GLOB_ABORTED\n"));
+ globfree(&g);
+ return;
+ case GLOB_NOMATCH:
+ fprintf(stderr,_("glob returned GLOB_NOMATCH\n"));
+ globfree(&g);
+ return;
+ }
+
+ for (c=0; c < g.gl_pathc; c++) {
+ fn(g.gl_pathv[c]);
+ }
+ globfree(&g);
+}
+
+int get_user_input(char *buf, unsigned sz)
+{
+ fflush(stdout);
+ echo();
+ /* Upon successful completion, these functions return OK. Otherwise, they return ERR. */
+ int ret = getnstr(buf, sz);
+ noecho();
+ fflush(stdout);
+ /* to distinguish between getnstr error and empty line */
+ return ret || strlen(buf);
+}
+
+int read_msr(int cpu, uint64_t offset, uint64_t *value)
+{
+#if defined(__i386__) || defined(__x86_64__)
+ ssize_t retval;
+ uint64_t msr;
+ int fd;
+ char msr_path[256];
+
+ snprintf(msr_path, sizeof(msr_path), "/dev/cpu/%d/msr", cpu);
+
+ if (access(msr_path, R_OK) != 0){
+ snprintf(msr_path, sizeof(msr_path), "/dev/msr%d", cpu);
+
+ if (access(msr_path, R_OK) != 0){
+ fprintf(stderr,
+ _("Model-specific registers (MSR)\
+ not found (try enabling CONFIG_X86_MSR).\n"));
+ return -1;
+ }
+ }
+
+ fd = open(msr_path, O_RDONLY);
+ if (fd < 0)
+ return -1;
+ retval = pread(fd, &msr, sizeof msr, offset);
+ close(fd);
+ if (retval != sizeof msr) {
+ return -1;
+ }
+ *value = msr;
+
+ return retval;
+#else
+ return -1;
+#endif
+}
+
+int write_msr(int cpu, uint64_t offset, uint64_t value)
+{
+#if defined(__i386__) || defined(__x86_64__)
+ ssize_t retval;
+ int fd;
+ char msr_path[256];
+
+ snprintf(msr_path, sizeof(msr_path), "/dev/cpu/%d/msr", cpu);
+
+ if (access(msr_path, R_OK) != 0){
+ snprintf(msr_path, sizeof(msr_path), "/dev/msr%d", cpu);
+
+ if (access(msr_path, R_OK) != 0){
+ fprintf(stderr,
+ _("Model-specific registers (MSR)\
+ not found (try enabling CONFIG_X86_MSR).\n"));
+ return -1;
+ }
+ }
+
+ fd = open(msr_path, O_WRONLY);
+ if (fd < 0)
+ return -1;
+ retval = pwrite(fd, &value, sizeof value, offset);
+ close(fd);
+ if (retval != sizeof value) {
+ return -1;
+ }
+
+ return retval;
+#else
+ return -1;
+#endif
+}
+
+#define UI_NOTIFY_BUFF_SZ 2048
+
+void ui_notify_user_ncurses(const char *frmt, ...)
+{
+ char notify[UI_NOTIFY_BUFF_SZ];
+ va_list list;
+
+ start_color();
+ init_pair(1, COLOR_BLACK, COLOR_WHITE);
+ attron(COLOR_PAIR(1));
+ va_start(list, frmt);
+ /* there is no ncurses *print() function which takes
+ * int x, int y and va_list, this is why we use temp
+ * buffer */
+ vsnprintf(notify, UI_NOTIFY_BUFF_SZ - 1, frmt, list);
+ va_end(list);
+ mvprintw(1, 0, "%s", notify);
+ attroff(COLOR_PAIR(1));
+}
+
+void ui_notify_user_console(const char *frmt, ...)
+{
+ va_list list;
+
+ va_start(list, frmt);
+ vprintf(frmt, list);
+ va_end(list);
+}
diff --git a/src/lib.h b/src/lib.h
new file mode 100644
index 0000000..6d85eb6
--- /dev/null
+++ b/src/lib.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef INCLUDE_GUARD_LIB_H
+#define INCLUDE_GUARD_LIB_H
+
+#include <libintl.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <cstring>
+
+/* Include only for Automake builds */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef ENABLE_NLS
+#define _(STRING) gettext(STRING)
+#else
+#define _(STRING) (STRING)
+#endif
+
+extern int is_turbo(uint64_t freq, uint64_t max, uint64_t maxmo);
+
+extern int get_max_cpu(void);
+extern void set_max_cpu(int cpu);
+
+extern double percentage(double F);
+extern char *hz_to_human(unsigned long hz, char *buffer, int digits = 2);
+
+
+extern const char *kernel_function(uint64_t address);
+
+
+
+#include <ctime>
+#include <string>
+using namespace std;
+
+extern void write_sysfs(const string &filename, const string &value);
+extern int read_sysfs(const string &filename, bool *ok = NULL);
+extern string read_sysfs_string(const string &filename);
+extern string read_sysfs_string(const char *format, const char *param);
+
+extern void format_watts(double W, char *buffer, unsigned int len);
+
+extern char *pci_id_to_name(uint16_t vendor, uint16_t device, char *buffer, int len);
+extern void end_pci_access(void);
+
+
+extern char *fmt_prefix(double n, char *buf);
+extern char *pretty_print(const char *str, char *buf, int len);
+extern int equals(double a, double b);
+
+template<size_t N> void pt_strcpy(char (&d)[N], const char *s)
+{
+ strncpy(d, s, N);
+ d[N-1] = '\0';
+}
+
+typedef void (*callback)(const char*);
+extern void process_directory(const char *d_name, callback fn);
+extern void process_glob(const char *glob, callback fn);
+extern int utf_ok;
+extern int get_user_input(char *buf, unsigned sz);
+extern int read_msr(int cpu, uint64_t offset, uint64_t *value);
+extern int write_msr(int cpu, uint64_t offset, uint64_t value);
+
+extern void align_string(char *buffer, size_t min_sz, size_t max_sz);
+
+extern void ui_notify_user_ncurses(const char *frmt, ...);
+extern void ui_notify_user_console(const char *frmt, ...);
+extern void (*ui_notify_user) (const char *frmt, ...);
+#endif
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..45aaa58
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,578 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * getopt code is taken from "The GNU C Library" reference manual,
+ * section 24.2 "Parsing program options using getopt"
+ * http://www.gnu.org/s/libc/manual/html_node/Getopt-Long-Option-Example.html
+ * Manual published under the terms of the Free Documentation License.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <iostream>
+#include <fstream>
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <locale.h>
+#include <sys/resource.h>
+#include <limits.h>
+#include <pthread.h>
+
+#include "cpu/cpu.h"
+#include "process/process.h"
+#include "perf/perf.h"
+#include "perf/perf_bundle.h"
+#include "lib.h"
+#include "../config.h"
+
+
+#include "devices/device.h"
+#include "devices/devfreq.h"
+#include "devices/usb.h"
+#include "devices/ahci.h"
+#include "measurement/measurement.h"
+#include "parameters/parameters.h"
+#include "calibrate/calibrate.h"
+
+
+#include "tuning/tuning.h"
+#include "wakeup/wakeup.h"
+
+#include "display.h"
+#include "devlist.h"
+#include "report/report.h"
+
+#define DEBUGFS_MAGIC 0x64626720
+
+#define NR_OPEN_DEF 1024 * 1024
+
+int debug_learning = 0;
+unsigned time_out = 20;
+int leave_powertop = 0;
+void (*ui_notify_user) (const char *frmt, ...);
+
+enum {
+ OPT_AUTO_TUNE = CHAR_MAX + 1,
+ OPT_EXTECH,
+ OPT_DEBUG
+};
+
+static const struct option long_options[] =
+{
+ /* These options set a flag. */
+ {"auto-tune", no_argument, NULL, OPT_AUTO_TUNE},
+ {"calibrate", no_argument, NULL, 'c'},
+ {"csv", optional_argument, NULL, 'C'},
+ {"debug", no_argument, &debug_learning, OPT_DEBUG},
+ {"extech", optional_argument, NULL, OPT_EXTECH},
+ {"html", optional_argument, NULL, 'r'},
+ {"iteration", optional_argument, NULL, 'i'},
+ {"quiet", no_argument, NULL, 'q'},
+ {"sample", optional_argument, NULL, 's'},
+ {"time", optional_argument, NULL, 't'},
+ {"workload", optional_argument, NULL, 'w'},
+ {"version", no_argument, NULL, 'V'},
+ {"help", no_argument, NULL, 'h'},
+ {NULL, 0, NULL, 0}
+};
+
+static void print_version()
+{
+ printf(_("PowerTOP version " PACKAGE_VERSION "\n"));
+}
+
+static bool set_refresh_timeout()
+{
+ static char buf[4];
+ mvprintw(1, 0, "%s (currently %u): ", _("Set refresh time out"), time_out);
+ memset(buf, '\0', sizeof(buf));
+ get_user_input(buf, sizeof(buf) - 1);
+ show_tab(0);
+ unsigned time = strtoul(buf, NULL, 0);
+ if (!time) return 0;
+ if (time > 32) time = 32;
+ time_out = time;
+ return 1;
+}
+
+static void print_usage()
+{
+ printf("%s\n\n", _("Usage: powertop [OPTIONS]"));
+ printf(" --auto-tune\t %s\n", _("sets all tunable options to their GOOD setting"));
+ printf(" -c, --calibrate\t %s\n", _("runs powertop in calibration mode"));
+ printf(" -C, --csv%s\t %s\n", _("[=filename]"), _("generate a csv report"));
+ printf(" --debug\t\t %s\n", _("run in \"debug\" mode"));
+ printf(" --extech%s\t %s\n", _("[=devnode]"), _("uses an Extech Power Analyzer for measurements"));
+ printf(" -r, --html%s\t %s\n", _("[=filename]"), _("generate a html report"));
+ printf(" -i, --iteration%s\n", _("[=iterations] number of times to run each test"));
+ printf(" -q, --quiet\t\t %s\n", _("suppress stderr output"));
+ printf(" -s, --sample%s\t %s\n", _("[=seconds]"), _("interval for power consumption measurement"));
+ printf(" -t, --time%s\t %s\n", _("[=seconds]"), _("generate a report for 'x' seconds"));
+ printf(" -w, --workload%s %s\n", _("[=workload]"), _("file to execute for workload"));
+ printf(" -V, --version\t\t %s\n", _("print version information"));
+ printf(" -h, --help\t\t %s\n", _("print this help menu"));
+ printf("\n");
+ printf("%s\n\n", _("For more help please refer to the 'man 8 powertop'"));
+}
+
+static void do_sleep(int seconds)
+{
+ time_t target;
+ int delta;
+
+ if (!ncurses_initialized()) {
+ sleep(seconds);
+ return;
+ }
+ target = time(NULL) + seconds;
+ delta = seconds;
+ do {
+ int c;
+ usleep(6000);
+ halfdelay(delta * 10);
+
+ c = getch();
+ switch (c) {
+ case KEY_BTAB:
+ show_prev_tab();
+ break;
+ case '\t':
+ show_next_tab();
+ break;
+ case KEY_RIGHT:
+ cursor_right();
+ break;
+ case KEY_LEFT:
+ cursor_left();
+ break;
+ case KEY_NPAGE:
+ case KEY_DOWN:
+ cursor_down();
+ break;
+ case KEY_PPAGE:
+ case KEY_UP:
+ cursor_up();
+ break;
+ case ' ':
+ case '\n':
+ cursor_enter();
+ break;
+ case 's':
+ if (set_refresh_timeout())
+ return;
+ break;
+ case 'r':
+ window_refresh();
+ return;
+ case KEY_EXIT:
+ case 'q':
+ case 27: // Escape
+ leave_powertop = 1;
+ return;
+ }
+
+ delta = target - time(NULL);
+ if (delta <= 0)
+ break;
+
+ } while (1);
+}
+
+extern "C" {
+ static volatile bool end_thread;
+ void* measure_background_thread(void *arg)
+ {
+ int sleep_time = *((int *) arg);
+ while (!end_thread) {
+ do_sleep(sleep_time);
+ global_sample_power();
+ }
+ return 0;
+ }
+}
+
+void one_measurement(int seconds, int sample_interval, char *workload)
+{
+ create_all_usb_devices();
+ start_power_measurement();
+ devices_start_measurement();
+ start_devfreq_measurement();
+ start_process_measurement();
+ start_cpu_measurement();
+
+ if (workload && workload[0]) {
+ pthread_t thread = 0UL;
+ end_thread = false;
+ if (pthread_create(&thread, NULL, measure_background_thread, &sample_interval))
+ fprintf(stderr, "ERROR: workload measurement thread creation failed\n");
+
+ if (system(workload))
+ fprintf(stderr, _("Unknown issue running workload!\n"));
+
+ if (thread)
+ {
+ end_thread = true;
+ pthread_join( thread, NULL);
+ }
+ global_sample_power();
+ } else {
+ while (seconds > 0)
+ {
+ do_sleep(sample_interval > seconds ? seconds : sample_interval);
+ seconds -= sample_interval;
+ global_sample_power();
+ }
+ }
+ end_cpu_measurement();
+ end_process_measurement();
+ collect_open_devices();
+ end_devfreq_measurement();
+ devices_end_measurement();
+ end_power_measurement();
+
+ process_cpu_data();
+ process_process_data();
+
+ /* output stats */
+ process_update_display();
+ report_summary();
+ w_display_cpu_cstates();
+ w_display_cpu_pstates();
+ if (reporttype != REPORT_OFF) {
+ report_display_cpu_cstates();
+ report_display_cpu_pstates();
+ }
+ report_process_update_display();
+ tuning_update_display();
+ wakeup_update_display();
+ end_process_data();
+
+ global_power();
+ compute_bundle();
+
+ show_report_devices();
+ report_show_open_devices();
+
+ report_devices();
+ display_devfreq_devices();
+ report_devfreq_devices();
+ ahci_create_device_stats_table();
+ store_results(measurement_time);
+ end_cpu_data();
+}
+
+void out_of_memory()
+{
+ reset_display();
+ printf("%s...\n",_("PowerTOP is out of memory. PowerTOP is Aborting"));
+ abort();
+}
+
+void make_report(int time, char *workload, int iterations, int sample_interval, char *file)
+{
+
+ /* one to warm up everything */
+ fprintf(stderr, _("Preparing to take measurements\n"));
+ utf_ok = 0;
+ one_measurement(1, sample_interval, NULL);
+
+ if (!workload[0])
+ fprintf(stderr, _("Taking %d measurement(s) for a duration of %d second(s) each.\n"),iterations,time);
+ else
+ fprintf(stderr, _("Measuring workload %s.\n"), workload);
+ for (int i=0; i != iterations; i++){
+ init_report_output(file, iterations);
+ initialize_tuning();
+ initialize_wakeup();
+ /* and then the real measurement */
+ one_measurement(time, sample_interval, workload);
+ report_show_tunables();
+ report_show_wakeup();
+ finish_report_output();
+ clear_tuning();
+ }
+ /* and wrap up */
+ learn_parameters(50, 0);
+ save_all_results("saved_results.powertop");
+ save_parameters("saved_parameters.powertop");
+ end_pci_access();
+ exit(0);
+}
+
+static void checkroot() {
+ int uid;
+ uid = getuid();
+
+ if (uid != 0) {
+ printf(_("PowerTOP " PACKAGE_VERSION " must be run with root privileges.\n"));
+ printf(_("exiting...\n"));
+ exit(EXIT_FAILURE);
+ }
+
+}
+
+static int get_nr_open(void) {
+ int nr_open = NR_OPEN_DEF;
+ ifstream file;
+
+ file.open("/proc/sys/fs/nr_open", ios::in);
+ if (file) {
+ file >> nr_open;
+ file.close();
+ }
+ return nr_open;
+}
+
+static void powertop_init(int auto_tune)
+{
+ static char initialized = 0;
+ int ret;
+ struct statfs st_fs;
+ struct rlimit rlmt;
+
+ if (initialized)
+ return;
+
+ checkroot();
+
+ rlmt.rlim_cur = rlmt.rlim_max = get_nr_open();
+ setrlimit (RLIMIT_NOFILE, &rlmt);
+
+ if (system("/sbin/modprobe cpufreq_stats > /dev/null 2>&1"))
+ fprintf(stderr, _("modprobe cpufreq_stats failed\n"));
+#if defined(__i386__) || defined(__x86_64__)
+ if (system("/sbin/modprobe msr > /dev/null 2>&1"))
+ fprintf(stderr, _("modprobe msr failed\n"));
+#endif
+ statfs("/sys/kernel/debug", &st_fs);
+
+ if (st_fs.f_type != (long) DEBUGFS_MAGIC) {
+ if (access("/bin/mount", X_OK) == 0) {
+ ret = system("/bin/mount -t debugfs debugfs /sys/kernel/debug > /dev/null 2>&1");
+ } else {
+ ret = system("mount -t debugfs debugfs /sys/kernel/debug > /dev/null 2>&1");
+ }
+ if (ret != 0) {
+ if (!auto_tune) {
+ fprintf(stderr, _("Failed to mount debugfs!\n"));
+ fprintf(stderr, _("exiting...\n"));
+ exit(EXIT_FAILURE);
+ } else {
+ fprintf(stderr, _("Failed to mount debugfs!\n"));
+ fprintf(stderr, _("Should still be able to auto tune...\n"));
+ }
+ }
+ }
+
+ srand(time(NULL));
+
+ if (access("/var/cache/", W_OK) == 0)
+ mkdir("/var/cache/powertop", 0600);
+ else
+ mkdir("/data/local/powertop", 0600);
+
+ load_results("saved_results.powertop");
+ load_parameters("saved_parameters.powertop");
+
+ enumerate_cpus();
+ create_all_devices();
+ create_all_devfreq_devices();
+ detect_power_meters();
+
+ register_parameter("base power", 100, 0.5);
+ register_parameter("cpu-wakeups", 39.5);
+ register_parameter("cpu-consumption", 1.56);
+ register_parameter("gpu-operations", 0.5576);
+ register_parameter("disk-operations-hard", 0.2);
+ register_parameter("disk-operations", 0.0);
+ register_parameter("xwakes", 0.1);
+
+ load_parameters("saved_parameters.powertop");
+
+ initialized = 1;
+}
+
+void clean_shutdown()
+{
+ close_results();
+ clean_open_devices();
+ clear_all_devices();
+ clear_all_devfreq();
+ clear_all_cpus();
+
+ return;
+}
+
+
+int main(int argc, char **argv)
+{
+ int option_index;
+ int c;
+ char filename[PATH_MAX];
+ char workload[PATH_MAX] = {0};
+ int iterations = 1, auto_tune = 0, sample_interval = 5;
+
+ set_new_handler(out_of_memory);
+
+ setlocale (LC_ALL, "");
+
+#ifdef ENABLE_NLS
+ bindtextdomain (PACKAGE, LOCALEDIR);
+ textdomain (PACKAGE);
+#endif
+ ui_notify_user = ui_notify_user_ncurses;
+ while (1) { /* parse commandline options */
+ c = getopt_long(argc, argv, "cC::r::i:qt:w:Vh", long_options, &option_index);
+ /* Detect the end of the options. */
+ if (c == -1)
+ break;
+ switch (c) {
+ case OPT_AUTO_TUNE:
+ auto_tune = 1;
+ leave_powertop = 1;
+ ui_notify_user = ui_notify_user_console;
+ break;
+ case 'c':
+ powertop_init(0);
+ calibrate();
+ break;
+ case 'C': /* csv report */
+ reporttype = REPORT_CSV;
+ snprintf(filename, sizeof(filename), "%s", optarg ? optarg : "powertop.csv");
+ if (!strlen(filename))
+ {
+ fprintf(stderr, _("Invalid CSV filename\n"));
+ exit(1);
+ }
+ break;
+ case OPT_DEBUG:
+ /* implemented using getopt_long(3) flag */
+ break;
+ case OPT_EXTECH: /* Extech power analyzer support */
+ checkroot();
+ extech_power_meter(optarg ? optarg : "/dev/ttyUSB0");
+ break;
+ case 'r': /* html report */
+ reporttype = REPORT_HTML;
+ snprintf(filename, sizeof(filename), "%s", optarg ? optarg : "powertop.html");
+ if (!strlen(filename))
+ {
+ fprintf(stderr, _("Invalid HTML filename\n"));
+ exit(1);
+ }
+ break;
+ case 'i':
+ iterations = (optarg ? atoi(optarg) : 1);
+ break;
+ case 'q':
+ if (freopen("/dev/null", "a", stderr))
+ fprintf(stderr, _("Quiet mode failed!\n"));
+ break;
+ case 's':
+ sample_interval = (optarg ? atoi(optarg) : 5);
+ break;
+ case 't':
+ time_out = (optarg ? atoi(optarg) : 20);
+ break;
+ case 'w': /* measure workload */
+ snprintf(workload, sizeof(workload), "%s", optarg ? optarg : "");
+ break;
+ case 'V':
+ print_version();
+ exit(0);
+ break;
+ case 'h':
+ print_usage();
+ exit(0);
+ break;
+ case '?': /* Unknown option */
+ /* getopt_long already printed an error message. */
+ exit(1);
+ break;
+ }
+ }
+
+ powertop_init(auto_tune);
+
+ if (reporttype != REPORT_OFF)
+ make_report(time_out, workload, iterations, sample_interval, filename);
+
+ if (debug_learning)
+ printf("Learning debugging enabled\n");
+
+ learn_parameters(250, 0);
+ save_parameters("saved_parameters.powertop");
+
+
+ if (debug_learning) {
+ learn_parameters(1000, 1);
+ dump_parameter_bundle();
+ end_pci_access();
+ exit(0);
+ }
+ if (!auto_tune)
+ init_display();
+
+ initialize_devfreq();
+ initialize_tuning();
+ initialize_wakeup();
+ /* first one is short to not let the user wait too long */
+ one_measurement(1, sample_interval, NULL);
+
+ if (!auto_tune) {
+ tuning_update_display();
+ show_tab(0);
+ } else {
+ auto_toggle_tuning();
+ }
+
+ while (!leave_powertop) {
+ if (!auto_tune)
+ show_cur_tab();
+ one_measurement(time_out, sample_interval, NULL);
+ learn_parameters(15, 0);
+ }
+ if (!auto_tune)
+ endwin();
+ fprintf(stderr, "%s\n", _("Leaving PowerTOP"));
+
+ end_process_data();
+ clear_process_data();
+ end_cpu_data();
+ clear_cpu_data();
+
+ save_all_results("saved_results.powertop");
+ save_parameters("saved_parameters.powertop");
+ learn_parameters(500, 0);
+ save_parameters("saved_parameters.powertop");
+ end_pci_access();
+ clear_tuning();
+ reset_display();
+
+ clean_shutdown();
+
+ return 0;
+}
diff --git a/src/measurement/acpi.cpp b/src/measurement/acpi.cpp
new file mode 100644
index 0000000..572852c
--- /dev/null
+++ b/src/measurement/acpi.cpp
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include "measurement.h"
+#include "acpi.h"
+#include <iostream>
+#include <fstream>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include "../lib.h"
+
+using namespace std;
+
+acpi_power_meter::acpi_power_meter(const char *acpi_name)
+{
+ rate = 0.0;
+ capacity = 0.0;
+ voltage = 0.0;
+ pt_strcpy(battery_name, acpi_name);
+}
+
+/*
+present: yes
+capacity state: ok
+charging state: discharging
+present rate: 8580 mW
+remaining capacity: 34110 mWh
+present voltage: 12001 mV
+*/
+
+void acpi_power_meter::measure(void)
+{
+ char filename[PATH_MAX];
+ char line[4096];
+ ifstream file;
+
+ double _rate = 0;
+ double _capacity = 0;
+ double _voltage = 0;
+
+ char rate_units[16];
+ char capacity_units[16];
+ char voltage_units[16];
+
+ rate_units[0] = 0;
+ capacity_units[0] = 0;
+ voltage_units[0] = 0;
+
+ rate = 0;
+ voltage = 0;
+ capacity = 0;
+
+ snprintf(filename, sizeof(filename), "/proc/acpi/battery/%s/state", battery_name);
+
+ file.open(filename, ios::in);
+ if (!file)
+ return;
+
+ while (file) {
+ char *c;
+ file.getline(line, sizeof(line));
+
+ if (strstr(line, "present:") && (strstr(line, "yes") == NULL)) {
+ return;
+ }
+ if (strstr(line, "charging state:") && (strstr(line, "discharging") == NULL)) {
+ return; /* not discharging */
+ }
+ if (strstr(line, "present rate:")) {
+ c = strchr(line, ':');
+ c++;
+ while (*c == ' ') c++;
+ _rate = strtoull(c, NULL, 10);
+ c = strchr(c, ' ');
+ if (c) {
+ c++;
+ pt_strcpy(rate_units, c);
+ } else {
+ _rate = 0;
+ strcpy(rate_units, "Unknown");
+ }
+
+ }
+ if (strstr(line, "remaining capacity:")) {
+ c = strchr(line, ':');
+ c++;
+ while (*c == ' ') c++;
+ _capacity = strtoull(c, NULL, 10);
+ c = strchr(c, ' ');
+ if (c) {
+ c++;
+ pt_strcpy(capacity_units, c);
+ } else {
+ _capacity = 0;
+ strcpy(capacity_units, "Unknown");
+ }
+ }
+ if (strstr(line, "present voltage:")) {
+ c = strchr(line, ':');
+ c++;
+ while (*c == ' ') c++;
+ _voltage = strtoull(c, NULL, 10);
+ c = strchr(c, ' ');
+ if (c) {
+ c++;
+ pt_strcpy(voltage_units, c);
+ } else {
+ _voltage = 0;
+ strcpy(voltage_units, "Unknown");
+ }
+ }
+ }
+ file.close();
+
+ /* BIOS report random crack-inspired units. Lets try to get to the Si-system units */
+
+ if (strcmp(voltage_units, "mV") == 0) {
+ _voltage = _voltage / 1000.0;
+ strcpy(voltage_units, "V");
+ }
+
+ if (strcmp(rate_units, "mW") == 0) {
+ _rate = _rate / 1000.0;
+ strcpy(rate_units, "W");
+ }
+
+ if (strcmp(rate_units, "mA") == 0) {
+ _rate = _rate / 1000.0;
+ strcpy(rate_units, "A");
+ }
+
+ if (strcmp(capacity_units, "mAh") == 0) {
+ _capacity = _capacity / 1000.0;
+ strcpy(capacity_units, "Ah");
+ }
+ if (strcmp(capacity_units, "mWh") == 0) {
+ _capacity = _capacity / 1000.0;
+ strcpy(capacity_units, "Wh");
+ }
+ if (strcmp(capacity_units, "Wh") == 0) {
+ _capacity = _capacity * 3600.0;
+ strcpy(capacity_units, "J");
+ }
+
+
+ if (strcmp(capacity_units, "Ah") == 0 && strcmp(voltage_units, "V") == 0) {
+ _capacity = _capacity * 3600.0 * _voltage;
+ strcpy(capacity_units, "J");
+ }
+
+ if (strcmp(rate_units, "A") == 0 && strcmp(voltage_units, "V")==0 ) {
+ _rate = _rate * _voltage;
+ strcpy(rate_units, "W");
+ }
+
+
+
+
+ if (strcmp(capacity_units, "J") == 0)
+ capacity = _capacity;
+ else
+ capacity = 0.0;
+
+ if (strcmp(rate_units, "W")==0)
+ rate = _rate;
+ else
+ rate = 0.0;
+
+ if (strcmp(voltage_units, "V")==0)
+ voltage = _voltage;
+ else
+ voltage = 0.0;
+}
+
+
+void acpi_power_meter::end_measurement(void)
+{
+ measure();
+}
+
+void acpi_power_meter::start_measurement(void)
+{
+ /* ACPI battery state is a lagging indication, lets only measure at the end */
+}
+
+
+double acpi_power_meter::power(void)
+{
+ return rate;
+}
diff --git a/src/measurement/acpi.h b/src/measurement/acpi.h
new file mode 100644
index 0000000..25bbe04
--- /dev/null
+++ b/src/measurement/acpi.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef __INCLUDE_GUARD_ACPI_H
+#define __INCLUDE_GUARD_ACPI_H
+
+#include "measurement.h"
+
+class acpi_power_meter: public power_meter {
+ char battery_name[256];
+
+ double capacity;
+ double rate;
+ double voltage;
+ void measure(void);
+public:
+ acpi_power_meter(const char *_battery_name);
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+ virtual double power(void);
+ virtual double dev_capacity(void) { return capacity; };
+};
+
+#endif
diff --git a/src/measurement/extech.cpp b/src/measurement/extech.cpp
new file mode 100644
index 0000000..867aca7
--- /dev/null
+++ b/src/measurement/extech.cpp
@@ -0,0 +1,354 @@
+/*
+ * extech - Program for controlling the extech Device
+ * This file is part of PowerTOP
+ *
+ * Based on earlier client by Patrick Mochel for Wattsup Pro device
+ * Copyright (c) 2005 Patrick Mochel
+ * Copyright (c) 2006 Intel Corporation
+ * Copyright (c) 2011 Intel Corporation
+ *
+ * Authors:
+ * Patrick Mochel
+ * Venkatesh Pallipadi
+ * Arjan van de Ven
+ *
+ * Thanks to Rajiv Kapoor for finding out the DTR, RTS line bits issue below
+ * Without that this program would never work.
+ *
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <time.h>
+#include <signal.h>
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#include <sys/stat.h>
+
+#include "measurement.h"
+#include "extech.h"
+#include "../lib.h"
+#include <iostream>
+#include <fstream>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+using namespace std;
+
+struct packet {
+ char buf[256];
+ char op[32];
+ double watts;
+ int len;
+};
+
+
+static int open_device(const char *device_name)
+{
+ struct stat s;
+ int ret;
+
+ ret = stat(device_name, &s);
+ if (ret < 0)
+ return -1;
+
+ if (!S_ISCHR(s.st_mode))
+ return -1;
+
+ ret = access(device_name, R_OK | W_OK);
+ if (ret)
+ return -1;
+
+ ret = open(device_name, O_RDWR | O_NONBLOCK | O_NOCTTY);
+ if (ret < 0)
+ return -1;
+
+ return ret;
+}
+
+
+static int setup_serial_device(int dev_fd)
+{
+ struct termios t;
+ int ret;
+ int flgs;
+
+ ret = tcgetattr(dev_fd, &t);
+ if (ret)
+ return ret;
+
+ cfmakeraw(&t);
+ cfsetispeed(&t, B9600);
+ cfsetospeed(&t, B9600);
+ tcflush(dev_fd, TCIFLUSH);
+
+ t.c_iflag = IGNPAR;
+ t.c_cflag = B9600 | CS8 | CREAD | CLOCAL;
+ t.c_oflag = 0;
+ t.c_lflag = 0;
+ t.c_cc[VMIN] = 2;
+ t.c_cc[VTIME] = 0;
+
+ t.c_iflag &= ~(IXON | IXOFF | IXANY);
+ t.c_oflag &= ~(IXON | IXOFF | IXANY);
+
+ ret = tcsetattr(dev_fd, TCSANOW, &t);
+
+ if (ret)
+ return ret;
+
+ /*
+ * Root caused by Rajiv Kapoor. Without this extech reads
+ * will fail
+ */
+
+ /* get DTR and RTS line bits settings */
+ ioctl(dev_fd, TIOCMGET, &flgs);
+
+ /* set DTR to 1 and RTS to 0 */
+ flgs |= TIOCM_DTR;
+ flgs &= ~TIOCM_RTS;
+ ioctl(dev_fd, TIOCMSET, &flgs);
+
+ return 0;
+}
+
+
+static unsigned int decode_extech_value(unsigned char byt3, unsigned char byt4, char *a)
+{
+ unsigned int input = ((unsigned int)byt4 << 8) + byt3;
+ unsigned int i;
+ unsigned int idx;
+ unsigned char revnum[] = { 0x0, 0x8, 0x4, 0xc,
+ 0x2, 0xa, 0x6, 0xe,
+ 0x1, 0x9, 0x5, 0xd,
+ 0x3, 0xb, 0x7, 0xf};
+ unsigned char revdec[] = { 0x0, 0x2, 0x1, 0x3};
+
+ unsigned int digit_map[] = {0x2, 0x3c, 0x3c0, 0x3c00};
+ unsigned int digit_shift[] = {1, 2, 6, 10};
+
+ unsigned int sign;
+ unsigned int decimal;
+
+ /* this is basically BCD encoded floating point... but kinda weird */
+
+ decimal = (input & 0xc000) >> 14;
+ decimal = revdec[decimal];
+
+ sign = input & 0x1;
+
+ idx = 0;
+ if (sign)
+ a[idx++] = '+';
+ else
+ a[idx++] = '-';
+
+ /* first digit is only one or zero */
+ a[idx] = '0';
+ if ((input & digit_map[0]) >> digit_shift[0])
+ a[idx] += 1;
+
+ idx++;
+ /* Reverse the remaining three digits and store in the array */
+ for (i = 1; i < 4; i++) {
+ int dig = ((input & digit_map[i]) >> digit_shift[i]);
+ dig = revnum[dig];
+ if (dig > 0xa)
+ goto error_exit;
+
+ a[idx++] = '0' + dig;
+ }
+
+ /* Fit the decimal point where appropriate */
+ for (i = 0; i < decimal; i++)
+ a[idx - i] = a[idx - i - 1];
+
+ a[idx - decimal] = '.';
+ a[++idx] = '0';
+ a[++idx] = '\0';
+
+ return 0;
+error_exit:
+ return -1;
+}
+
+static int parse_packet(struct packet * p)
+{
+ int i;
+ int ret;
+
+ p->buf[p->len] = '\0';
+
+ /*
+ * First character in 5 character block should be '02'
+ * Fifth character in 5 character block should be '03'
+ */
+ for (i = 0; i < 4; i++) {
+ if (p->buf[i * 0] != 2 || p->buf[i * 0 + 4] != 3) {
+ printf("Invalid packet\n");
+ return -1;
+ }
+ }
+
+ for (i = 0; i < 1; i++) {
+ ret = decode_extech_value(p->buf[5 * i + 2],
+ p->buf[5 * i + 3],
+ &(p->op[8 * i]));
+ if (ret) {
+ printf("Invalid packet, conversion failed\n");
+ return -1;
+ }
+ p->watts = strtod( &(p->op[8 * i]), NULL);
+ }
+ return 0;
+}
+
+
+static double extech_read(int fd)
+{
+ struct packet p;
+ fd_set read_fd;
+ struct timeval tv;
+ int ret;
+
+ if (fd < 0)
+ return 0.0;
+
+ FD_ZERO(&read_fd);
+ FD_SET(fd, &read_fd);
+
+ tv.tv_sec = 0;
+ tv.tv_usec = 500000;
+
+ memset(&p, 0, sizeof(p));
+
+ ret = select(fd + 1, &read_fd, NULL, NULL, &tv);
+ if (ret <= 0)
+ return -1;
+
+ ret = read(fd, &p.buf, 250);
+ if (ret < 0)
+ return ret;
+ p.len = ret;
+
+ if (!parse_packet(&p))
+ return p.watts;
+
+ return -1000.0;
+}
+
+extech_power_meter::extech_power_meter(const char *extech_name)
+{
+ rate = 0.0;
+ pt_strcpy(dev_name, extech_name);
+ int ret;
+
+ fd = open_device(dev_name);
+ if (fd < 0)
+ return;
+
+ ret = setup_serial_device(fd);
+ if (ret) {
+ close(fd);
+ fd = -1;
+ return;
+ }
+}
+
+
+void extech_power_meter::measure(void)
+{
+ /* trigger the extech to send data */
+ if(write(fd, " ", 1) == -1)
+ printf("Error: %s\n", strerror(errno));
+
+ rate = extech_read(fd);
+
+}
+
+void extech_power_meter::sample(void)
+{
+ ssize_t ret;
+ struct timespec tv;
+
+ tv.tv_sec = 0;
+ tv.tv_nsec = 200000000;
+ while (!end_thread) {
+ nanosleep(&tv, NULL);
+ /* trigger the extech to send data */
+ ret = write(fd, " ", 1);
+ if (ret < 0)
+ continue;
+
+ sum += extech_read(fd);
+ samples++;
+
+ }
+}
+
+extern "C"
+{
+ void* thread_proc(void *arg)
+ {
+ class extech_power_meter *parent;
+ parent = (class extech_power_meter*)arg;
+ parent->sample();
+ return 0;
+ }
+}
+
+void extech_power_meter::end_measurement(void)
+{
+ end_thread = 1;
+ pthread_join( thread, NULL);
+ if (samples){
+ rate = sum / samples;
+ }
+ else
+ measure();
+}
+
+void extech_power_meter::start_measurement(void)
+{
+ end_thread = 0;
+ sum = samples = 0;
+
+ if (pthread_create(&thread, NULL, thread_proc, this))
+ fprintf(stderr, "ERROR: extech measurement thread creation failed\n");
+
+}
+
+
+double extech_power_meter::power(void)
+{
+ return rate;
+}
diff --git a/src/measurement/extech.h b/src/measurement/extech.h
new file mode 100644
index 0000000..b7b330a
--- /dev/null
+++ b/src/measurement/extech.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef __INCLUDE_GUARD_EXTECH_H
+#define __INCLUDE_GUARD_EXTECH_H
+
+#include <pthread.h>
+#include "measurement.h"
+
+class extech_power_meter: public power_meter {
+ char dev_name[256];
+ int fd;
+
+ double rate;
+ void measure(void);
+ double sum;
+ int samples;
+ int end_thread;
+ pthread_t thread;
+public:
+ extech_power_meter(const char *_dev_name);
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+ virtual void sample(void);
+
+ virtual double power(void);
+ virtual double dev_capacity(void) { return 0.0; };
+};
+
+#endif
diff --git a/src/measurement/measurement.cpp b/src/measurement/measurement.cpp
new file mode 100644
index 0000000..caee24e
--- /dev/null
+++ b/src/measurement/measurement.cpp
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include "measurement.h"
+#include "acpi.h"
+#include "extech.h"
+#include "sysfs.h"
+#include "opal-sensors.h"
+#include "../parameters/parameters.h"
+#include "../lib.h"
+
+#include <string>
+#include <sys/types.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <fstream>
+#include <unistd.h>
+#include <time.h>
+
+double min_power = 50000.0;
+
+void power_meter::start_measurement(void)
+{
+}
+
+
+void power_meter::end_measurement(void)
+{
+}
+
+
+double power_meter::power(void)
+{
+ return 0.0;
+}
+
+vector<class power_meter *> power_meters;
+
+static struct timespec tlast;
+
+void start_power_measurement(void)
+{
+ unsigned int i;
+ clock_gettime(CLOCK_REALTIME, &tlast);
+ for (i = 0; i < power_meters.size(); i++)
+ power_meters[i]->start_measurement();
+ all_results.joules = 0.0;
+}
+void end_power_measurement(void)
+{
+ unsigned int i;
+ for (i = 0; i < power_meters.size(); i++)
+ power_meters[i]->end_measurement();
+}
+
+double global_power(void)
+{
+ bool global_discharging = false;
+ double total = 0.0;
+ unsigned int i;
+
+ for (i = 0; i < power_meters.size(); i++) {
+ global_discharging |= power_meters[i]->is_discharging();
+ total += power_meters[i]->power();
+ }
+
+ /* report global time left if at least one battery is discharging */
+ if (!global_discharging)
+ return 0.0;
+
+ all_results.power = total;
+ if (total < min_power && total > 0.01)
+ min_power = total;
+ return total;
+}
+
+void global_sample_power(void)
+{
+ struct timespec tnow;
+
+ clock_gettime(CLOCK_REALTIME, &tnow);
+ /* power * time = joules */
+ all_results.joules += global_power() * \
+ ( ((double)tnow.tv_sec + 1.0e-9*tnow.tv_nsec) - \
+ ((double)tlast.tv_sec + 1.0e-9*tlast.tv_nsec));
+ tlast = tnow;
+}
+
+double global_joules(void)
+{
+ return all_results.joules;
+}
+
+double global_time_left(void)
+{
+ bool global_discharging = false;
+ double total_capacity = 0.0;
+ double total_rate = 0.0;
+ unsigned int i;
+ for (i = 0; i < power_meters.size(); i++) {
+ global_discharging |= power_meters[i]->is_discharging();
+ total_capacity += power_meters[i]->dev_capacity();
+ total_rate += power_meters[i]->power();
+ }
+ /* report global time left if at least one battery is discharging */
+ if (!global_discharging)
+ return 0.0;
+
+ /* return 0.0 instead of INF+ */
+ if (total_rate < 0.001)
+ return 0.0;
+ return total_capacity / total_rate;
+}
+
+void sysfs_power_meters_callback(const char *d_name)
+{
+ std::string type = read_sysfs_string("/sys/class/power_supply/%s/type", d_name);
+
+ if (type != "Battery" && type != "UPS")
+ return;
+
+ class sysfs_power_meter *meter;
+ meter = new(std::nothrow) class sysfs_power_meter(d_name);
+ if (meter)
+ power_meters.push_back(meter);
+}
+
+void acpi_power_meters_callback(const char *d_name)
+{
+ class acpi_power_meter *meter;
+ meter = new(std::nothrow) class acpi_power_meter(d_name);
+ if (meter)
+ power_meters.push_back(meter);
+}
+
+void sysfs_opal_sensors_callback(const char *d_name)
+{
+ class opal_sensors_power_meter *meter;
+ const char *c;
+
+ /* Those that end in / are directories and we don't want them */
+ c = strrchr(d_name, '/');
+ if (c && *(c+1) == '\0')
+ return;
+
+ meter = new(std::nothrow) class opal_sensors_power_meter(d_name);
+ if (meter)
+ power_meters.push_back(meter);
+}
+
+void detect_power_meters(void)
+{
+ process_directory("/sys/class/power_supply", sysfs_power_meters_callback);
+ process_glob("/sys/devices/platform/opal-sensor/hwmon/hwmon*/power*", sysfs_opal_sensors_callback);
+ if (power_meters.size() == 0) {
+ process_directory("/proc/acpi/battery", acpi_power_meters_callback);
+ }
+}
+
+void extech_power_meter(const char *devnode)
+{
+ class extech_power_meter *meter;
+
+ meter = new class extech_power_meter(devnode);
+
+ power_meters.push_back(meter);
+}
diff --git a/src/measurement/measurement.h b/src/measurement/measurement.h
new file mode 100644
index 0000000..9a84bc2
--- /dev/null
+++ b/src/measurement/measurement.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef __INCLUDE_GUARD_MEASUREMENT_H
+#define __INCLUDE_GUARD_MEASUREMENT_H
+
+#include <vector>
+
+using namespace std;
+
+class power_meter {
+ bool discharging = false;
+public:
+ virtual ~power_meter() {};
+
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+ virtual double power(void);
+
+ virtual double dev_capacity(void)
+ {
+ return 0.0; /* in Joules */
+ }
+
+ virtual void set_discharging(bool d)
+ {
+ discharging = d;
+ }
+
+ virtual bool is_discharging()
+ {
+ return discharging;
+ }
+};
+
+extern vector<class power_meter *> power_meters;
+
+extern void start_power_measurement(void);
+extern void end_power_measurement(void);
+extern double global_power(void);
+extern void global_sample_power(void);
+extern double global_joules(void);
+extern double global_time_left(void);
+
+extern void detect_power_meters(void);
+extern void extech_power_meter(const char *devnode);
+
+extern double min_power;
+
+#endif
diff --git a/src/measurement/opal-sensors.cpp b/src/measurement/opal-sensors.cpp
new file mode 100644
index 0000000..a70ec56
--- /dev/null
+++ b/src/measurement/opal-sensors.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015 IBM Corp.
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Stewart Smith <stewart@linux.vnet.ibm.com>
+ */
+#include "measurement.h"
+#include "opal-sensors.h"
+#include "../lib.h"
+#include <string.h>
+#include <stdio.h>
+#include <limits.h>
+
+opal_sensors_power_meter::opal_sensors_power_meter(const char *power_supply_name)
+{
+ strncpy(name, power_supply_name, sizeof(name));
+}
+
+double opal_sensors_power_meter::power(void)
+{
+ bool ok;
+ int value;
+ double r = 0;
+
+ value = read_sysfs(name, &ok);
+
+ if(ok)
+ r = value / 1000000.0;
+ return r;
+}
diff --git a/src/measurement/opal-sensors.h b/src/measurement/opal-sensors.h
new file mode 100644
index 0000000..7962091
--- /dev/null
+++ b/src/measurement/opal-sensors.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015 IBM Corp.
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Stewart Smith <stewart@linux.vnet.ibm.com>
+ */
+#ifndef INCLUDE_GUARD_OPAL_SENSORS_H
+#define INCLUDE_GUARD_OPAL_SENSORS_H
+
+#include "measurement.h"
+#include <limits.h>
+
+class opal_sensors_power_meter: public power_meter {
+ char name[PATH_MAX];
+public:
+ opal_sensors_power_meter(const char *power_supply_name);
+ virtual void start_measurement(void) {};
+ virtual void end_measurement(void) {};
+
+ virtual double power(void);
+ virtual double dev_capacity(void) { return 0.0; }
+};
+
+#endif
diff --git a/src/measurement/sysfs.cpp b/src/measurement/sysfs.cpp
new file mode 100644
index 0000000..c5a7a12
--- /dev/null
+++ b/src/measurement/sysfs.cpp
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2011 Anssi Hannula
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Anssi Hannula <anssi.hannula@iki.fi>
+ */
+#include "measurement.h"
+#include "sysfs.h"
+#include "../lib.h"
+#include <string.h>
+#include <stdio.h>
+#include <limits.h>
+
+sysfs_power_meter::sysfs_power_meter(const char *power_supply_name)
+{
+ rate = 0.0;
+ capacity = 0.0;
+ pt_strcpy(name, power_supply_name);
+}
+
+bool sysfs_power_meter::get_sysfs_attr(const char *attribute, int *value)
+{
+ char filename[PATH_MAX];
+ bool ok;
+
+ snprintf(filename, sizeof(filename), "/sys/class/power_supply/%s/%s", name, attribute);
+ *value = read_sysfs(filename, &ok);
+
+ return ok;
+}
+
+bool sysfs_power_meter::is_present()
+{
+ int present = 0;
+
+ if (!get_sysfs_attr("present", &present))
+ return true; /* assume always present */
+
+ return present;
+}
+
+double sysfs_power_meter::get_voltage()
+{
+ int voltage;
+
+ if (!get_sysfs_attr("voltage_now", &voltage))
+ return -1.0;
+
+ /* µV to V */
+ return voltage / 1000000.0;
+}
+
+bool sysfs_power_meter::set_rate_from_power()
+{
+ int power;
+
+ if (!get_sysfs_attr("power_now", &power))
+ return false;
+
+ /* µW to W */
+ rate = power / 1000000.0;
+ return true;
+}
+
+bool sysfs_power_meter::set_rate_from_current(double voltage)
+{
+ int current;
+
+ if (!get_sysfs_attr("current_now", &current))
+ return false;
+
+ /* current: µA
+ * voltage: V
+ * rate: W */
+ rate = (current / 1000000.0) * voltage;
+ return true;
+}
+
+bool sysfs_power_meter::set_capacity_from_energy()
+{
+ int energy;
+
+ if (!get_sysfs_attr("energy_now", &energy))
+ return false;
+
+ /* µWh to J */
+ capacity = energy / 1000000.0 * 3600.0;
+ return true;
+}
+
+bool sysfs_power_meter::set_capacity_from_charge(double voltage)
+{
+ int charge;
+
+ if (!get_sysfs_attr("charge_now", &charge))
+ return false;
+
+ /* charge: µAh
+ * voltage: V
+ * capacity: J */
+ capacity = (charge / 1000000.0) * voltage * 3600.0;
+ return true;
+}
+
+void sysfs_power_meter::measure()
+{
+ bool got_rate = false;
+ bool got_capacity = false;
+
+ rate = 0.0;
+ capacity = 0.0;
+ this->set_discharging(false);
+
+ if (!is_present())
+ return;
+ /** do not jump over. we may have discharging battery */
+ if (read_sysfs_string("/sys/class/power_supply/%s/status", name) == "Discharging")
+ this->set_discharging(true);
+
+ got_rate = set_rate_from_power();
+ got_capacity = set_capacity_from_energy();
+
+ if (!got_rate || !got_capacity) {
+ double voltage = get_voltage();
+ if (voltage < 0.0)
+ return;
+ if (!got_rate)
+ set_rate_from_current(voltage);
+ if (!got_capacity)
+ set_capacity_from_charge(voltage);
+ }
+}
+
+void sysfs_power_meter::end_measurement(void)
+{
+ measure();
+}
+
+void sysfs_power_meter::start_measurement(void)
+{
+ /* Battery state is generally a lagging indication, lets only measure at the end */
+}
diff --git a/src/measurement/sysfs.h b/src/measurement/sysfs.h
new file mode 100644
index 0000000..5b440f5
--- /dev/null
+++ b/src/measurement/sysfs.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2011 Anssi Hannula
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Anssi Hannula <anssi.hannula@iki.fi>
+ */
+#ifndef INCLUDE_GUARD_SYSFS_H
+#define INCLUDE_GUARD_SYSFS_H
+
+#include "measurement.h"
+
+class sysfs_power_meter: public power_meter {
+ char name[256];
+
+ double capacity;
+ double rate;
+
+ bool get_sysfs_attr(const char *attribute, int *value);
+ bool is_present();
+ double get_voltage();
+
+ bool set_rate_from_power();
+ bool set_rate_from_current(double voltage);
+ bool set_capacity_from_energy();
+ bool set_capacity_from_charge(double voltage);
+
+ void measure();
+public:
+ sysfs_power_meter(const char *power_supply_name);
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+ virtual double power(void) { return rate; }
+ virtual double dev_capacity(void) { return capacity; }
+};
+
+#endif
diff --git a/src/parameters/learn.cpp b/src/parameters/learn.cpp
new file mode 100644
index 0000000..aaef5a2
--- /dev/null
+++ b/src/parameters/learn.cpp
@@ -0,0 +1,282 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include "parameters.h"
+#include "../measurement/measurement.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+extern int debug_learning;
+
+double calculate_params(struct parameter_bundle *params)
+{
+ unsigned int i;
+
+ params->score = 0;
+
+
+ for (i = 0; i < past_results.size(); i++)
+ compute_bundle(params, past_results[i]);
+
+ return params->score;
+}
+
+
+/*
+ * gradual linear convergence of non-independent variables works better if once in a while
+ * you make a wrong move....
+ */
+static int random_disturb(int retry_left)
+{
+ if (retry_left < 10)
+ return 0;
+
+ if ( (rand() % 500) == 7)
+ return 1;
+ return 0;
+}
+
+static int try_zero(double value)
+{
+ if (value > 0.01)
+ if ( (rand() % 100) == 1)
+ return 1;
+
+ if ( (rand() % 5) == 1)
+ return 1;
+ return 0;
+}
+
+static unsigned int previous_measurements;
+
+static void weed_empties(struct parameter_bundle *best_so_far)
+{
+ double best_score;
+ unsigned int i;
+
+ best_score = best_so_far->score;
+
+
+ for (i = 0; i < best_so_far->parameters.size(); i++) {
+ double orgvalue;
+
+ orgvalue = best_so_far->parameters[i];
+
+
+ best_so_far->parameters[i] = 0.0;
+
+ calculate_params(best_so_far);
+ if (best_so_far->score > best_score) {
+ best_so_far->parameters[i] = orgvalue;
+ } else {
+ best_score = best_so_far->score;
+ }
+
+ }
+ calculate_params(best_so_far);
+
+}
+
+/* leaks like a sieve */
+void learn_parameters(int iterations, int do_base_power)
+{
+ struct parameter_bundle *best_so_far;
+ double best_score = 10000000000000000.0;
+ int retry = iterations;
+ int prevparam = -1;
+ int locked = 0;
+ static unsigned int bpi = 0;
+ unsigned int i;
+ time_t start;
+
+ /* don't start fitting anything until we have at least 1 more measurement than we have parameters */
+ if (past_results.size() <= all_parameters.parameters.size())
+ return;
+
+
+
+// if (past_results.size() == previous_measurements)
+// return;
+
+ precompute_valid();
+
+
+ previous_measurements = past_results.size();
+
+ double delta = 0.50;
+
+ best_so_far = &all_parameters;
+
+ if (!bpi)
+ bpi = get_param_index("base power");
+
+ calculate_params(best_so_far);
+ best_score = best_so_far->score;
+
+ delta = 0.001 / pow(0.8, iterations / 2.0);
+ if (iterations < 25)
+ delta = 0.001 / pow(0.5, iterations / 2.0);
+
+ if (delta > 0.2)
+ delta = 0.2;
+
+ if (1.0 * best_score / past_results.size() < 4 && delta > 0.05)
+ delta = 0.05;
+
+ if (debug_learning)
+ printf("Delta starts at %5.3f\n", delta);
+
+ if (best_so_far->parameters[bpi] > min_power * 0.9)
+ best_so_far->parameters[bpi] = min_power * 0.9;
+
+ /* We want to give up a little of base power, to give other parameters room to change;
+ base power is the end post for everything after all
+ */
+ if (do_base_power && !debug_learning)
+ best_so_far->parameters[bpi] = best_so_far->parameters[bpi] * 0.9998;
+
+ start = time(NULL);
+
+ while (retry--) {
+ int changed = 0;
+ int bestparam;
+ double newvalue = 0;
+ double orgscore;
+ double weight;
+
+ bestparam = -1;
+
+ if (time(NULL) - start > 1 && !debug_learning)
+ retry = 0;
+
+ calculate_params(best_so_far);
+ orgscore = best_score = best_so_far->score;
+
+
+ for (i = 1; i < best_so_far->parameters.size(); i++) {
+ double value, orgvalue;
+
+ weight = delta * best_so_far->weights[i];
+
+ orgvalue = value = best_so_far->parameters[i];
+ if (value <= 0.001) {
+ value = 0.1;
+ } else
+ value = value * (1 + weight);
+
+ if (i == bpi && value > min_power)
+ value = min_power;
+
+ if (i == bpi && orgvalue > min_power)
+ orgvalue = min_power;
+
+ if (value > 5000)
+ value = 5000;
+
+// printf("Trying %s %4.2f -> %4.2f\n", param.c_str(), best_so_far->parameters[param], value);
+ best_so_far->parameters[i] = value;
+
+ calculate_params(best_so_far);
+ if (best_so_far->score < best_score || random_disturb(retry)) {
+ best_score = best_so_far->score;
+ newvalue = value;
+ bestparam = i;
+ changed++;
+ }
+
+ value = orgvalue * 1 / (1 + weight);
+
+ if (value < 0.0001)
+ value = 0.0;
+
+ if (try_zero(value))
+ value = 0.0;
+
+
+ if (value > 5000)
+ value = 5000;
+
+
+// printf("Trying %s %4.2f -> %4.2f\n", param.c_str(), orgvalue, value);
+
+ if (orgvalue != value) {
+ best_so_far->parameters[i] = value;
+
+ calculate_params(best_so_far);
+
+ if (best_so_far->score + 0.00001 < best_score || (random_disturb(retry) && value > 0.0)) {
+ best_score = best_so_far->score;
+ newvalue = value;
+ bestparam = i;
+ changed++;
+ }
+ }
+ best_so_far->parameters[i] = orgvalue;
+
+ }
+ if (!changed) {
+ double mult;
+
+ if (!locked) {
+ mult = 0.8;
+ if (iterations < 25)
+ mult = 0.5;
+ delta = delta * mult;
+ }
+ locked = 0;
+ prevparam = -1;
+ } else {
+ if (debug_learning) {
+ printf("Retry is %i \n", retry);
+ printf("delta is %5.4f\n", delta);
+ printf("Best parameter is %i \n", bestparam);
+ printf("Changing score from %4.3f to %4.3f\n", orgscore, best_score);
+ printf("Changing value from %4.3f to %4.3f\n", best_so_far->parameters[bestparam], newvalue);
+ }
+ best_so_far->parameters[bestparam] = newvalue;
+ if (prevparam == bestparam)
+ delta = delta * 1.1;
+ prevparam = bestparam;
+ locked = 1;
+ }
+
+ if (delta < 0.001 && !locked)
+ break;
+
+ if (retry % 50 == 49)
+ weed_empties(best_so_far);
+ }
+
+
+ /* now we weed out all parameters that don't have value */
+ if (iterations > 50)
+ weed_empties(best_so_far);
+
+ if (debug_learning)
+ printf("Final score %4.2f (%i points)\n", best_so_far->score / past_results.size(), (int)past_results.size());
+// dump_parameter_bundle(best_so_far);
+// dump_past_results();
+}
diff --git a/src/parameters/parameters.cpp b/src/parameters/parameters.cpp
new file mode 100644
index 0000000..38e1752
--- /dev/null
+++ b/src/parameters/parameters.cpp
@@ -0,0 +1,462 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include "parameters.h"
+#include "../measurement/measurement.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <vector>
+#include <unistd.h>
+#include <limits.h>
+
+
+struct parameter_bundle all_parameters;
+struct result_bundle all_results;
+
+vector <struct result_bundle *> past_results;
+
+map <string, int> param_index;
+static int maxindex = 1;
+map <string, int> result_index;
+static int maxresindex = 1;
+
+int get_param_index(const char *name)
+{
+ std::map<string, int>::iterator it;
+ int index = 0;
+
+ it = param_index.find(name);
+ if (it == param_index.end()) {
+ param_index[name] = ++maxindex;
+ index = maxindex;
+ } else
+ index = it->second;
+
+ if (index == 0)
+ printf("OH BLA\n");
+ return index;
+}
+
+int get_result_index(const char *name)
+{
+ std::map<string, int>::iterator it;
+ int index = 0;
+
+ it = result_index.find(name);
+ if (it == result_index.end()) {
+ result_index[name] = ++maxresindex;
+ index = maxresindex;
+ } else
+ index = it->second;
+
+ return index;
+}
+
+
+void register_parameter(const char *name, double default_value, double weight)
+{
+ int index;
+
+ index = get_param_index(name);
+
+ if (index >= (int)all_parameters.parameters.size()) {
+ all_parameters.parameters.resize(index+1, 0.0);
+ all_parameters.weights.resize(index+1, 1.0);
+ }
+
+ if (all_parameters.parameters[index] <= 0.0001)
+ all_parameters.parameters[index] = default_value;
+
+ all_parameters.weights[index] = weight;
+}
+
+void set_parameter_value(const char *name, double value, struct parameter_bundle *bundle)
+{
+ int index;
+
+ index = get_param_index(name);
+
+ if (index >= (int)bundle->parameters.size()) {
+ bundle->parameters.resize(index+1, 0.0);
+ bundle->weights.resize(index+1, 1.0);
+ }
+
+ bundle->parameters[index] = value;
+}
+
+double get_parameter_value(const char *name, struct parameter_bundle *the_bundle)
+{
+ unsigned int index;
+ index = get_param_index(name);
+ return get_parameter_value(index, the_bundle);
+}
+
+double get_parameter_value(unsigned int index, struct parameter_bundle *the_bundle)
+{
+ if (index >= the_bundle->parameters.size()) {
+ fprintf(stderr, "BUG: requesting unregistered parameter %d\n", index);
+ return 0;
+ }
+ return the_bundle->parameters[index];
+}
+
+double get_parameter_weight(int index, struct parameter_bundle *the_bundle)
+{
+ return the_bundle->weights[index];
+}
+
+double get_result_value(const char *name, struct result_bundle *the_bundle)
+{
+ return get_result_value(get_result_index(name), the_bundle);
+}
+
+void set_result_value(const char *name, double value, struct result_bundle *the_bundle)
+{
+ unsigned int index = get_result_index(name);
+ if (index >= the_bundle->utilization.size())
+ the_bundle->utilization.resize(index+1);
+ the_bundle->utilization[index] = value;
+}
+
+void set_result_value(unsigned int index, double value, struct result_bundle *the_bundle)
+{
+ if (index >= the_bundle->utilization.size())
+ the_bundle->utilization.resize(index+1);
+ the_bundle->utilization[index] = value;
+}
+
+double get_result_value(int index, struct result_bundle *the_bundle)
+{
+ if (!the_bundle)
+ return 0;
+ if (index >= (int) the_bundle->utilization.size())
+ return 0;
+ return the_bundle->utilization[index];
+}
+
+
+int result_device_exists(const char *name)
+{
+ unsigned int i;
+ for (i = 0; i < all_devices.size(); i++) {
+ if (strcmp(all_devices[i]->device_name(), name) == 0)
+ return 1;
+ }
+ return 0;
+}
+
+void report_utilization(const char *name, double value, struct result_bundle *bundle)
+{
+ set_result_value(name, value, bundle);
+}
+void report_utilization(int index, double value, struct result_bundle *bundle)
+{
+ set_result_value(index, value, bundle);
+}
+
+
+
+double compute_bundle(struct parameter_bundle *parameters, struct result_bundle *results)
+{
+ double power = 0;
+ unsigned int i;
+
+ static int bpi = 0;
+
+ if (!bpi)
+ bpi = get_param_index("base power");
+
+ for (i = 0; i < all_devices.size(); i++)
+ power += all_devices[i]->power_usage(results, parameters);
+
+ parameters->actual_power = results->power;
+ parameters->guessed_power = power;
+ /* scale the squared error by the actual power so that non-idle data points weigh heavier */
+ parameters->score += results->power * (power - results->power) * (power - results->power);
+ parameters->parameters[bpi] = power;
+ return power;
+}
+
+static int precomputed_valid = 0;
+void precompute_valid(void)
+{
+ unsigned int i;
+
+
+ for (i = 0; i < all_devices.size(); i++) {
+ all_devices[i]->cached_valid = all_devices[i]->power_valid();
+ }
+ precomputed_valid = 1;
+}
+
+double bundle_power(struct parameter_bundle *parameters, struct result_bundle *results)
+{
+ double power = 0;
+ unsigned int i;
+ static int bpi = 0;
+
+ if (!bpi)
+ bpi = get_param_index("base power");
+
+ if (!precomputed_valid)
+ precompute_valid();
+
+
+ power = parameters->parameters[bpi];
+
+ for (i = 0; i < all_devices.size(); i++) {
+
+ if (all_devices[i]->cached_valid)
+ power += all_devices[i]->power_usage(results, parameters);
+ }
+
+ return power;
+}
+
+
+void dump_parameter_bundle(struct parameter_bundle *para)
+{
+ map<string, int>::iterator it;
+ int index;
+
+ printf("\n\n");
+ printf("Parameter state \n");
+ printf("----------------------------------\n");
+ printf("Value\t\tName\n");
+ for (it = param_index.begin(); it != param_index.end(); it++) {
+ index = it->second;
+ printf("%5.2f\t\t%s (%i)\n", para->parameters[index], it->first.c_str(), index);
+ }
+
+ printf("\n");
+ printf("Score: %5.1f (%5.1f)\n", sqrt(para->score / (0.001 + past_results.size()) / average_power()), para->score);
+ printf("Guess: %5.1f\n", para->guessed_power);
+ printf("Actual: %5.1f\n", para->actual_power);
+
+ printf("----------------------------------\n");
+}
+
+void dump_result_bundle(struct result_bundle *res)
+{
+ map<string, int>::iterator it;
+ unsigned int index;
+
+ printf("\n\n");
+ printf("Utilisation state \n");
+ printf("----------------------------------\n");
+ printf("Value\t\tName\n");
+ for (it = result_index.begin(); it != result_index.end(); it++) {
+ index = get_result_index(it->first.c_str());
+ printf("%5.2f%%\t\t%s(%i)\n", res->utilization[index], it->first.c_str(), index);
+ }
+
+ printf("\n");
+ printf("Power: %5.1f\n", res->power);
+
+ printf("----------------------------------\n");
+}
+
+struct result_bundle * clone_results(struct result_bundle *bundle)
+{
+ struct result_bundle *b2;
+ map<string, double>::iterator it;
+ unsigned int i;
+
+ b2 = new struct result_bundle;
+
+ if (!b2)
+ return NULL;
+
+ b2->power = bundle->power;
+ b2->utilization.resize(bundle->utilization.size());
+
+ for (i = 0; i < bundle->utilization.size(); i++) {
+ b2->utilization[i] = bundle->utilization[i];
+ }
+
+ return b2;
+}
+
+
+struct parameter_bundle * clone_parameters(struct parameter_bundle *bundle)
+{
+ struct parameter_bundle *b2;
+ unsigned int i;
+
+ b2 = new struct parameter_bundle;
+
+ if (!b2)
+ return NULL;
+
+ b2->score = 0;
+ b2->guessed_power = 0;
+ b2->actual_power = bundle->actual_power;
+ b2->parameters.resize(bundle->parameters.size());
+ for (i = 0; i < bundle->parameters.size(); i++) {
+ b2->parameters[i] = bundle->parameters[i];
+ }
+
+ return b2;
+}
+
+
+void store_results(double duration)
+{
+ if (duration < 5)
+ return;
+ global_power();
+ if (all_results.power > 0.01) {
+ unsigned int overflow_index;
+ overflow_index = 50 + (rand() % MAX_KEEP);
+ if (past_results.size() >= MAX_PARAM) {
+ /* memory leak, must free old one first */
+ past_results[overflow_index] = clone_results(&all_results);
+ } else {
+ past_results.push_back(clone_results(&all_results));
+ }
+ if ((past_results.size() % 10) == 0)
+ save_all_results("saved_results.powertop");
+ }
+
+}
+
+
+
+void dump_past_results(void)
+{
+ unsigned int j;
+ unsigned int i;
+ struct result_bundle *result;
+
+ for (j = 0; j < past_results.size(); j+=10) {
+ printf("Est ");
+ for (i = j; i < past_results.size() && i < j + 10; i++) {
+ result = past_results[i];
+ printf("%6.2f ", bundle_power(&all_parameters, result));
+ }
+ printf("\n");
+ printf("Actual ");
+ for (i = j; i < past_results.size() && i < j + 10; i++) {
+ result = past_results[i];
+ printf("%6.2f ", result->power);
+ }
+ printf("\n\n");
+ }
+}
+
+double average_power(void)
+{
+ double sum = 0.0;
+ unsigned int i;
+ for (i = 0; i < past_results.size(); i++)
+ sum += past_results[i]->power;
+
+ if (past_results.size())
+ sum = sum / past_results.size() + 0.0001;
+ else
+ sum = 0.0001;
+ return sum;
+}
+
+int utilization_power_valid(const char *u)
+{
+ unsigned int i;
+ unsigned int index;
+ double first_value;
+
+ index = get_result_index(u);
+ if (index <= 0)
+ return 0;
+
+ first_value = past_results[0]->utilization[index];
+ for (i = 1; i < past_results.size(); i++) {
+ if (get_result_value(index, past_results[i]) < first_value - 0.0001)
+ return 1;
+ if (get_result_value(index, past_results[i]) > first_value + 0.0001)
+ return 1;
+ }
+
+ return 0;
+}
+
+int utilization_power_valid(int index)
+{
+ unsigned int i;
+ double first_value;
+
+ if (index <= 0)
+ return 0;
+
+ if (past_results.size() == 0)
+ return 0;
+
+ if (index >= (int)past_results[0]->utilization.size())
+ return 0;
+ first_value = past_results[0]->utilization[index];
+ for (i = 1; i < past_results.size(); i++) {
+ if (get_result_value(index, past_results[i]) < first_value - 0.0001)
+ return 1;
+ if (get_result_value(index, past_results[i]) > first_value + 0.0001)
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/* force power data to be valid to the rest of the system */
+int global_power_override = 0;
+int global_run_times=0;
+/*
+ * only report power numbers once we have 3* more measurements than
+ * we have parameters; anything less and our model fit is highly suspect
+ */
+int global_power_valid(void)
+{
+ if (past_results.size() > 3 * all_parameters.parameters.size())
+ return 1;
+
+ if (past_results.size() > 0 && global_run_times < 1){
+ printf("To show power estimates do %ld measurement(s) connected to battery only\n",
+ (3 * all_parameters.parameters.size()) - past_results.size());
+ global_run_times += 1;
+ }
+
+ return global_power_override;
+}
+
+/* find the directory to store powertop results/parameters based on distribution*/
+char* get_param_directory(const char *filename)
+{
+ static char tempfilename[PATH_MAX];
+
+ if (access("/var/cache/powertop", W_OK ) == 0)
+ snprintf(tempfilename, sizeof(tempfilename), "/var/cache/powertop/%s", filename);
+ if (access("/data/local/powertop", W_OK ) == 0)
+ snprintf(tempfilename, sizeof(tempfilename), "/data/local/powertop/%s", filename);
+
+ return tempfilename;
+};
diff --git a/src/parameters/parameters.h b/src/parameters/parameters.h
new file mode 100644
index 0000000..1781a0e
--- /dev/null
+++ b/src/parameters/parameters.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef __INCLUDE_GUARD_PARAMETERS_H_
+#define __INCLUDE_GUARD_PARAMETERS_H_
+
+
+#include <map>
+#include <vector>
+#include <string>
+
+#include "string.h"
+#include "../devices/device.h"
+#include "../lib.h"
+
+using namespace std;
+
+#define MAX_KEEP 700
+#define MAX_PARAM 750
+
+
+struct parameter_bundle
+{
+ double score;
+ double guessed_power;
+ double actual_power;
+
+ vector<double> parameters;
+ vector<double> weights;
+};
+
+extern struct parameter_bundle all_parameters;
+extern map <string, int> param_index;
+extern map <string, int> result_index;
+
+extern int get_param_index(const char *param);
+extern int get_result_index(const char *param);
+
+
+extern void register_parameter(const char *name, double default_value = 0.00, double weight = 1.0);
+extern double get_parameter_value(const char *name, struct parameter_bundle *bundle = &all_parameters);
+extern double get_parameter_value(unsigned int index, struct parameter_bundle *bundle = &all_parameters);
+extern void set_parameter_value(const char *name, double value, struct parameter_bundle *bundle = &all_parameters);
+
+
+struct result_bundle
+{
+ double joules;
+ double power;
+ vector <double> utilization; /* device name, device utilization %age */
+};
+
+extern struct result_bundle all_results;
+extern vector <struct result_bundle *> past_results;
+
+extern double get_result_value(const char *name, struct result_bundle *bundle = &all_results);
+extern double get_result_value(int index, struct result_bundle *bundle = &all_results);
+
+extern void set_result_value(const char *name, double value, struct result_bundle *bundle = &all_results);
+
+
+extern int result_device_exists(const char *name);
+
+extern void report_utilization(const char *name, double value, struct result_bundle *bundle = &all_results);
+extern void report_utilization(int index, double value, struct result_bundle *bundle = &all_results);
+
+
+extern void precompute_valid(void);
+
+extern double compute_bundle(struct parameter_bundle *parameters = &all_parameters, struct result_bundle *results = &all_results);
+
+
+void dump_parameter_bundle(struct parameter_bundle *patameters = &all_parameters);
+void dump_result_bundle(struct result_bundle *res = &all_results);
+
+extern struct result_bundle * clone_results(struct result_bundle *bundle);
+extern struct parameter_bundle * clone_parameters(struct parameter_bundle *bundle);
+
+extern void store_results(double duration);
+extern void learn_parameters(int iterations, int do_base_power);
+extern char *get_param_directory(const char *filename);
+extern void save_all_results(const char *filename = "saved_results.powertop");
+extern void close_results(void);
+extern void load_results(const char *filename);
+extern void save_parameters(const char *filename);
+extern void load_parameters(const char *filename);
+
+extern void dump_past_results(void);
+extern double bundle_power(struct parameter_bundle *parameters, struct result_bundle *results);
+
+extern double average_power(void);
+
+extern int utilization_power_valid(const char *u);
+extern int utilization_power_valid(int index);
+extern double calculate_params(struct parameter_bundle *params = &all_parameters);
+int global_power_valid(void);
+
+
+extern int global_power_override;
+
+
+#endif
diff --git a/src/parameters/persistent.cpp b/src/parameters/persistent.cpp
new file mode 100644
index 0000000..0711b4d
--- /dev/null
+++ b/src/parameters/persistent.cpp
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+#include <stdlib.h>
+
+#include "parameters.h"
+#include "../measurement/measurement.h"
+
+using namespace std;
+
+void save_all_results(const char *filename)
+{
+ ofstream file;
+ unsigned int i;
+ struct result_bundle *bundle;
+ char* pathname;
+
+ pathname = get_param_directory(filename);
+
+ file.open(pathname, ios::out);
+ if (!file) {
+ cout << _("Cannot save to file") << " " << pathname << "\n";
+ return;
+ }
+ for (i = 0; i < past_results.size(); i++) {
+ bundle = past_results[i];
+ map<string, int>::iterator it;
+ file << setiosflags(ios::fixed) << setprecision(5) << bundle->power << "\n";
+
+ for (it = result_index.begin(); it != result_index.end(); it++) {
+ file << it->first << "\t" << setprecision(5) << get_result_value(it->second, bundle) << "\n";
+ }
+ file << ":\n";
+ }
+
+ file.close();
+
+}
+
+void close_results()
+{
+ for (unsigned int i = 0; i < past_results.size(); i++) {
+ delete past_results[i];
+ }
+
+ past_results.clear();
+ return;
+}
+
+void load_results(const char *filename)
+{
+ ifstream file;
+ char line[4096];
+ char *c1;
+ struct result_bundle *bundle;
+ int first = 1;
+ unsigned int count = 0;
+ char* pathname;
+ int bundle_saved = 0;
+
+ pathname = get_param_directory(filename);
+
+ file.open(pathname, ios::in);
+ if (!file) {
+ cout << _("Cannot load from file") << " " << pathname << "\n";
+ return;
+ }
+
+ bundle = new struct result_bundle;
+
+ while (file) {
+ double d;
+ if (first) {
+ file.getline(line, 4096);
+ if (strlen(line)>0) {
+ sscanf(line, "%lf", &bundle->power);
+ if (bundle->power < min_power)
+ min_power = bundle->power;
+ }
+ first = 0;
+ continue;
+ }
+ file.getline(line, 4096);
+ if (strlen(line) < 3) {
+ int overflow_index;
+
+ bundle_saved = 1;
+ overflow_index = 50 + (rand() % MAX_KEEP);
+ if (past_results.size() >= MAX_PARAM) {
+ /* memory leak, must free old one first */
+ past_results[overflow_index] = bundle;
+ } else {
+ past_results.push_back(bundle);
+ }
+ bundle = new struct result_bundle;
+ first = 1;
+ count++;
+ continue;
+ }
+ c1 = strchr(line, '\t');
+ if (!c1)
+ continue;
+ *c1 = 0;
+ c1++;
+ sscanf(c1, "%lf", &d);
+ set_result_value(line, d, bundle);
+ }
+
+ if (bundle_saved == 0)
+ delete bundle;
+
+ file.close();
+ // '%i" is for count, do not translate
+ fprintf(stderr, _("Loaded %i prior measurements\n"), count);
+}
+
+void save_parameters(const char *filename)
+{
+ ofstream file;
+ char* pathname;
+
+// printf("result size is %i, #parameters is %i \n", (int)past_results.size(), (int)all_parameters.parameters.size());
+
+ if (!global_power_valid())
+ return;
+
+ pathname = get_param_directory(filename);
+
+ file.open(pathname, ios::out);
+ if (!file) {
+ cout << _("Cannot save to file") << " " << pathname << "\n";
+ return;
+ }
+
+ map<string, int>::iterator it;
+
+ for (it = param_index.begin(); it != param_index.end(); it++) {
+ int index;
+ index = it->second;
+ file << it->first << "\t" << setprecision(9) << all_parameters.parameters[index] << "\n";
+ }
+ file.close();
+}
+
+void load_parameters(const char *filename)
+{
+ ifstream file;
+ char line[4096];
+ char *c1;
+ char* pathname;
+
+ pathname = get_param_directory(filename);
+
+ file.open(pathname, ios::in);
+ if (!file) {
+ cout << _("Cannot load from file") << " " << pathname << "\n";
+ cout << _("File will be loaded after taking minimum number of measurement(s) with battery only \n");
+ return;
+ }
+
+ while (file) {
+ double d;
+ memset(line, 0, 4096);
+ file.getline(line, 4095);
+
+ c1 = strchr(line, '\t');
+ if (!c1)
+ continue;
+ *c1 = 0;
+ c1++;
+ sscanf(c1, "%lf", &d);
+
+
+ set_parameter_value(line, d);
+ }
+
+ file.close();
+}
diff --git a/src/perf/perf.cpp b/src/perf/perf.cpp
new file mode 100644
index 0000000..9ed0ba8
--- /dev/null
+++ b/src/perf/perf.cpp
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+
+#include <iostream>
+#include <fstream>
+
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+
+#include <fcntl.h>
+
+#include "perf_event.h"
+#include "perf.h"
+#include "../lib.h"
+#include "../display.h"
+
+struct pevent *perf_event::pevent;
+
+static int get_trace_type(const char *eventname)
+{
+ string str;
+ int this_trace;
+
+ str = read_sysfs_string("/sys/kernel/debug/tracing/events/%s/id",
+ eventname);
+ if (str.length() < 1)
+ return -1;
+
+ this_trace = strtoull(str.c_str(), NULL, 10);
+ return this_trace;
+}
+
+static inline int sys_perf_event_open(struct perf_event_attr *attr,
+ pid_t pid, int cpu, int group_fd,
+ unsigned long flags)
+{
+ attr->size = sizeof(*attr);
+ return syscall(__NR_perf_event_open, attr, pid, cpu,
+ group_fd, flags);
+}
+
+void perf_event::create_perf_event(char *eventname, int _cpu)
+{
+ struct perf_event_attr attr;
+ int ret;
+ int err;
+
+ struct {
+ __u64 count;
+ __u64 time_enabled;
+ __u64 time_running;
+ __u64 id;
+ } read_data;
+
+ if (perf_fd != -1)
+ clear();
+
+ memset(&attr, 0, sizeof(attr));
+
+ attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
+ PERF_FORMAT_TOTAL_TIME_RUNNING |
+ PERF_FORMAT_ID;
+
+ attr.sample_freq = 0;
+ attr.sample_period = 1;
+ attr.sample_type |= PERF_SAMPLE_RAW | PERF_SAMPLE_CPU | PERF_SAMPLE_TIME;
+
+ attr.mmap = 1;
+ attr.comm = 1;
+ attr.inherit = 0;
+ attr.disabled = 1;
+
+ attr.type = PERF_TYPE_TRACEPOINT;
+ attr.config = trace_type;
+
+ if (attr.config <= 0)
+ return;
+
+ perf_fd = sys_perf_event_open(&attr, -1, _cpu, -1, 0);
+
+ if (perf_fd < 0) {
+ err = errno;
+ reset_display();
+ if (err == EMFILE)
+ fprintf(stderr, _("Too many open files, please increase the limit of open file descriptors.\n"));
+ else {
+ fprintf(stderr, _("PowerTOP %s needs the kernel to support the 'perf' subsystem\n"), PACKAGE_VERSION);
+ fprintf(stderr, _("as well as support for trace points in the kernel:\n"));
+ fprintf(stderr, "CONFIG_PERF_EVENTS=y\nCONFIG_PERF_COUNTERS=y\nCONFIG_TRACEPOINTS=y\nCONFIG_TRACING=y\n");
+ }
+ exit(EXIT_FAILURE);
+ }
+ if (read(perf_fd, &read_data, sizeof(read_data)) == -1) {
+ reset_display();
+ perror("Unable to read perf file descriptor\n");
+ exit(-1);
+ }
+
+ fcntl(perf_fd, F_SETFL, O_NONBLOCK);
+
+ perf_mmap = mmap(NULL, (bufsize+1)*getpagesize(),
+ PROT_READ | PROT_WRITE, MAP_SHARED, perf_fd, 0);
+ if (perf_mmap == MAP_FAILED) {
+ fprintf(stderr, "failed to mmap with %d (%s)\n", errno, strerror(errno));
+ return;
+ }
+
+ ret = ioctl(perf_fd, PERF_EVENT_IOC_ENABLE, 0);
+
+ if (ret < 0) {
+ fprintf(stderr, "failed to enable perf \n");
+ }
+
+ pc = (perf_event_mmap_page *)perf_mmap;
+ data_mmap = (unsigned char *)perf_mmap + getpagesize();
+
+
+}
+
+void perf_event::set_event_name(const char *event_name)
+{
+ free(name);
+ name = strdup(event_name);
+ if (!name) {
+ fprintf(stderr, "failed to allocate event name\n");
+ return;
+ }
+
+ char *c;
+
+ c = strchr(name, ':');
+ if (c)
+ *c = '/';
+
+ trace_type = get_trace_type(name);
+}
+
+perf_event::~perf_event(void)
+{
+ free(name);
+
+ if (perf_event::pevent->ref_count == 1) {
+ pevent_free(perf_event::pevent);
+ perf_event::pevent = NULL;
+ clear();
+ } else
+ pevent_unref(perf_event::pevent);
+}
+
+void perf_event::set_cpu(int _cpu)
+{
+ cpu = _cpu;
+}
+
+static void allocate_pevent(void)
+{
+ if (!perf_event::pevent)
+ perf_event::pevent = pevent_alloc();
+ else
+ pevent_ref(perf_event::pevent);
+}
+
+perf_event::perf_event(const char *event_name, int _cpu, int buffer_size)
+{
+ allocate_pevent();
+ name = NULL;
+ perf_fd = -1;
+ bufsize = buffer_size;
+ cpu = _cpu;
+ perf_mmap = NULL;
+ trace_type = 0;
+ set_event_name(event_name);
+}
+
+perf_event::perf_event(void)
+{
+ allocate_pevent();
+ name = NULL;
+ perf_fd = -1;
+ bufsize = 128;
+ perf_mmap = NULL;
+ cpu = 0;
+ trace_type = 0;
+}
+
+void perf_event::start(void)
+{
+ create_perf_event(name, cpu);
+}
+
+void perf_event::stop(void)
+{
+ int ret;
+ ret = ioctl(perf_fd, PERF_EVENT_IOC_DISABLE, 0);
+ if (ret)
+ cout << "stop failing\n";
+}
+
+void perf_event::process(void *cookie)
+{
+ struct perf_event_header *header;
+
+ if (perf_fd < 0)
+ return;
+
+ while (pc->data_tail != pc->data_head ) {
+ while (pc->data_tail >= (unsigned int)bufsize * getpagesize())
+ pc->data_tail -= bufsize * getpagesize();
+
+ header = (struct perf_event_header *)( (unsigned char *)data_mmap + pc->data_tail);
+
+ if (header->size == 0)
+ break;
+
+ pc->data_tail += header->size;
+
+ while (pc->data_tail >= (unsigned int)bufsize * getpagesize())
+ pc->data_tail -= bufsize * getpagesize();
+
+ if (header->type == PERF_RECORD_SAMPLE)
+ handle_event(header, cookie);
+ }
+ pc->data_tail = pc->data_head;
+}
+
+void perf_event::clear(void)
+{
+ if (perf_mmap) {
+// memset(perf_mmap, 0, (bufsize)*getpagesize());
+ munmap(perf_mmap, (bufsize+1)*getpagesize());
+ perf_mmap = NULL;
+ }
+ if (perf_fd != -1)
+ close(perf_fd);
+ perf_fd = -1;
+}
diff --git a/src/perf/perf.h b/src/perf/perf.h
new file mode 100644
index 0000000..ee072ae
--- /dev/null
+++ b/src/perf/perf.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_PERF_H_
+#define _INCLUDE_GUARD_PERF_H_
+
+#include <iostream>
+
+
+extern "C" {
+ #include "../traceevent/event-parse.h"
+}
+
+
+using namespace std;
+
+class perf_event {
+protected:
+ int perf_fd;
+ void * perf_mmap;
+ void * data_mmap;
+ struct perf_event_mmap_page *pc;
+
+
+
+ int bufsize;
+ char *name;
+ int cpu;
+ void create_perf_event(char *eventname, int cpu);
+
+public:
+ unsigned int trace_type;
+
+ perf_event(void);
+ perf_event(const char *event_name, int cpu = 0, int buffer_size = 128);
+
+ virtual ~perf_event(void);
+
+
+ void set_event_name(const char *event_name);
+ void set_cpu(int cpu);
+
+ void start(void);
+ void stop(void);
+ void clear(void);
+
+ void process(void *cookie);
+
+ virtual void handle_event(struct perf_event_header *header, void *cookie) { };
+
+ static struct pevent *pevent;
+
+};
+
+#endif
diff --git a/src/perf/perf_bundle.cpp b/src/perf/perf_bundle.cpp
new file mode 100644
index 0000000..3d216ff
--- /dev/null
+++ b/src/perf/perf_bundle.cpp
@@ -0,0 +1,348 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <iostream>
+#include <malloc.h>
+#include <algorithm>
+#include <string.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#include "perf_bundle.h"
+#include "perf_event.h"
+#include "perf.h"
+
+#include "../cpu/cpu.h"
+
+#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)
+# define USE_DECLTYPE
+#endif
+
+class perf_bundle_event: public perf_event
+{
+public:
+ perf_bundle_event(void);
+ virtual void handle_event(struct perf_event_header *header, void *cookie);
+};
+
+perf_bundle_event::perf_bundle_event(void) : perf_event()
+{
+}
+
+
+void perf_bundle_event::handle_event(struct perf_event_header *header, void *cookie)
+{
+ unsigned char *buffer;
+ vector<void *> *vector;
+
+ buffer = (unsigned char *)malloc(header->size);
+ memcpy(buffer, header, header->size);
+
+#ifdef USE_DECLTYPE
+ vector = (decltype(vector))cookie;
+#else
+ vector = (typeof(vector))cookie;
+#endif
+ vector->push_back(buffer);
+}
+
+
+void perf_bundle::release(void)
+{
+ class perf_event *ev;
+ unsigned int i = 0;
+
+ for (i = 0; i < events.size(); i++) {
+ ev = events[i];
+ if (!ev)
+ continue;
+ ev->clear();
+ delete ev;
+ }
+ events.clear();
+
+ for (i = 0; i < event_names.size(); i++) {
+ free((void*)event_names[i]);
+ }
+ event_names.clear();
+
+ for(i = 0; i < records.size(); i++) {
+ free(records[i]);
+ }
+ records.clear();
+}
+
+static char * read_file(const char *file)
+{
+ char *buffer = NULL; /* quient gcc */
+ char buf[4096];
+ int len = 0;
+ int fd;
+ int r;
+
+ fd = open(file, O_RDONLY);
+ if (fd < 0)
+ exit(-1);
+
+ while((r = read(fd, buf, 4096)) > 0) {
+ if (len) {
+ char *tmp = (char *)realloc(buffer, len + r + 1);
+ if (!tmp)
+ free(buffer);
+ buffer = tmp;
+ } else
+ buffer = (char *)malloc(r + 1);
+ if (!buffer)
+ goto out;
+ memcpy(buffer + len, buf, r);
+ len += r;
+ buffer[len] = '\0';
+ }
+out:
+ close(fd);
+ return buffer;
+}
+
+static void parse_event_format(const char *event_name)
+{
+ char *tptr;
+ char *name = strdup(event_name);
+ char *sys = strtok_r(name, ":", &tptr);
+ char *event = strtok_r(NULL, ":", &tptr);
+ char *file;
+ char *buf;
+
+ file = (char *)malloc(strlen(sys) + strlen(event) +
+ strlen("/sys/kernel/debug/tracing/events////format") + 2);
+ sprintf(file, "/sys/kernel/debug/tracing/events/%s/%s/format", sys, event);
+
+ buf = read_file(file);
+ free(file);
+ if (!buf) {
+ free(name);
+ return;
+ }
+
+ pevent_parse_event(perf_event::pevent, buf, strlen(buf), sys);
+ free(name);
+ free(buf);
+}
+
+bool perf_bundle::add_event(const char *event_name)
+{
+ unsigned int i;
+ int event_added = false;
+ class perf_event *ev;
+
+
+ for (i = 0; i < all_cpus.size(); i++) {
+
+ if (!all_cpus[i])
+ continue;
+
+ ev = new class perf_bundle_event();
+
+ ev->set_event_name(event_name);
+ ev->set_cpu(i);
+
+ if ((int)ev->trace_type >= 0) {
+ if (event_names.find(ev->trace_type) == event_names.end()) {
+ event_names[ev->trace_type] = strdup(event_name);
+ parse_event_format(event_name);
+ }
+ events.push_back(ev);
+ event_added = true;
+ } else {
+ delete ev;
+ }
+ }
+ return event_added;
+}
+
+void perf_bundle::start(void)
+{
+ unsigned int i;
+ class perf_event *ev;
+
+ for (i = 0; i < events.size(); i++) {
+ ev = events[i];
+ if (!ev)
+ continue;
+ ev->start();
+ }
+}
+void perf_bundle::stop(void)
+{
+ unsigned int i;
+ class perf_event *ev;
+
+ for (i = 0; i < events.size(); i++) {
+ ev = events[i];
+ if (!ev)
+ continue;
+ ev->stop();
+ }
+}
+void perf_bundle::clear(void)
+{
+ unsigned int i;
+
+ class perf_event *ev;
+
+ for (i = 0; i < events.size(); i++) {
+ ev = events[i];
+ if (!ev)
+ continue;
+ ev->clear();
+ }
+
+ for (i = 0; i < records.size(); i++) {
+ free(records[i]);
+ }
+ records.resize(0);
+}
+
+
+struct trace_entry {
+ uint64_t time;
+ uint32_t cpu;
+ uint32_t res;
+ __u32 size;
+} __attribute__((packed));;
+
+
+struct perf_sample {
+ struct perf_event_header header;
+ struct trace_entry trace;
+ unsigned char data[0];
+} __attribute__((packed));
+
+static uint64_t timestamp(perf_event_header *event)
+{
+ struct perf_sample *sample;
+
+ if (event->type != PERF_RECORD_SAMPLE)
+ return 0;
+
+ sample = (struct perf_sample *)event;
+
+#if 0
+ int i;
+ unsigned char *x;
+
+ printf("header:\n");
+ printf(" type is %x \n", sample->header.type);
+ printf(" misc is %x \n", sample->header.misc);
+ printf(" size is %i \n", sample->header.size);
+ printf("sample:\n");
+ printf(" time is %llx \n", sample->trace.time);
+ printf(" cpu is %i / %x \n", sample->trace.cpu, sample->trace.cpu);
+ printf(" res is %i / %x \n", sample->trace.res, sample->trace.res);
+ printf(" size is %i / %x \n", sample->trace.size, sample->trace.size);
+ printf(" type is %i / %x \n", sample->trace.type, sample->trace.type);
+ printf(" flags is %i / %x \n", sample->trace.flags, sample->trace.flags);
+ printf(" p/c is %i / %x \n", sample->trace.preempt_count, sample->trace.preempt_count);
+ printf(" pid is %i / %x \n", sample->trace.pid, sample->trace.pid);
+ printf(" lock dept is %i / %x \n", sample->trace.lock_depth, sample->trace.lock_depth);
+
+ x = (unsigned char *)sample;
+ for (i = 0; i < sample->header.size; i++)
+ printf("%02x ", *(x+i));
+ printf("\n");
+#endif
+ return sample->trace.time;
+
+}
+
+static bool event_sort_function (void *i, void *j)
+{
+ struct perf_event_header *I, *J;
+
+ I = (struct perf_event_header *) i;
+ J = (struct perf_event_header *) j;
+ return (timestamp(I)<timestamp(J));
+}
+
+/*
+ * sample's PERF_SAMPLE_CPU cpu nr is a raw_smp_processor_id() by the
+ * time of perf_event_output(), which may differ from struct perf_event
+ * cpu, thus we need to fix sample->trace.cpu.
+ */
+static void fixup_sample_trace_cpu(struct perf_sample *sample)
+{
+ struct event_format *event;
+ struct pevent_record rec;
+ unsigned long long cpu_nr;
+ int type;
+ int ret;
+
+ rec.data = &sample->data;
+ type = pevent_data_type(perf_event::pevent, &rec);
+ event = pevent_find_event(perf_event::pevent, type);
+ if (!event)
+ return;
+ /** don't touch trace if event does not contain cpu_id field*/
+ ret = pevent_get_field_val(NULL, event, "cpu_id", &rec, &cpu_nr, 0);
+ if (ret < 0)
+ return;
+ sample->trace.cpu = cpu_nr;
+}
+
+void perf_bundle::process(void)
+{
+ unsigned int i;
+ class perf_event *ev;
+
+ /* fixme: reserve enough space in the array in one go */
+ for (i = 0; i < events.size(); i++) {
+ ev = events[i];
+ if (!ev)
+ continue;
+ ev->process(&records);
+ }
+ sort(records.begin(), records.end(), event_sort_function);
+
+ for (i = 0; i < records.size(); i++) {
+ struct perf_sample *sample;
+
+ sample = (struct perf_sample *)records[i];
+ if (!sample)
+ continue;
+
+ if (sample->header.type != PERF_RECORD_SAMPLE)
+ continue;
+
+ fixup_sample_trace_cpu(sample);
+ handle_trace_point(&sample->data, sample->trace.cpu, sample->trace.time);
+ }
+}
+
+void perf_bundle::handle_trace_point(void *trace, int cpu, uint64_t time)
+{
+ printf("UH OH... abstract handle_trace_point called\n");
+}
diff --git a/src/perf/perf_bundle.h b/src/perf/perf_bundle.h
new file mode 100644
index 0000000..ec50744
--- /dev/null
+++ b/src/perf/perf_bundle.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_PERF_BUNDLE_H_
+#define _INCLUDE_GUARD_PERF_BUNDLE_H_
+
+#include <iostream>
+#include <vector>
+#include <map>
+
+using namespace std;
+
+#include "perf.h"
+class perf_event;
+
+
+class perf_bundle {
+protected:
+ vector<class perf_event *> events;
+ std::map<int, char*> event_names;
+public:
+ vector<void *> records;
+ virtual ~perf_bundle() {};
+
+ virtual void release(void);
+ bool add_event(const char *event_name);
+
+ void start(void);
+ void stop(void);
+ void clear(void);
+
+ void process(void);
+
+ virtual void handle_trace_point(void *trace, int cpu = 0, uint64_t time = 0);
+};
+
+
+#endif
diff --git a/src/perf/perf_event.h b/src/perf/perf_event.h
new file mode 100644
index 0000000..92a38b8
--- /dev/null
+++ b/src/perf/perf_event.h
@@ -0,0 +1,910 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+/*
+ * Performance events:
+ *
+ * Copyright (C) 2008-2009, Thomas Gleixner <tglx@linutronix.de>
+ * Copyright (C) 2008-2009, Red Hat, Inc., Ingo Molnar
+ * Copyright (C) 2008-2009, Red Hat, Inc., Peter Zijlstra
+ *
+ * Data type definitions, declarations, prototypes.
+ *
+ * Started by: Thomas Gleixner and Ingo Molnar
+ *
+ * For licencing details see kernel-base/COPYING
+ */
+#ifndef _LINUX_PERF_EVENT_H
+#define _LINUX_PERF_EVENT_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <asm/byteorder.h>
+#include <sys/syscall.h>
+
+
+/*
+ * User-space ABI bits:
+ */
+
+/*
+ * attr.type
+ */
+enum perf_type_id {
+ PERF_TYPE_HARDWARE = 0,
+ PERF_TYPE_SOFTWARE = 1,
+ PERF_TYPE_TRACEPOINT = 2,
+ PERF_TYPE_HW_CACHE = 3,
+ PERF_TYPE_RAW = 4,
+
+ PERF_TYPE_MAX, /* non-ABI */
+};
+
+/*
+ * Generalized performance event event_id types, used by the
+ * attr.event_id parameter of the sys_perf_event_open()
+ * syscall:
+ */
+enum perf_hw_id {
+ /*
+ * Common hardware events, generalized by the kernel:
+ */
+ PERF_COUNT_HW_CPU_CYCLES = 0,
+ PERF_COUNT_HW_INSTRUCTIONS = 1,
+ PERF_COUNT_HW_CACHE_REFERENCES = 2,
+ PERF_COUNT_HW_CACHE_MISSES = 3,
+ PERF_COUNT_HW_BRANCH_INSTRUCTIONS = 4,
+ PERF_COUNT_HW_BRANCH_MISSES = 5,
+ PERF_COUNT_HW_BUS_CYCLES = 6,
+
+ PERF_COUNT_HW_MAX, /* non-ABI */
+};
+
+/*
+ * Generalized hardware cache events:
+ *
+ * { L1-D, L1-I, LLC, ITLB, DTLB, BPU } x
+ * { read, write, prefetch } x
+ * { accesses, misses }
+ */
+enum perf_hw_cache_id {
+ PERF_COUNT_HW_CACHE_L1D = 0,
+ PERF_COUNT_HW_CACHE_L1I = 1,
+ PERF_COUNT_HW_CACHE_LL = 2,
+ PERF_COUNT_HW_CACHE_DTLB = 3,
+ PERF_COUNT_HW_CACHE_ITLB = 4,
+ PERF_COUNT_HW_CACHE_BPU = 5,
+
+ PERF_COUNT_HW_CACHE_MAX, /* non-ABI */
+};
+
+enum perf_hw_cache_op_id {
+ PERF_COUNT_HW_CACHE_OP_READ = 0,
+ PERF_COUNT_HW_CACHE_OP_WRITE = 1,
+ PERF_COUNT_HW_CACHE_OP_PREFETCH = 2,
+
+ PERF_COUNT_HW_CACHE_OP_MAX, /* non-ABI */
+};
+
+enum perf_hw_cache_op_result_id {
+ PERF_COUNT_HW_CACHE_RESULT_ACCESS = 0,
+ PERF_COUNT_HW_CACHE_RESULT_MISS = 1,
+
+ PERF_COUNT_HW_CACHE_RESULT_MAX, /* non-ABI */
+};
+
+/*
+ * Special "software" events provided by the kernel, even if the hardware
+ * does not support performance events. These events measure various
+ * physical and sw events of the kernel (and allow the profiling of them as
+ * well):
+ */
+enum perf_sw_ids {
+ PERF_COUNT_SW_CPU_CLOCK = 0,
+ PERF_COUNT_SW_TASK_CLOCK = 1,
+ PERF_COUNT_SW_PAGE_FAULTS = 2,
+ PERF_COUNT_SW_CONTEXT_SWITCHES = 3,
+ PERF_COUNT_SW_CPU_MIGRATIONS = 4,
+ PERF_COUNT_SW_PAGE_FAULTS_MIN = 5,
+ PERF_COUNT_SW_PAGE_FAULTS_MAJ = 6,
+
+ PERF_COUNT_SW_MAX, /* non-ABI */
+};
+
+/*
+ * Bits that can be set in attr.sample_type to request information
+ * in the overflow packets.
+ */
+enum perf_event_sample_format {
+ PERF_SAMPLE_IP = 1U << 0,
+ PERF_SAMPLE_TID = 1U << 1,
+ PERF_SAMPLE_TIME = 1U << 2,
+ PERF_SAMPLE_ADDR = 1U << 3,
+ PERF_SAMPLE_READ = 1U << 4,
+ PERF_SAMPLE_CALLCHAIN = 1U << 5,
+ PERF_SAMPLE_ID = 1U << 6,
+ PERF_SAMPLE_CPU = 1U << 7,
+ PERF_SAMPLE_PERIOD = 1U << 8,
+ PERF_SAMPLE_STREAM_ID = 1U << 9,
+ PERF_SAMPLE_RAW = 1U << 10,
+
+ PERF_SAMPLE_MAX = 1U << 11, /* non-ABI */
+};
+
+/*
+ * The format of the data returned by read() on a perf event fd,
+ * as specified by attr.read_format:
+ *
+ * struct read_format {
+ * { u64 value;
+ * { u64 time_enabled; } && PERF_FORMAT_ENABLED
+ * { u64 time_running; } && PERF_FORMAT_RUNNING
+ * { u64 id; } && PERF_FORMAT_ID
+ * } && !PERF_FORMAT_GROUP
+ *
+ * { u64 nr;
+ * { u64 time_enabled; } && PERF_FORMAT_ENABLED
+ * { u64 time_running; } && PERF_FORMAT_RUNNING
+ * { u64 value;
+ * { u64 id; } && PERF_FORMAT_ID
+ * } cntr[nr];
+ * } && PERF_FORMAT_GROUP
+ * };
+ */
+enum perf_event_read_format {
+ PERF_FORMAT_TOTAL_TIME_ENABLED = 1U << 0,
+ PERF_FORMAT_TOTAL_TIME_RUNNING = 1U << 1,
+ PERF_FORMAT_ID = 1U << 2,
+ PERF_FORMAT_GROUP = 1U << 3,
+
+ PERF_FORMAT_MAX = 1U << 4, /* non-ABI */
+};
+
+#define PERF_ATTR_SIZE_VER0 64 /* sizeof first published struct */
+
+/*
+ * Hardware event_id to monitor via a performance monitoring event:
+ */
+struct perf_event_attr {
+
+ /*
+ * Major type: hardware/software/tracepoint/etc.
+ */
+ __u32 type;
+
+ /*
+ * Size of the attr structure, for fwd/bwd compat.
+ */
+ __u32 size;
+
+ /*
+ * Type specific configuration information.
+ */
+ __u64 config;
+
+ union {
+ __u64 sample_period;
+ __u64 sample_freq;
+ };
+
+ __u64 sample_type;
+ __u64 read_format;
+
+ __u64 disabled : 1, /* off by default */
+ inherit : 1, /* children inherit it */
+ pinned : 1, /* must always be on PMU */
+ exclusive : 1, /* only group on PMU */
+ exclude_user : 1, /* don't count user */
+ exclude_kernel : 1, /* ditto kernel */
+ exclude_hv : 1, /* ditto hypervisor */
+ exclude_idle : 1, /* don't count when idle */
+ mmap : 1, /* include mmap data */
+ comm : 1, /* include comm data */
+ freq : 1, /* use freq, not period */
+ inherit_stat : 1, /* per task counts */
+ enable_on_exec : 1, /* next exec enables */
+ task : 1, /* trace fork/exit */
+ watermark : 1, /* wakeup_watermark */
+
+ __reserved_1 : 49;
+
+ union {
+ __u32 wakeup_events; /* wakeup every n events */
+ __u32 wakeup_watermark; /* bytes before wakeup */
+ };
+ __u32 __reserved_2;
+
+ __u64 __reserved_3;
+};
+
+/*
+ * Ioctls that can be done on a perf event fd:
+ */
+#define PERF_EVENT_IOC_ENABLE _IO ('$', 0)
+#define PERF_EVENT_IOC_DISABLE _IO ('$', 1)
+#define PERF_EVENT_IOC_REFRESH _IO ('$', 2)
+#define PERF_EVENT_IOC_RESET _IO ('$', 3)
+#define PERF_EVENT_IOC_PERIOD _IOW('$', 4, u64)
+#define PERF_EVENT_IOC_SET_OUTPUT _IO ('$', 5)
+
+enum perf_event_ioc_flags {
+ PERF_IOC_FLAG_GROUP = 1U << 0,
+};
+
+/*
+ * Structure of the page that can be mapped via mmap
+ */
+struct perf_event_mmap_page {
+ __u32 version; /* version number of this structure */
+ __u32 compat_version; /* lowest version this is compat with */
+
+ /*
+ * Bits needed to read the hw events in user-space.
+ *
+ * u32 seq;
+ * s64 count;
+ *
+ * do {
+ * seq = pc->lock;
+ *
+ * barrier()
+ * if (pc->index) {
+ * count = pmc_read(pc->index - 1);
+ * count += pc->offset;
+ * } else
+ * goto regular_read;
+ *
+ * barrier();
+ * } while (pc->lock != seq);
+ *
+ * NOTE: for obvious reason this only works on self-monitoring
+ * processes.
+ */
+ __u32 lock; /* seqlock for synchronization */
+ __u32 index; /* hardware event identifier */
+ __s64 offset; /* add to hardware event value */
+ __u64 time_enabled; /* time event active */
+ __u64 time_running; /* time event on cpu */
+
+ /*
+ * Hole for extension of the self monitor capabilities
+ */
+
+ __u64 __reserved[123]; /* align to 1k */
+
+ /*
+ * Control data for the mmap() data buffer.
+ *
+ * User-space reading the @data_head value should issue an rmb(), on
+ * SMP capable platforms, after reading this value -- see
+ * perf_event_wakeup().
+ *
+ * When the mapping is PROT_WRITE the @data_tail value should be
+ * written by userspace to reflect the last read data. In this case
+ * the kernel will not over-write unread data.
+ */
+ __u64 data_head; /* head in the data section */
+ __u64 data_tail; /* user-space written tail */
+};
+
+#define PERF_RECORD_MISC_CPUMODE_MASK (3 << 0)
+#define PERF_RECORD_MISC_CPUMODE_UNKNOWN (0 << 0)
+#define PERF_RECORD_MISC_KERNEL (1 << 0)
+#define PERF_RECORD_MISC_USER (2 << 0)
+#define PERF_RECORD_MISC_HYPERVISOR (3 << 0)
+
+struct perf_event_header {
+ __u32 type;
+ __u16 misc;
+ __u16 size;
+};
+
+enum perf_event_type {
+
+ /*
+ * The MMAP events record the PROT_EXEC mappings so that we can
+ * correlate userspace IPs to code. They have the following structure:
+ *
+ * struct {
+ * struct perf_event_header header;
+ *
+ * u32 pid, tid;
+ * u64 addr;
+ * u64 len;
+ * u64 pgoff;
+ * char filename[];
+ * };
+ */
+ PERF_RECORD_MMAP = 1,
+
+ /*
+ * struct {
+ * struct perf_event_header header;
+ * u64 id;
+ * u64 lost;
+ * };
+ */
+ PERF_RECORD_LOST = 2,
+
+ /*
+ * struct {
+ * struct perf_event_header header;
+ *
+ * u32 pid, tid;
+ * char comm[];
+ * };
+ */
+ PERF_RECORD_COMM = 3,
+
+ /*
+ * struct {
+ * struct perf_event_header header;
+ * u32 pid, ppid;
+ * u32 tid, ptid;
+ * u64 time;
+ * };
+ */
+ PERF_RECORD_EXIT = 4,
+
+ /*
+ * struct {
+ * struct perf_event_header header;
+ * u64 time;
+ * u64 id;
+ * u64 stream_id;
+ * };
+ */
+ PERF_RECORD_THROTTLE = 5,
+ PERF_RECORD_UNTHROTTLE = 6,
+
+ /*
+ * struct {
+ * struct perf_event_header header;
+ * u32 pid, ppid;
+ * u32 tid, ptid;
+ * u64 time;
+ * };
+ */
+ PERF_RECORD_FORK = 7,
+
+ /*
+ * struct {
+ * struct perf_event_header header;
+ * u32 pid, tid;
+ *
+ * struct read_format values;
+ * };
+ */
+ PERF_RECORD_READ = 8,
+
+ /*
+ * struct {
+ * struct perf_event_header header;
+ *
+ * { u64 ip; } && PERF_SAMPLE_IP
+ * { u32 pid, tid; } && PERF_SAMPLE_TID
+ * { u64 time; } && PERF_SAMPLE_TIME
+ * { u64 addr; } && PERF_SAMPLE_ADDR
+ * { u64 id; } && PERF_SAMPLE_ID
+ * { u64 stream_id;} && PERF_SAMPLE_STREAM_ID
+ * { u32 cpu, res; } && PERF_SAMPLE_CPU
+ * { u64 period; } && PERF_SAMPLE_PERIOD
+ *
+ * { struct read_format values; } && PERF_SAMPLE_READ
+ *
+ * { u64 nr,
+ * u64 ips[nr]; } && PERF_SAMPLE_CALLCHAIN
+ *
+ * #
+ * # The RAW record below is opaque data wrt the ABI
+ * #
+ * # That is, the ABI doesn't make any promises wrt to
+ * # the stability of its content, it may vary depending
+ * # on event, hardware, kernel version and phase of
+ * # the moon.
+ * #
+ * # In other words, PERF_SAMPLE_RAW contents are not an ABI.
+ * #
+ *
+ * { u32 size;
+ * char data[size];}&& PERF_SAMPLE_RAW
+ * };
+ */
+ PERF_RECORD_SAMPLE = 9,
+
+ PERF_RECORD_MAX, /* non-ABI */
+};
+
+enum perf_callchain_context {
+ PERF_CONTEXT_HV = (__u64)-32,
+ PERF_CONTEXT_KERNEL = (__u64)-128,
+ PERF_CONTEXT_USER = (__u64)-512,
+
+ PERF_CONTEXT_GUEST = (__u64)-2048,
+ PERF_CONTEXT_GUEST_KERNEL = (__u64)-2176,
+ PERF_CONTEXT_GUEST_USER = (__u64)-2560,
+
+ PERF_CONTEXT_MAX = (__u64)-4095,
+};
+
+#define PERF_FLAG_FD_NO_GROUP (1U << 0)
+#define PERF_FLAG_FD_OUTPUT (1U << 1)
+
+#ifdef __KERNEL__
+/*
+ * Kernel-internal data types and definitions:
+ */
+
+#ifdef CONFIG_PERF_EVENTS
+# include <asm/perf_event.h>
+#endif
+
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/rculist.h>
+#include <linux/rcupdate.h>
+#include <linux/spinlock.h>
+#include <linux/hrtimer.h>
+#include <linux/fs.h>
+#include <linux/pid_namespace.h>
+#include <linux/workqueue.h>
+#include <asm/atomic.h>
+
+#define PERF_MAX_STACK_DEPTH 255
+
+struct perf_callchain_entry {
+ __u64 nr;
+ __u64 ip[PERF_MAX_STACK_DEPTH];
+};
+
+struct perf_raw_record {
+ u32 size;
+ void *data;
+};
+
+struct task_struct;
+
+/**
+ * struct hw_perf_event - performance event hardware details:
+ */
+struct hw_perf_event {
+#ifdef CONFIG_PERF_EVENTS
+ union {
+ struct { /* hardware */
+ u64 config;
+ unsigned long config_base;
+ unsigned long event_base;
+ int idx;
+ };
+ struct { /* software */
+ s64 remaining;
+ struct hrtimer hrtimer;
+ };
+ };
+ atomic64_t prev_count;
+ u64 sample_period;
+ u64 last_period;
+ atomic64_t period_left;
+ u64 interrupts;
+
+ u64 freq_count;
+ u64 freq_interrupts;
+ u64 freq_stamp;
+#endif
+};
+
+struct perf_event;
+
+/**
+ * struct pmu - generic performance monitoring unit
+ */
+struct pmu {
+ int (*enable) (struct perf_event *event);
+ void (*disable) (struct perf_event *event);
+ void (*read) (struct perf_event *event);
+ void (*unthrottle) (struct perf_event *event);
+};
+
+/**
+ * enum perf_event_active_state - the states of a event
+ */
+enum perf_event_active_state {
+ PERF_EVENT_STATE_ERROR = -2,
+ PERF_EVENT_STATE_OFF = -1,
+ PERF_EVENT_STATE_INACTIVE = 0,
+ PERF_EVENT_STATE_ACTIVE = 1,
+};
+
+struct file;
+
+struct perf_mmap_data {
+ struct rcu_head rcu_head;
+#ifdef CONFIG_PERF_USE_VMALLOC
+ struct work_struct work;
+#endif
+ int data_order;
+ int nr_pages; /* nr of data pages */
+ int writable; /* are we writable */
+ int nr_locked; /* nr pages mlocked */
+
+ atomic_t poll; /* POLL_ for wakeups */
+ atomic_t events; /* event_id limit */
+
+ atomic_long_t head; /* write position */
+ atomic_long_t done_head; /* completed head */
+
+ atomic_t lock; /* concurrent writes */
+ atomic_t wakeup; /* needs a wakeup */
+ atomic_t lost; /* nr records lost */
+
+ long watermark; /* wakeup watermark */
+
+ struct perf_event_mmap_page *user_page;
+ void *data_pages[0];
+};
+
+struct perf_pending_entry {
+ struct perf_pending_entry *next;
+ void (*func)(struct perf_pending_entry *);
+};
+
+/**
+ * struct perf_event - performance event kernel representation:
+ */
+struct perf_event {
+#ifdef CONFIG_PERF_EVENTS
+ struct list_head group_entry;
+ struct list_head event_entry;
+ struct list_head sibling_list;
+ int nr_siblings;
+ struct perf_event *group_leader;
+ struct perf_event *output;
+ const struct pmu *pmu;
+
+ enum perf_event_active_state state;
+ atomic64_t count;
+
+ /*
+ * These are the total time in nanoseconds that the event
+ * has been enabled (i.e. eligible to run, and the task has
+ * been scheduled in, if this is a per-task event)
+ * and running (scheduled onto the CPU), respectively.
+ *
+ * They are computed from tstamp_enabled, tstamp_running and
+ * tstamp_stopped when the event is in INACTIVE or ACTIVE state.
+ */
+ u64 total_time_enabled;
+ u64 total_time_running;
+
+ /*
+ * These are timestamps used for computing total_time_enabled
+ * and total_time_running when the event is in INACTIVE or
+ * ACTIVE state, measured in nanoseconds from an arbitrary point
+ * in time.
+ * tstamp_enabled: the notional time when the event was enabled
+ * tstamp_running: the notional time when the event was scheduled on
+ * tstamp_stopped: in INACTIVE state, the notional time when the
+ * event was scheduled off.
+ */
+ u64 tstamp_enabled;
+ u64 tstamp_running;
+ u64 tstamp_stopped;
+
+ struct perf_event_attr attr;
+ struct hw_perf_event hw;
+
+ struct perf_event_context *ctx;
+ struct file *filp;
+
+ /*
+ * These accumulate total time (in nanoseconds) that children
+ * events have been enabled and running, respectively.
+ */
+ atomic64_t child_total_time_enabled;
+ atomic64_t child_total_time_running;
+
+ /*
+ * Protect attach/detach and child_list:
+ */
+ struct mutex child_mutex;
+ struct list_head child_list;
+ struct perf_event *parent;
+
+ int oncpu;
+ int cpu;
+
+ struct list_head owner_entry;
+ struct task_struct *owner;
+
+ /* mmap bits */
+ struct mutex mmap_mutex;
+ atomic_t mmap_count;
+ struct perf_mmap_data *data;
+
+ /* poll related */
+ wait_queue_head_t waitq;
+ struct fasync_struct *fasync;
+
+ /* delayed work for NMIs and such */
+ int pending_wakeup;
+ int pending_kill;
+ int pending_disable;
+ struct perf_pending_entry pending;
+
+ atomic_t event_limit;
+
+ void (*destroy)(struct perf_event *);
+ struct rcu_head rcu_head;
+
+ struct pid_namespace *ns;
+ u64 id;
+#endif
+};
+
+/**
+ * struct perf_event_context - event context structure
+ *
+ * Used as a container for task events and CPU events as well:
+ */
+struct perf_event_context {
+ /*
+ * Protect the states of the events in the list,
+ * nr_active, and the list:
+ */
+ spinlock_t lock;
+ /*
+ * Protect the list of events. Locking either mutex or lock
+ * is sufficient to ensure the list doesn't change; to change
+ * the list you need to lock both the mutex and the spinlock.
+ */
+ struct mutex mutex;
+
+ struct list_head group_list;
+ struct list_head event_list;
+ int nr_events;
+ int nr_active;
+ int is_active;
+ int nr_stat;
+ atomic_t refcount;
+ struct task_struct *task;
+
+ /*
+ * Context clock, runs when context enabled.
+ */
+ u64 time;
+ u64 timestamp;
+
+ /*
+ * These fields let us detect when two contexts have both
+ * been cloned (inherited) from a common ancestor.
+ */
+ struct perf_event_context *parent_ctx;
+ u64 parent_gen;
+ u64 generation;
+ int pin_count;
+ struct rcu_head rcu_head;
+};
+
+/**
+ * struct perf_event_cpu_context - per cpu event context structure
+ */
+struct perf_cpu_context {
+ struct perf_event_context ctx;
+ struct perf_event_context *task_ctx;
+ int active_oncpu;
+ int max_pertask;
+ int exclusive;
+
+ /*
+ * Recursion avoidance:
+ *
+ * task, softirq, irq, nmi context
+ */
+ int recursion[4];
+};
+
+struct perf_output_handle {
+ struct perf_event *event;
+ struct perf_mmap_data *data;
+ unsigned long head;
+ unsigned long offset;
+ int nmi;
+ int sample;
+ int locked;
+ unsigned long flags;
+};
+
+#ifdef CONFIG_PERF_EVENTS
+
+/*
+ * Set by architecture code:
+ */
+extern int perf_max_events;
+
+extern const struct pmu *hw_perf_event_init(struct perf_event *event);
+
+extern void perf_event_task_sched_in(struct task_struct *task, int cpu);
+extern void perf_event_task_sched_out(struct task_struct *task,
+ struct task_struct *next, int cpu);
+extern void perf_event_task_tick(struct task_struct *task, int cpu);
+extern int perf_event_init_task(struct task_struct *child);
+extern void perf_event_exit_task(struct task_struct *child);
+extern void perf_event_free_task(struct task_struct *task);
+extern void set_perf_event_pending(void);
+extern void perf_event_do_pending(void);
+extern void perf_event_print_debug(void);
+extern void __perf_disable(void);
+extern bool __perf_enable(void);
+extern void perf_disable(void);
+extern void perf_enable(void);
+extern int perf_event_task_disable(void);
+extern int perf_event_task_enable(void);
+extern int hw_perf_group_sched_in(struct perf_event *group_leader,
+ struct perf_cpu_context *cpuctx,
+ struct perf_event_context *ctx, int cpu);
+extern void perf_event_update_userpage(struct perf_event *event);
+
+struct perf_sample_data {
+ u64 type;
+
+ u64 ip;
+ struct {
+ u32 pid;
+ u32 tid;
+ } tid_entry;
+ u64 time;
+ u64 addr;
+ u64 id;
+ u64 stream_id;
+ struct {
+ u32 cpu;
+ u32 reserved;
+ } cpu_entry;
+ u64 period;
+ struct perf_callchain_entry *callchain;
+ struct perf_raw_record *raw;
+};
+
+extern void perf_output_sample(struct perf_output_handle *handle,
+ struct perf_event_header *header,
+ struct perf_sample_data *data,
+ struct perf_event *event);
+extern void perf_prepare_sample(struct perf_event_header *header,
+ struct perf_sample_data *data,
+ struct perf_event *event,
+ struct pt_regs *regs);
+
+extern int perf_event_overflow(struct perf_event *event, int nmi,
+ struct perf_sample_data *data,
+ struct pt_regs *regs);
+
+/*
+ * Return 1 for a software event, 0 for a hardware event
+ */
+static inline int is_software_event(struct perf_event *event)
+{
+ return (event->attr.type != PERF_TYPE_RAW) &&
+ (event->attr.type != PERF_TYPE_HARDWARE) &&
+ (event->attr.type != PERF_TYPE_HW_CACHE);
+}
+
+extern atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX];
+
+extern void __perf_sw_event(u32, u64, int, struct pt_regs *, u64);
+
+static inline void
+perf_sw_event(u32 event_id, u64 nr, int nmi, struct pt_regs *regs, u64 addr)
+{
+ if (atomic_read(&perf_swevent_enabled[event_id]))
+ __perf_sw_event(event_id, nr, nmi, regs, addr);
+}
+
+extern void __perf_event_mmap(struct vm_area_struct *vma);
+
+static inline void perf_event_mmap(struct vm_area_struct *vma)
+{
+ if (vma->vm_flags & VM_EXEC)
+ __perf_event_mmap(vma);
+}
+
+extern void perf_event_comm(struct task_struct *tsk);
+extern void perf_event_fork(struct task_struct *tsk);
+
+extern struct perf_callchain_entry *perf_callchain(struct pt_regs *regs);
+
+extern int sysctl_perf_event_paranoid;
+extern int sysctl_perf_event_mlock;
+extern int sysctl_perf_event_sample_rate;
+
+extern void perf_event_init(void);
+extern void perf_tp_event(int event_id, u64 addr, u64 count,
+ void *record, int entry_size);
+
+#ifndef perf_misc_flags
+#define perf_misc_flags(regs) (user_mode(regs) ? PERF_RECORD_MISC_USER : \
+ PERF_RECORD_MISC_KERNEL)
+#define perf_instruction_pointer(regs) instruction_pointer(regs)
+#endif
+
+extern int perf_output_begin(struct perf_output_handle *handle,
+ struct perf_event *event, unsigned int size,
+ int nmi, int sample);
+extern void perf_output_end(struct perf_output_handle *handle);
+extern void perf_output_copy(struct perf_output_handle *handle,
+ const void *buf, unsigned int len);
+#else
+static inline void
+perf_event_task_sched_in(struct task_struct *task, int cpu) { }
+static inline void
+perf_event_task_sched_out(struct task_struct *task,
+ struct task_struct *next, int cpu) { }
+static inline void
+perf_event_task_tick(struct task_struct *task, int cpu) { }
+static inline int perf_event_init_task(struct task_struct *child) { return 0; }
+static inline void perf_event_exit_task(struct task_struct *child) { }
+static inline void perf_event_free_task(struct task_struct *task) { }
+static inline void perf_event_do_pending(void) { }
+static inline void perf_event_print_debug(void) { }
+static inline void perf_disable(void) { }
+static inline void perf_enable(void) { }
+static inline int perf_event_task_disable(void) { return -EINVAL; }
+static inline int perf_event_task_enable(void) { return -EINVAL; }
+
+static inline void
+perf_sw_event(u32 event_id, u64 nr, int nmi,
+ struct pt_regs *regs, u64 addr) { }
+
+static inline void perf_event_mmap(struct vm_area_struct *vma) { }
+static inline void perf_event_comm(struct task_struct *tsk) { }
+static inline void perf_event_fork(struct task_struct *tsk) { }
+static inline void perf_event_init(void) { }
+
+#endif
+
+#define perf_output_put(handle, x) \
+ perf_output_copy((handle), &(x), sizeof(x))
+
+#endif /* __KERNEL__ */
+
+
+#if 0
+/*
+ * trace_flag_type is an enumeration that holds different
+ * states when a trace occurs. These are:
+ * IRQS_OFF - interrupts were disabled
+ * IRQS_NOSUPPORT - arch does not support irqs_disabled_flags
+ * NEED_RESCED - reschedule is requested
+ * HARDIRQ - inside an interrupt handler
+ * SOFTIRQ - inside a softirq handler
+ */
+enum trace_flag_type {
+ TRACE_FLAG_IRQS_OFF = 0x01,
+ TRACE_FLAG_IRQS_NOSUPPORT = 0x02,
+ TRACE_FLAG_NEED_RESCHED = 0x04,
+ TRACE_FLAG_HARDIRQ = 0x08,
+ TRACE_FLAG_SOFTIRQ = 0x10,
+};
+#endif
+
+#endif /* _LINUX_PERF_EVENT_H */
diff --git a/src/powertop.css b/src/powertop.css
new file mode 100644
index 0000000..daa20c5
--- /dev/null
+++ b/src/powertop.css
@@ -0,0 +1,263 @@
+<!DOCTYPE html>
+<html lang='en'>
+<head>
+<title>PowerTOP report</title>
+<meta http-equiv='content-type' content='text/html;charset=utf-8'>
+
+<script type='text/javascript'>
+
+var powertop = {
+ blocks: {
+ summary: 'Summary',
+ cpuidle: 'CPU Idle',
+ cpufreq: 'CPU Frequency',
+ software: 'Software Info',
+ devinfo: 'Device Info',
+ tuning: 'Tuning',
+ ahci: 'AHCI'
+ },
+ cadd: function(idx, c){
+ var el = document.getElementById(idx);
+ if (el) {
+ var cn = el.className;
+ if (cn.indexOf(c) != -1)
+ return;
+ cn += ' ' + c;
+ el.className = cn;
+ }
+ },
+ crm: function(id, c){
+ var el = document.getElementById(id);
+ if (el) {
+ var cn = el.className
+ while (cn.indexOf(' ' + c) != -1)
+ cn = cn.replace(' ' + c,'');
+ el.className = cn;
+ }
+ },
+ newbutton: function(id, txt) {
+ var x = document.createElement('div');
+ x.id = id + '_button';
+ x.className = 'nav_button';
+ x.textContent = txt;
+ x.innerText = txt;
+ x.onclick = function() { powertop.toggle(id); };
+ return x;
+ },
+ setupbuttons: function() {
+ var t = document.getElementById('main_menu');
+ if (t) {
+ for (var b in powertop.blocks) {
+ t.appendChild(powertop.newbutton(b, powertop.blocks[b]));
+ }
+ t.appendChild(powertop.newbutton('all', 'All'));
+ }
+ },
+ toggle: function(b) {
+ powertop.baseall();
+ if (b == 'all') {
+ for (var c in powertop.blocks) {
+ powertop.crm(c, 'hide');
+ }
+ } else {
+ powertop.crm(b, 'hide');
+ }
+ powertop.cadd(b + '_button', 'pressed');
+ },
+ baseall: function() {
+ for (var b in powertop.blocks) {
+ powertop.cadd(b, 'hide');
+ powertop.crm(b + '_button', 'pressed');
+ }
+ powertop.cadd('all', 'hide');
+ powertop.crm('all_button', 'pressed');
+ },
+ onload: function() {
+ powertop.setupbuttons();
+ powertop.toggle('summary');
+ }
+}
+</script>
+
+<style type='text/css'>
+/* General CSS */
+*{
+ margin:0px;
+ padding:0px;
+ width: auto;
+}
+
+body {
+ background-color: #eee; /* Background color */
+ color: #222; /* Font color */
+ font-family: Helvetica;
+ font-size: 14px;
+}
+
+#main_container{
+ margin: 2px auto;
+}
+
+/* Top logo & system table css */
+#main_header{
+ min-width: 960px;
+}
+
+img.pwtop_logo{
+ float:left;
+ height:40%;
+ width: 40%;
+ padding:20px;
+}
+
+.sys_info
+{
+ float: right;
+ height:116px;
+ width:450px;
+ font-size: 12px;
+ text-align: left;
+}
+
+th{
+ text-align: left;
+}
+
+/* CSS Main Content */
+
+.content_title
+{
+ color: #296629;
+ padding:0px;
+ margin:2px;
+}
+
+#chart_div{
+ float: left;
+}
+
+.small
+{
+ font-size: 10px;
+}
+
+table.emphasis2
+{
+ font-size: 13px;
+ max-width:95%;
+}
+
+
+th.emph_title {
+ padding:5px;
+}
+
+tr.emph1:nth-child(odd) {
+ background: #ffffff;
+}
+
+tr.emph1:nth-child(even) {
+ background: #ebebeb;
+}
+
+tr.tune:nth-child(odd) {
+ background: #fffcfc;
+}
+tr.tune:nth-child(even) {
+ background: #fff0f0;
+}
+
+td.no_wrap:first-child {
+ white-space:nowrap;
+}
+
+.side_by_side_left{
+ float:left;
+}
+.side_by_side_right{
+ float:right;
+}
+
+#device{
+ display: inline-block;
+}
+.clear_block{
+ clear:both;
+}
+
+td.package{
+ background-color: #e0ddfa; /*purple*/
+}
+
+td.core{
+ background-color: #d1ddff; /*ccebff; /*blue*/
+}
+
+td.cpu{
+ background-color: #ffffeb; /* yellow */
+}
+
+th.title{
+ text-align: center;
+ /*border-bottom: 1px solid #666;*/
+}
+
+
+li.summary_list
+{
+ display: inline;
+ padding: 5px;
+ background-color: #f6f6f9;
+ font-size: 12px;
+}
+
+
+
+/* main menu css*/
+#main_menu {
+ clear:both;
+ font-weight: bold;
+ padding: 5px 0;
+ text-align: left;
+ background-image: -webkit-gradient(linear, left top, left bottom,
+ from(#aaa), to(#eee));
+ background: -moz-linear-gradient(top, #aaa, #eee);
+}
+
+
+#main_menu div {
+ font-size: 12px;
+ font-weight: bold;
+ color: white;
+}
+
+#main_menu div.nav_button {
+ margin: 0 0.2em;
+ display: inline;
+ cursor: pointer;
+ color: #223232;
+ font-size: 13px;
+ font-weight: bold;
+ padding: 5px;
+ text-align: center;
+ text-decoration: none;
+}
+
+div.pressed {
+ border: -webkit-gradient(linear, left top, left bottom,
+ from(#b2ffb2), to(#e0ffe0));
+ border-width:0px 8px 0px 8px;
+ background: #999;
+ background-image: -webkit-gradient(linear, left top, left bottom,
+ from(#b2ffb2), to(#e0ffe0));
+ background: -moz-linear-gradient(top, #b2ffb2, #e0ffe0);
+}
+
+div.hide {
+ display: none;
+}
+</style>
+</head>
+
+<body onload='powertop.onload();'>
+<div id=\"main_container\">
diff --git a/src/process/do_process.cpp b/src/process/do_process.cpp
new file mode 100644
index 0000000..be8d3bd
--- /dev/null
+++ b/src/process/do_process.cpp
@@ -0,0 +1,1230 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include "process.h"
+#include "interrupt.h"
+#include "timer.h"
+#include "work.h"
+#include "processdevice.h"
+#include "../lib.h"
+#include "../report/report.h"
+#include "../report/report-data-html.h"
+#include "../report/report-maker.h"
+#include "../devlist.h"
+
+#include <vector>
+#include <algorithm>
+#include <stack>
+
+#include <stdio.h>
+#include <string.h>
+#include <ncurses.h>
+
+#include "../perf/perf_bundle.h"
+#include "../perf/perf_event.h"
+#include "../parameters/parameters.h"
+#include "../display.h"
+#include "../measurement/measurement.h"
+
+static class perf_bundle * perf_events;
+
+vector <class power_consumer *> all_power;
+
+vector< vector<class power_consumer *> > cpu_stack;
+
+vector<int> cpu_level;
+vector<int> cpu_credit;
+vector<class power_consumer *> cpu_blame;
+
+#define LEVEL_HARDIRQ 1
+#define LEVEL_SOFTIRQ 2
+#define LEVEL_TIMER 3
+#define LEVEL_WAKEUP 4
+#define LEVEL_PROCESS 5
+#define LEVEL_WORK 6
+
+static uint64_t first_stamp, last_stamp;
+
+double measurement_time;
+
+static void push_consumer(unsigned int cpu, class power_consumer *consumer)
+{
+ if (cpu_stack.size() <= cpu)
+ cpu_stack.resize(cpu + 1);
+ cpu_stack[cpu].push_back(consumer);
+}
+
+static void pop_consumer(unsigned int cpu)
+{
+ if (cpu_stack.size() <= cpu)
+ cpu_stack.resize(cpu + 1);
+
+ if (cpu_stack[cpu].size())
+ cpu_stack[cpu].resize(cpu_stack[cpu].size()-1);
+}
+
+static int consumer_depth(unsigned int cpu)
+{
+ if (cpu_stack.size() <= cpu)
+ cpu_stack.resize(cpu + 1);
+ return cpu_stack[cpu].size();
+}
+
+static class power_consumer *current_consumer(unsigned int cpu)
+{
+ if (cpu_stack.size() <= cpu)
+ cpu_stack.resize(cpu + 1);
+ if (cpu_stack[cpu].size())
+
+ return cpu_stack[cpu][cpu_stack[cpu].size()-1];
+
+ return NULL;
+}
+
+static void clear_consumers(void)
+{
+ unsigned int i;
+ for (i = 0; i < cpu_stack.size(); i++)
+ cpu_stack[i].resize(0);
+}
+
+static void consumer_child_time(unsigned int cpu, uint64_t time)
+{
+ unsigned int i;
+ if (cpu_stack.size() <= cpu)
+ cpu_stack.resize(cpu + 1);
+ for (i = 0; i < cpu_stack[cpu].size(); i++)
+ cpu_stack[cpu][i]->child_runtime += time;
+}
+
+static void set_wakeup_pending(unsigned int cpu)
+{
+ if (cpu_credit.size() <= cpu)
+ cpu_credit.resize(cpu + 1);
+
+ cpu_credit[cpu] = 1;
+}
+
+static void clear_wakeup_pending(unsigned int cpu)
+{
+ if (cpu_credit.size() <= cpu)
+ cpu_credit.resize(cpu + 1);
+
+ cpu_credit[cpu] = 0;
+}
+
+static int get_wakeup_pending(unsigned int cpu)
+{
+ if (cpu_credit.size() <= cpu)
+ cpu_credit.resize(cpu + 1);
+ return cpu_credit[cpu];
+}
+
+static void change_blame(unsigned int cpu, class power_consumer *consumer, int level)
+{
+ if (cpu_level[cpu] >= level)
+ return;
+ cpu_blame[cpu] = consumer;
+ cpu_level[cpu] = level;
+}
+
+static void consume_blame(unsigned int cpu)
+{
+ if (!get_wakeup_pending(cpu))
+ return;
+ if (cpu_level.size() <= cpu)
+ return;
+ if (cpu_blame.size() <= cpu)
+ return;
+ if (!cpu_blame[cpu])
+ return;
+
+ cpu_blame[cpu]->wake_ups++;
+ cpu_blame[cpu] = NULL;
+ cpu_level[cpu] = 0;
+ clear_wakeup_pending(cpu);
+}
+
+
+class perf_process_bundle: public perf_bundle
+{
+ virtual void handle_trace_point(void *trace, int cpu, uint64_t time);
+};
+
+static bool comm_is_xorg(char *comm)
+{
+ return strcmp(comm, "Xorg") == 0 || strcmp(comm, "X") == 0;
+}
+
+/* some processes shouldn't be blamed for the wakeup if they wake a process up... for now this is a hardcoded list */
+int dont_blame_me(char *comm)
+{
+ if (comm_is_xorg(comm))
+ return 1;
+ if (strcmp(comm, "dbus-daemon") == 0)
+ return 1;
+
+ return 0;
+}
+
+static char * get_pevent_field_str(void *trace, struct event_format *event, struct format_field *field)
+{
+ unsigned long long offset, len;
+ if (field->flags & FIELD_IS_DYNAMIC) {
+ offset = field->offset;
+ len = field->size;
+ offset = pevent_read_number(event->pevent, (char *)trace + offset, len);
+ offset &= 0xffff;
+ return (char *)trace + offset;
+ }
+ /** no __data_loc field type*/
+ return (char *)trace + field->offset;
+}
+
+void perf_process_bundle::handle_trace_point(void *trace, int cpu, uint64_t time)
+{
+ struct event_format *event;
+ struct pevent_record rec; /* holder */
+ struct format_field *field;
+ unsigned long long val;
+ int type;
+ int ret;
+
+ rec.data = trace;
+
+ type = pevent_data_type(perf_event::pevent, &rec);
+ event = pevent_find_event(perf_event::pevent, type);
+ if (!event)
+ return;
+
+ if (time < first_stamp)
+ first_stamp = time;
+
+ if (time > last_stamp) {
+ last_stamp = time;
+ measurement_time = (0.0001 + last_stamp - first_stamp) / 1000000000 ;
+ }
+
+ if (strcmp(event->name, "sched_switch") == 0) {
+ class process *old_proc = NULL;
+ class process *new_proc = NULL;
+ const char *next_comm;
+ int next_pid;
+ int prev_pid;
+
+ field = pevent_find_any_field(event, "next_comm");
+ if (!field || !(field->flags & FIELD_IS_STRING))
+ return; /* ?? */
+
+ next_comm = get_pevent_field_str(trace, event, field);
+
+ ret = pevent_get_field_val(NULL, event, "next_pid", &rec, &val, 0);
+ if (ret < 0)
+ return;
+ next_pid = (int)val;
+
+ ret = pevent_get_field_val(NULL, event, "prev_pid", &rec, &val, 0);
+ if (ret < 0)
+ return;
+ prev_pid = (int)val;
+
+ /* find new process pointer */
+ new_proc = find_create_process(next_comm, next_pid);
+
+ /* find the old process pointer */
+
+ while (consumer_depth(cpu) > 1) {
+ pop_consumer(cpu);
+ }
+
+ if (consumer_depth(cpu) == 1)
+ old_proc = (class process *)current_consumer(cpu);
+
+ if (old_proc && strcmp(old_proc->name(), "process"))
+ old_proc = NULL;
+
+ /* retire the old process */
+
+ if (old_proc) {
+ old_proc->deschedule_thread(time, prev_pid);
+ old_proc->waker = NULL;
+ }
+
+ if (consumer_depth(cpu))
+ pop_consumer(cpu);
+
+ push_consumer(cpu, new_proc);
+
+ /* start new process */
+ new_proc->schedule_thread(time, next_pid);
+
+ if (strncmp(next_comm,"migration/", 10) && strncmp(next_comm,"kworker/", 8) && strncmp(next_comm, "kondemand/",10)) {
+ if (next_pid) {
+ /* If someone woke us up.. blame him instead */
+ if (new_proc->waker) {
+ change_blame(cpu, new_proc->waker, LEVEL_PROCESS);
+ } else {
+ change_blame(cpu, new_proc, LEVEL_PROCESS);
+ }
+ }
+
+ consume_blame(cpu);
+ }
+ new_proc->waker = NULL;
+ }
+ else if (strcmp(event->name, "sched_wakeup") == 0) {
+ class power_consumer *from = NULL;
+ class process *dest_proc = NULL;
+ class process *from_proc = NULL;
+ const char *comm;
+ int flags;
+ int pid;
+
+ ret = pevent_get_common_field_val(NULL, event, "common_flags", &rec, &val, 0);
+ if (ret < 0)
+ return;
+ flags = (int)val;
+
+ if ( (flags & TRACE_FLAG_HARDIRQ) || (flags & TRACE_FLAG_SOFTIRQ)) {
+ class timer *timer;
+ timer = (class timer *) current_consumer(cpu);
+ if (timer && strcmp(timer->name(), "timer")==0) {
+ if (strcmp(timer->handler, "delayed_work_timer_fn") &&
+ strcmp(timer->handler, "hrtimer_wakeup") &&
+ strcmp(timer->handler, "it_real_fn"))
+ from = timer;
+ }
+ /* woken from interrupt */
+ /* TODO: find the current irq handler and set "from" to that */
+ } else {
+ from = current_consumer(cpu);
+ }
+
+
+ field = pevent_find_any_field(event, "comm");
+
+ if (!field || !(field->flags & FIELD_IS_STRING))
+ return;
+
+ comm = get_pevent_field_str(trace, event, field);
+
+ ret = pevent_get_field_val(NULL, event, "pid", &rec, &val, 0);
+ if (ret < 0)
+ return;
+ pid = (int)val;
+
+ dest_proc = find_create_process(comm, pid);
+
+ if (from && strcmp(from->name(), "process")!=0){
+ /* not a process doing the wakeup */
+ from = NULL;
+ from_proc = NULL;
+ } else {
+ from_proc = (class process *) from;
+ }
+
+ if (from_proc && (dest_proc->running == 0) && (dest_proc->waker == NULL) && (pid != 0) && !dont_blame_me(from_proc->comm))
+ dest_proc->waker = from;
+ if (from)
+ dest_proc->last_waker = from;
+
+ /* Account processes that wake up X specially */
+ if (from && dest_proc && comm_is_xorg(dest_proc->comm))
+ from->xwakes ++ ;
+
+ }
+ else if (strcmp(event->name, "irq_handler_entry") == 0) {
+ class interrupt *irq = NULL;
+ const char *handler;
+ int nr;
+
+ field = pevent_find_any_field(event, "name");
+ if (!field || !(field->flags & FIELD_IS_STRING))
+ return; /* ?? */
+
+ handler = get_pevent_field_str(trace, event, field);
+
+ ret = pevent_get_field_val(NULL, event, "irq", &rec, &val, 0);
+ if (ret < 0)
+ return;
+ nr = (int)val;
+
+ irq = find_create_interrupt(handler, nr, cpu);
+
+
+ push_consumer(cpu, irq);
+
+ irq->start_interrupt(time);
+
+ if (strstr(irq->handler, "timer") ==NULL)
+ change_blame(cpu, irq, LEVEL_HARDIRQ);
+
+ }
+
+ else if (strcmp(event->name, "irq_handler_exit") == 0) {
+ class interrupt *irq = NULL;
+ uint64_t t;
+
+ /* find interrupt (top of stack) */
+ irq = (class interrupt *)current_consumer(cpu);
+ if (!irq || strcmp(irq->name(), "interrupt"))
+ return;
+ pop_consumer(cpu);
+ /* retire interrupt */
+ t = irq->end_interrupt(time);
+ consumer_child_time(cpu, t);
+ }
+
+ else if (strcmp(event->name, "softirq_entry") == 0) {
+ class interrupt *irq = NULL;
+ const char *handler = NULL;
+ int vec;
+
+ ret = pevent_get_field_val(NULL, event, "vec", &rec, &val, 0);
+ if (ret < 0) {
+ fprintf(stderr, "softirq_entry event returned no vector number?\n");
+ return;
+ }
+ vec = (int)val;
+
+ if (vec <= 9)
+ handler = softirqs[vec];
+
+ if (!handler)
+ return;
+
+ irq = find_create_interrupt(handler, vec, cpu);
+
+ push_consumer(cpu, irq);
+
+ irq->start_interrupt(time);
+ change_blame(cpu, irq, LEVEL_SOFTIRQ);
+ }
+ else if (strcmp(event->name, "softirq_exit") == 0) {
+ class interrupt *irq = NULL;
+ uint64_t t;
+
+ irq = (class interrupt *) current_consumer(cpu);
+ if (!irq || strcmp(irq->name(), "interrupt"))
+ return;
+ pop_consumer(cpu);
+ /* pop irq */
+ t = irq->end_interrupt(time);
+ consumer_child_time(cpu, t);
+ }
+ else if (strcmp(event->name, "timer_expire_entry") == 0) {
+ class timer *timer = NULL;
+ uint64_t function;
+ uint64_t tmr;
+
+ ret = pevent_get_field_val(NULL, event, "function", &rec, &val, 0);
+ if (ret < 0) {
+ fprintf(stderr, "timer_expire_entry event returned no function value?\n");
+ return;
+ }
+ function = (uint64_t)val;
+
+ timer = find_create_timer(function);
+
+ if (timer->is_deferred())
+ return;
+
+ ret = pevent_get_field_val(NULL, event, "timer", &rec, &val, 0);
+ if (ret < 0) {
+ fprintf(stderr, "softirq_entry event returned no timer ?\n");
+ return;
+ }
+ tmr = (uint64_t)val;
+
+ push_consumer(cpu, timer);
+ timer->fire(time, tmr);
+
+ if (strcmp(timer->handler, "delayed_work_timer_fn"))
+ change_blame(cpu, timer, LEVEL_TIMER);
+ }
+ else if (strcmp(event->name, "timer_expire_exit") == 0) {
+ class timer *timer = NULL;
+ uint64_t tmr;
+ uint64_t t;
+
+ ret = pevent_get_field_val(NULL, event, "timer", &rec, &val, 0);
+ if (ret < 0)
+ return;
+ tmr = (uint64_t)val;
+
+ timer = (class timer *) current_consumer(cpu);
+ if (!timer || strcmp(timer->name(), "timer")) {
+ return;
+ }
+ pop_consumer(cpu);
+ t = timer->done(time, tmr);
+ if (t == ~0ULL) {
+ timer->fire(first_stamp, tmr);
+ t = timer->done(time, tmr);
+ }
+ consumer_child_time(cpu, t);
+ }
+ else if (strcmp(event->name, "hrtimer_expire_entry") == 0) {
+ class timer *timer = NULL;
+ uint64_t function;
+ uint64_t tmr;
+
+ ret = pevent_get_field_val(NULL, event, "function", &rec, &val, 0);
+ if (ret < 0)
+ return;
+ function = (uint64_t)val;
+
+ timer = find_create_timer(function);
+
+ ret = pevent_get_field_val(NULL, event, "hrtimer", &rec, &val, 0);
+ if (ret < 0)
+ return;
+ tmr = (uint64_t)val;
+
+ push_consumer(cpu, timer);
+ timer->fire(time, tmr);
+
+ if (strcmp(timer->handler, "delayed_work_timer_fn"))
+ change_blame(cpu, timer, LEVEL_TIMER);
+ }
+ else if (strcmp(event->name, "hrtimer_expire_exit") == 0) {
+ class timer *timer = NULL;
+ uint64_t tmr;
+ uint64_t t;
+
+ timer = (class timer *) current_consumer(cpu);
+ if (!timer || strcmp(timer->name(), "timer")) {
+ return;
+ }
+
+ ret = pevent_get_field_val(NULL, event, "hrtimer", &rec, &val, 0);
+ if (ret < 0)
+ return;
+ tmr = (uint64_t)val;
+
+ pop_consumer(cpu);
+ t = timer->done(time, tmr);
+ if (t == ~0ULL) {
+ timer->fire(first_stamp, tmr);
+ t = timer->done(time, tmr);
+ }
+ consumer_child_time(cpu, t);
+ }
+ else if (strcmp(event->name, "workqueue_execute_start") == 0) {
+ class work *work = NULL;
+ uint64_t function;
+ uint64_t wk;
+
+ ret = pevent_get_field_val(NULL, event, "function", &rec, &val, 0);
+ if (ret < 0)
+ return;
+ function = (uint64_t)val;
+
+ ret = pevent_get_field_val(NULL, event, "work", &rec, &val, 0);
+ if (ret < 0)
+ return;
+ wk = (uint64_t)val;
+
+ work = find_create_work(function);
+
+
+ push_consumer(cpu, work);
+ work->fire(time, wk);
+
+
+ if (strcmp(work->handler, "do_dbs_timer") != 0 && strcmp(work->handler, "vmstat_update") != 0)
+ change_blame(cpu, work, LEVEL_WORK);
+ }
+ else if (strcmp(event->name, "workqueue_execute_end") == 0) {
+ class work *work = NULL;
+ uint64_t t;
+ uint64_t wk;
+
+ ret = pevent_get_field_val(NULL, event, "work", &rec, &val, 0);
+ if (ret < 0)
+ return;
+ wk = (uint64_t)val;
+
+ work = (class work *) current_consumer(cpu);
+ if (!work || strcmp(work->name(), "work")) {
+ return;
+ }
+ pop_consumer(cpu);
+ t = work->done(time, wk);
+ if (t == ~0ULL) {
+ work->fire(first_stamp, wk);
+ t = work->done(time, wk);
+ }
+ consumer_child_time(cpu, t);
+ }
+ else if (strcmp(event->name, "cpu_idle") == 0) {
+ pevent_get_field_val(NULL, event, "state", &rec, &val, 0);
+ if (val == (unsigned int)-1)
+ consume_blame(cpu);
+ else
+ set_wakeup_pending(cpu);
+ }
+ else if (strcmp(event->name, "power_start") == 0) {
+ set_wakeup_pending(cpu);
+ }
+ else if (strcmp(event->name, "power_end") == 0) {
+ consume_blame(cpu);
+ }
+ else if (strcmp(event->name, "i915_gem_ring_dispatch") == 0
+ || strcmp(event->name, "i915_gem_request_submit") == 0) {
+ /* any kernel contains only one of the these tracepoints,
+ * the latter one got replaced by the former one */
+ class power_consumer *consumer = NULL;
+ int flags;
+
+ ret = pevent_get_common_field_val(NULL, event, "common_flags", &rec, &val, 0);
+ if (ret < 0)
+ return;
+ flags = (int)val;
+
+ consumer = current_consumer(cpu);
+ /* currently we don't count graphic requests submitted from irq contect */
+ if ( (flags & TRACE_FLAG_HARDIRQ) || (flags & TRACE_FLAG_SOFTIRQ)) {
+ consumer = NULL;
+ }
+
+
+ /* if we are X, and someone just woke us, account the GPU op to the guy waking us */
+ if (consumer && strcmp(consumer->name(), "process")==0) {
+ class process *proc = NULL;
+ proc = (class process *) consumer;
+ if (comm_is_xorg(proc->comm) && proc->last_waker) {
+ consumer = proc->last_waker;
+ }
+ }
+
+
+
+ if (consumer) {
+ consumer->gpu_ops++;
+ }
+ }
+ else if (strcmp(event->name, "writeback_inode_dirty") == 0) {
+ static uint64_t prev_time;
+ class power_consumer *consumer = NULL;
+ int dev;
+
+ consumer = current_consumer(cpu);
+
+ ret = pevent_get_field_val(NULL, event, "dev", &rec, &val, 0);
+ if (ret < 0)
+
+ return;
+ dev = (int)val;
+
+ if (consumer && strcmp(consumer->name(),
+ "process")==0 && dev > 0) {
+
+ consumer->disk_hits++;
+
+ /* if the previous inode dirty was > 1 second ago, it becomes a hard hit */
+ if ((time - prev_time) > 1000000000)
+ consumer->hard_disk_hits++;
+
+ prev_time = time;
+ }
+ }
+}
+
+void start_process_measurement(void)
+{
+ if (!perf_events) {
+ perf_events = new perf_process_bundle();
+ perf_events->add_event("sched:sched_switch");
+ perf_events->add_event("sched:sched_wakeup");
+ perf_events->add_event("irq:irq_handler_entry");
+ perf_events->add_event("irq:irq_handler_exit");
+ perf_events->add_event("irq:softirq_entry");
+ perf_events->add_event("irq:softirq_exit");
+ perf_events->add_event("timer:timer_expire_entry");
+ perf_events->add_event("timer:timer_expire_exit");
+ perf_events->add_event("timer:hrtimer_expire_entry");
+ perf_events->add_event("timer:hrtimer_expire_exit");
+ if (!perf_events->add_event("power:cpu_idle")){
+ perf_events->add_event("power:power_start");
+ perf_events->add_event("power:power_end");
+ }
+ perf_events->add_event("workqueue:workqueue_execute_start");
+ perf_events->add_event("workqueue:workqueue_execute_end");
+ perf_events->add_event("i915:i915_gem_ring_dispatch");
+ perf_events->add_event("i915:i915_gem_request_submit");
+ perf_events->add_event("writeback:writeback_inode_dirty");
+ }
+
+ first_stamp = ~0ULL;
+ last_stamp = 0;
+ perf_events->start();
+}
+
+void end_process_measurement(void)
+{
+ if (!perf_events)
+ return;
+
+ perf_events->stop();
+}
+
+
+static bool power_cpu_sort(class power_consumer * i, class power_consumer * j)
+{
+ double iW, jW;
+
+ iW = i->Witts();
+ jW = j->Witts();
+
+ if (equals(iW, jW)) {
+ double iR, jR;
+
+ iR = i->accumulated_runtime - i->child_runtime;
+ jR = j->accumulated_runtime - j->child_runtime;
+
+ if (equals(iR, jR))
+ return i->wake_ups > j->wake_ups;
+ return (iR > jR);
+ }
+
+ return (iW > jW);
+}
+
+double total_wakeups(void)
+{
+ double total = 0;
+ unsigned int i;
+ for (i = 0; i < all_power.size() ; i++)
+ total += all_power[i]->wake_ups;
+
+ total = total / measurement_time;
+
+
+ return total;
+}
+
+double total_gpu_ops(void)
+{
+ double total = 0;
+ unsigned int i;
+ for (i = 0; i < all_power.size() ; i++)
+ total += all_power[i]->gpu_ops;
+
+
+ total = total / measurement_time;
+
+
+ return total;
+}
+
+double total_disk_hits(void)
+{
+ double total = 0;
+ unsigned int i;
+ for (i = 0; i < all_power.size() ; i++)
+ total += all_power[i]->disk_hits;
+
+
+ total = total / measurement_time;
+
+
+ return total;
+}
+
+
+double total_hard_disk_hits(void)
+{
+ double total = 0;
+ unsigned int i;
+ for (i = 0; i < all_power.size() ; i++)
+ total += all_power[i]->hard_disk_hits;
+
+
+ total = total / measurement_time;
+
+
+ return total;
+}
+
+double total_xwakes(void)
+{
+ double total = 0;
+ unsigned int i;
+ for (i = 0; i < all_power.size() ; i++)
+ total += all_power[i]->xwakes;
+
+
+ total = total / measurement_time;
+
+
+ return total;
+}
+
+void process_update_display(void)
+{
+ unsigned int i;
+ WINDOW *win;
+ double pw;
+ double joules;
+ int tl;
+ int tlt;
+ int tlr;
+
+ int show_power;
+ int need_linebreak = 0;
+
+ sort(all_power.begin(), all_power.end(), power_cpu_sort);
+
+ show_power = global_power_valid();
+
+ win = get_ncurses_win("Overview");
+ if (!win)
+ return;
+
+ wclear(win);
+
+ wmove(win, 1,0);
+
+#if 0
+ double sum;
+ calculate_params();
+ sum = 0.0;
+ sum += get_parameter_value("base power");
+ for (i = 0; i < all_power.size(); i++) {
+ sum += all_power[i]->Witts();
+ }
+
+ wprintw(win, _("Estimated power: %5.1f Measured power: %5.1f Sum: %5.1f\n\n"),
+ all_parameters.guessed_power, global_power(), sum);
+#endif
+
+ pw = global_power();
+ joules = global_joules();
+ tl = global_time_left() / 60;
+ tlt = (tl /60);
+ tlr = tl % 60;
+
+ if (pw > 0.0001) {
+ char buf[32];
+ wprintw(win, _("The battery reports a discharge rate of %sW\n"),
+ fmt_prefix(pw, buf));
+ wprintw(win, _("The energy consumed was %sJ\n"),
+ fmt_prefix(joules, buf));
+ need_linebreak = 1;
+ }
+ if (tl > 0 && pw > 0.0001) {
+ wprintw(win, _("The estimated remaining time is %i hours, %i minutes\n"), tlt, tlr);
+ need_linebreak = 1;
+ }
+
+ if (need_linebreak)
+ wprintw(win, "\n");
+
+
+ wprintw(win, "%s: %3.1f %s, %3.1f %s, %3.1f %s %3.1f%% %s\n\n",_("Summary"), total_wakeups(), _("wakeups/second"), total_gpu_ops(), _("GPU ops/seconds"), total_disk_hits(), _("VFS ops/sec and"), total_cpu_time()*100, _("CPU use"));
+
+
+ if (show_power)
+ wprintw(win, "%s %s %s %s %s\n", _("Power est."), _("Usage"), _("Events/s"), _("Category"), _("Description"));
+ else
+ wprintw(win, " %s %s %s %s\n", _("Usage"), _("Events/s"), _("Category"), _("Description"));
+
+ for (i = 0; i < all_power.size(); i++) {
+ char power[16];
+ char name[20];
+ char usage[20];
+ char events[20];
+ char descr[128];
+
+ format_watts(all_power[i]->Witts(), power, 10);
+ if (!show_power)
+ strcpy(power, " ");
+ snprintf(name, sizeof(name), "%s", all_power[i]->type());
+
+ align_string(name, 14, 20);
+
+ if (all_power[i]->events() == 0 && all_power[i]->usage() == 0 && all_power[i]->Witts() == 0)
+ break;
+
+ usage[0] = 0;
+ if (all_power[i]->usage_units()) {
+ if (all_power[i]->usage() < 1000)
+ snprintf(usage, sizeof(usage), "%5.1f%s", all_power[i]->usage(), all_power[i]->usage_units());
+ else
+ snprintf(usage, sizeof(usage), "%5i%s", (int)all_power[i]->usage(), all_power[i]->usage_units());
+ }
+
+ align_string(usage, 14, 20);
+
+ snprintf(events, sizeof(events), "%5.1f", all_power[i]->events());
+ if (!all_power[i]->show_events())
+ events[0] = 0;
+ else if (all_power[i]->events() <= 0.3)
+ snprintf(events, sizeof(events), "%5.2f", all_power[i]->events());
+
+ align_string(events, 12, 20);
+ wprintw(win, "%s %s %s %s %s\n", power, usage, events, name, pretty_print(all_power[i]->description(), descr, 128));
+ }
+}
+
+void report_process_update_display(void)
+{
+ unsigned int i;
+ unsigned int total;
+ int show_power, cols, rows, idx;
+
+ /* div attr css_class and css_id */
+ tag_attr div_attr;
+ init_div(&div_attr, "clear_block", "software");
+
+ /* Set Table attributes, rows, and cols */
+ cols=7;
+ sort(all_power.begin(), all_power.end(), power_cpu_sort);
+ show_power = global_power_valid();
+ if (show_power)
+ cols=8;
+
+ idx=cols;
+
+ total = all_power.size();
+ if (total > 100)
+ total = 100;
+
+ rows=total+1;
+ table_attributes std_table_css;
+ init_nowarp_table_attr(&std_table_css, rows, cols);
+
+
+ /* Set Title attributes */
+ tag_attr title_attr;
+ init_title_attr(&title_attr);
+
+ /* Set array of data in row Major order */
+ string *software_data = new string[cols * rows];
+ software_data[0]=__("Usage");
+ software_data[1]=__("Wakeups/s");
+ software_data[2]=__("GPU ops/s");
+ software_data[3]=__("Disk IO/s");
+ software_data[4]=__("GFX Wakeups/s");
+ software_data[5]=__("Category");
+ software_data[6]=__("Description");
+
+ if (show_power)
+ software_data[7]=__("PW Estimate");
+
+
+ for (i = 0; i < total; i++) {
+ char power[16];
+ char name[20];
+ char usage[20];
+ char wakes[20];
+ char gpus[20];
+ char disks[20];
+ char xwakes[20];
+ char descr[128];
+ format_watts(all_power[i]->Witts(), power, 10);
+
+ if (!show_power)
+ strcpy(power, " ");
+ snprintf(name, sizeof(name), "%s", all_power[i]->type());
+
+ if (strcmp(name, "Device") == 0)
+ continue;
+
+ if (all_power[i]->events() == 0 && all_power[i]->usage() == 0
+ && all_power[i]->Witts() == 0)
+ break;
+
+ usage[0] = 0;
+ if (all_power[i]->usage_units()) {
+ if (all_power[i]->usage() < 1000)
+ snprintf(usage, sizeof(usage), "%5.1f%s", all_power[i]->usage(), all_power[i]->usage_units());
+ else
+ snprintf(usage, sizeof(usage), "%5i%s", (int)all_power[i]->usage(), all_power[i]->usage_units());
+ }
+ snprintf(wakes, sizeof(wakes), "%5.1f", all_power[i]->wake_ups / measurement_time);
+ if (all_power[i]->wake_ups / measurement_time <= 0.3)
+ snprintf(wakes, sizeof(wakes), "%5.2f", all_power[i]->wake_ups / measurement_time);
+ snprintf(gpus, sizeof(gpus), "%5.1f", all_power[i]->gpu_ops / measurement_time);
+ snprintf(disks, sizeof(disks), "%5.1f (%5.1f)", all_power[i]->hard_disk_hits / measurement_time,
+ all_power[i]->disk_hits / measurement_time);
+ snprintf(xwakes, sizeof(xwakes), "%5.1f", all_power[i]->xwakes / measurement_time);
+ if (!all_power[i]->show_events()) {
+ wakes[0] = 0;
+ gpus[0] = 0;
+ disks[0] = 0;
+ }
+
+ if (all_power[i]->gpu_ops == 0)
+ gpus[0] = 0;
+ if (all_power[i]->wake_ups == 0)
+ wakes[0] = 0;
+ if (all_power[i]->disk_hits == 0)
+ disks[0] = 0;
+ if (all_power[i]->xwakes == 0)
+ xwakes[0] = 0;
+
+ software_data[idx]=string(usage);
+ idx+=1;
+
+ software_data[idx]=string(wakes);
+ idx+=1;
+
+ software_data[idx]=string(gpus);
+ idx+=1;
+
+ software_data[idx]=string(disks);
+ idx+=1;
+
+ software_data[idx]=string(xwakes);
+ idx+=1;
+
+ software_data[idx]=string(name);
+ idx+=1;
+
+ software_data[idx]=string(pretty_print(all_power[i]->description(), descr, 128));
+ idx+=1;
+ if (show_power) {
+ software_data[idx]=string(power);
+ idx+=1;
+ }
+ }
+
+ /* Report Output */
+ report.add_div(&div_attr);
+ report.add_title(&title_attr, __("Overview of Software Power Consumers"));
+ report.add_table(software_data, &std_table_css);
+ report.end_div();
+ delete [] software_data;
+}
+
+void report_summary(void)
+{
+ unsigned int i;
+ unsigned int total;
+ int show_power;
+ int rows, cols, idx;
+
+ sort(all_power.begin(), all_power.end(), power_cpu_sort);
+ show_power = global_power_valid();
+
+ /* div attr css_class and css_id */
+ tag_attr div_attr;
+ init_div(&div_attr, "clear_block", "summary");
+
+
+ /* Set table attributes, rows, and cols */
+ cols=4;
+ if (show_power)
+ cols=5;
+ idx=cols;
+ total = all_power.size();
+ if (total > 10)
+ total = 10;
+ rows=total+1;
+ table_attributes std_table_css;
+ init_std_table_attr(&std_table_css, rows, cols);
+
+ /* Set title attributes */
+ tag_attr title_attr;
+ init_title_attr(&title_attr);
+
+ /* Set array for summary */
+ int summary_size =12;
+ string *summary = new string [summary_size];
+ summary[0]=__("Target:");
+ summary[1]=__("1 units/s");
+ summary[2]=__("System: ");
+ summary[3]= double_to_string(total_wakeups());
+ summary[3].append(__(" wakeup/s"));
+ summary[4]=__("CPU: ");
+ summary[5]= double_to_string(total_cpu_time()*100);
+ summary[5].append(__("\% usage"));
+ summary[6]=__("GPU:");
+ summary[7]=double_to_string(total_gpu_ops());
+ summary[7].append(__(" ops/s"));
+ summary[8]=__("GFX:");
+ summary[9]=double_to_string(total_xwakes());
+ summary[9].append(__(" wakeups/s"));
+ summary[10]=__("VFS:");
+ summary[11]= double_to_string(total_disk_hits());
+ summary[11].append(__(" ops/s"));
+
+ /* Set array of data in row Major order */
+ string *summary_data = new string[cols * (rows + 1)];
+ summary_data[0]=__("Usage");
+ summary_data[1]=__("Events/s");
+ summary_data[2]=__("Category");
+ summary_data[3]=__("Description");
+ if (show_power)
+ summary_data[4]=__("PW Estimate");
+
+ for (i = 0; i < all_power.size(); i++) {
+ char power[16];
+ char name[20];
+ char usage[20];
+ char events[20];
+ char descr[128];
+ format_watts(all_power[i]->Witts(), power, 10);
+
+ if (!show_power)
+ strcpy(power, " ");
+ snprintf(name, sizeof(name), "%s", all_power[i]->type());
+
+ if (i > total)
+ break;
+
+ if (all_power[i]->events() == 0 && all_power[i]->usage() == 0 &&
+ all_power[i]->Witts() == 0)
+ break;
+
+ usage[0] = 0;
+ if (all_power[i]->usage_units()) {
+ if (all_power[i]->usage() < 1000)
+ snprintf(usage, sizeof(usage), "%5.1f%s", all_power[i]->usage_summary(),
+ all_power[i]->usage_units_summary());
+ else
+ snprintf(usage, sizeof(usage), "%5i%s", (int)all_power[i]->usage_summary(),
+ all_power[i]->usage_units_summary());
+ }
+ snprintf(events, sizeof(events), "%5.1f", all_power[i]->events());
+ if (!all_power[i]->show_events())
+ events[0] = 0;
+ else if (all_power[i]->events() <= 0.3)
+ snprintf(events, sizeof(events), "%5.2f", all_power[i]->events());
+
+ summary_data[idx]=string(usage);
+ idx+=1;
+
+ summary_data[idx]=string(events);
+ idx+=1;
+
+ summary_data[idx]=string(name);
+ idx+=1;
+
+ summary_data[idx]=string(pretty_print(all_power[i]->description(), descr, 128));
+ idx+=1;
+
+ if (show_power){
+ summary_data[idx]=power;
+ idx+=1;
+ }
+ }
+
+ /* Report Summary for all */
+ report.add_summary_list(summary, summary_size);
+ report.add_div(&div_attr);
+ report.add_title(&title_attr, __("Top 10 Power Consumers"));
+ report.add_table(summary_data, &std_table_css);
+ report.end_div();
+ delete [] summary;
+ delete [] summary_data;
+}
+
+
+void process_process_data(void)
+{
+ if (!perf_events)
+ return;
+
+ clear_processes();
+ clear_interrupts();
+
+ all_power.erase(all_power.begin(), all_power.end());
+ clear_consumers();
+
+
+ cpu_credit.resize(0, 0);
+ cpu_credit.resize(get_max_cpu()+1, 0);
+ cpu_level.resize(0, 0);
+ cpu_level.resize(get_max_cpu()+1, 0);
+ cpu_blame.resize(0, NULL);
+ cpu_blame.resize(get_max_cpu()+1, NULL);
+
+
+
+ /* process data */
+ perf_events->process();
+ perf_events->clear();
+
+ run_devpower_list();
+
+ merge_processes();
+
+ all_processes_to_all_power();
+ all_interrupts_to_all_power();
+ all_timers_to_all_power();
+ all_work_to_all_power();
+ all_devices_to_all_power();
+
+ sort(all_power.begin(), all_power.end(), power_cpu_sort);
+}
+
+
+double total_cpu_time(void)
+{
+ unsigned int i;
+ double total = 0.0;
+ for (i = 0; i < all_power.size() ; i++) {
+ if (all_power[i]->child_runtime > all_power[i]->accumulated_runtime)
+ all_power[i]->child_runtime = 0;
+ total += all_power[i]->accumulated_runtime - all_power[i]->child_runtime;
+ }
+
+ total = (total / (0.0001 + last_stamp - first_stamp));
+
+ return total;
+}
+
+
+
+void end_process_data(void)
+{
+ report_utilization("cpu-consumption", total_cpu_time());
+ report_utilization("cpu-wakeups", total_wakeups());
+ report_utilization("gpu-operations", total_gpu_ops());
+ report_utilization("disk-operations", total_disk_hits());
+ report_utilization("disk-operations-hard", total_hard_disk_hits());
+ report_utilization("xwakes", total_xwakes());
+
+ all_power.erase(all_power.begin(), all_power.end());
+ clear_processes();
+ clear_proc_devices();
+ clear_interrupts();
+ clear_timers();
+ clear_work();
+ clear_consumers();
+
+ perf_events->clear();
+
+}
+
+void clear_process_data(void)
+{
+ if (perf_events)
+ perf_events->release();
+ delete perf_events;
+}
+
diff --git a/src/process/interrupt.cpp b/src/process/interrupt.cpp
new file mode 100644
index 0000000..a6553b1
--- /dev/null
+++ b/src/process/interrupt.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include "process.h"
+#include "interrupt.h"
+#include "../lib.h"
+
+const char* softirqs[] = {
+ "HI_SOFTIRQ",
+ "timer(softirq)",
+ "net tx(softirq)",
+ "net_rx(softirq)",
+ "block(softirq)",
+ "block_iopoll(softirq)",
+ "tasklet(softirq)",
+ "sched(softirq)",
+ "hrtimer(softirq)",
+ "RCU(softirq)",
+ NULL
+};
+
+
+interrupt::interrupt(const char *_handler, int _number) : power_consumer()
+{
+ char buf[128];
+ running_since = 0;
+ number = _number;
+ pt_strcpy(handler, _handler);
+ raw_count = 0;
+ snprintf(desc, sizeof(desc), "[%i] %s", number, pretty_print(handler, buf, 128));
+}
+
+
+vector <class interrupt *> all_interrupts;
+
+void interrupt::start_interrupt(uint64_t time)
+{
+ running_since = time;
+ raw_count ++;
+}
+
+uint64_t interrupt::end_interrupt(uint64_t time)
+{
+ uint64_t delta;
+
+ delta = time - running_since;
+ accumulated_runtime += delta;
+ return delta;
+}
+
+const char * interrupt::description(void)
+{
+ if (child_runtime > accumulated_runtime)
+ child_runtime = 0;
+ return desc;
+}
+
+double interrupt::usage_summary(void)
+{
+ double t;
+ t = (accumulated_runtime - child_runtime) / 1000000.0 / measurement_time / 10;
+ return t;
+}
+
+const char * interrupt::usage_units_summary(void)
+{
+ return "%";
+}
+
+
+class interrupt * find_create_interrupt(const char *_handler, int nr, int cpu)
+{
+ char handler[64];
+ unsigned int i;
+ class interrupt *new_irq;
+
+ pt_strcpy(handler, _handler);
+ if (strcmp(handler, "timer")==0)
+ sprintf(handler, "timer/%i", cpu);
+
+
+ for (i = 0; i < all_interrupts.size(); i++) {
+ if (all_interrupts[i] && all_interrupts[i]->number == nr && strcmp(handler, all_interrupts[i]->handler) == 0)
+ return all_interrupts[i];
+ }
+
+ new_irq = new class interrupt(handler, nr);
+ all_interrupts.push_back(new_irq);
+ return new_irq;
+}
+
+void all_interrupts_to_all_power(void)
+{
+ unsigned int i;
+ for (i = 0; i < all_interrupts.size() ; i++)
+ if (all_interrupts[i]->accumulated_runtime)
+ all_power.push_back(all_interrupts[i]);
+}
+
+void clear_interrupts(void)
+{
+ std::vector<class interrupt *>::iterator it = all_interrupts.begin();
+ while (it != all_interrupts.end()) {
+ delete *it;
+ it = all_interrupts.erase(it);
+ }
+}
diff --git a/src/process/interrupt.h b/src/process/interrupt.h
new file mode 100644
index 0000000..8d3a4d7
--- /dev/null
+++ b/src/process/interrupt.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_INTERRUPT_H
+#define _INCLUDE_GUARD_INTERRUPT_H
+
+#include <stdint.h>
+
+#include "powerconsumer.h"
+
+class interrupt : public power_consumer {
+ uint64_t running_since;
+ char desc[256];
+public:
+ char handler[32];
+ int number;
+
+ int raw_count;
+
+ interrupt(const char *_handler, int _number);
+
+ virtual void start_interrupt(uint64_t time);
+ virtual uint64_t end_interrupt(uint64_t time);
+
+ virtual const char * description(void);
+
+ virtual const char * name(void) { return "interrupt"; };
+ virtual const char * type(void) { return "Interrupt"; };
+ virtual double usage_summary(void);
+ virtual const char * usage_units_summary(void);
+};
+
+extern vector <class interrupt *> all_interrupts;
+extern const char* softirqs[];
+
+
+extern class interrupt * find_create_interrupt(const char *_handler, int nr, int cpu);
+extern void all_interrupts_to_all_power(void);
+extern void clear_interrupts(void);
+
+#endif
diff --git a/src/process/powerconsumer.cpp b/src/process/powerconsumer.cpp
new file mode 100644
index 0000000..2ff2132
--- /dev/null
+++ b/src/process/powerconsumer.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+
+#include "powerconsumer.h"
+#include "process.h"
+#include "../parameters/parameters.h"
+
+double power_consumer::Witts(void)
+{
+ double cost;
+ double timecost;
+ double wakeupcost;
+ double gpucost;
+ double disk_cost;
+ double hard_disk_cost;
+ double xwake_cost;
+
+ if (child_runtime > accumulated_runtime)
+ child_runtime = 0;
+
+ timecost = get_parameter_value("cpu-consumption");
+ wakeupcost = get_parameter_value("cpu-wakeups");
+ gpucost = get_parameter_value("gpu-operations");
+ disk_cost = get_parameter_value("disk-operations");
+ hard_disk_cost = get_parameter_value("disk-operations-hard");
+ xwake_cost = get_parameter_value("xwakes");
+
+ cost = 0;
+
+ cost += wakeupcost * wake_ups / 10000.0;
+ cost += ( (accumulated_runtime - child_runtime) / 1000000000.0) * timecost;
+ cost += gpucost * gpu_ops / 100.0;
+ cost += hard_disk_cost * hard_disk_hits / 100.0;
+ cost += disk_cost * disk_hits / 100.0;
+ cost += xwake_cost * xwakes / 100.0;
+
+ cost = cost / measurement_time;
+
+ cost += power_charge;
+
+ return cost;
+}
+
+power_consumer::power_consumer(void)
+{
+ accumulated_runtime = 0;
+ child_runtime = 0;
+ disk_hits = 0;
+ wake_ups = 0;
+ gpu_ops = 0;
+ hard_disk_hits = 0;
+ xwakes = 0;
+ waker = NULL;
+ last_waker = NULL;
+ power_charge = 0.0;
+}
+
+double power_consumer::usage(void)
+{
+ double t;
+ t = (accumulated_runtime - child_runtime) / 1000000.0 / measurement_time;
+ if (t < 0.7)
+ t = t * 1000;
+ return t;
+}
+
+const char * power_consumer::usage_units(void)
+{
+ double t;
+ t = (accumulated_runtime - child_runtime) / 1000000.0 / measurement_time;
+ if (t < 0.7) {
+ if (utf_ok)
+ return " µs/s";
+ else
+ return " us/s";
+ }
+ return " ms/s";
+}
diff --git a/src/process/powerconsumer.h b/src/process/powerconsumer.h
new file mode 100644
index 0000000..0ae384a
--- /dev/null
+++ b/src/process/powerconsumer.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef __INCLUDE_GUARD_POWER_CONSUMER_
+#define __INCLUDE_GUARD_POWER_CONSUMER_
+
+#include <stdint.h>
+#include <vector>
+#include <algorithm>
+
+using namespace std;
+
+extern double measurement_time;
+
+class power_consumer;
+
+class power_consumer {
+
+public:
+ uint64_t accumulated_runtime;
+ uint64_t child_runtime;
+ int disk_hits;
+ int wake_ups;
+ int gpu_ops;
+ int hard_disk_hits; /* those which are likely a wakeup of the disk */
+ int xwakes;
+
+ double power_charge; /* power consumed by devices opened by this process */
+ class power_consumer *waker;
+ class power_consumer *last_waker;
+
+ power_consumer(void);
+ virtual ~power_consumer() {};
+
+ virtual double Witts(void);
+ virtual const char * description(void) { return ""; };
+
+ virtual const char * name(void) { return "abstract"; };
+ virtual const char * type(void) { return "abstract"; };
+
+ virtual double usage(void);
+ virtual const char * usage_units(void);
+
+ virtual double usage_summary(void) { return usage();};
+ virtual const char * usage_units_summary(void) { return usage_units(); };
+ virtual double events(void) { return (wake_ups + gpu_ops + hard_disk_hits) / measurement_time;};
+ virtual int show_events(void) { return 1; };
+};
+
+extern vector <class power_consumer *> all_power;
+
+extern double total_wakeups(void);
+extern double total_cpu_time(void);
+extern double total_gpu_ops(void);
+
+
+
+#endif \ No newline at end of file
diff --git a/src/process/process.cpp b/src/process/process.cpp
new file mode 100644
index 0000000..dad90ba
--- /dev/null
+++ b/src/process/process.cpp
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+
+
+
+#include "process.h"
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <iostream>
+#include <fstream>
+#include <algorithm>
+#include <iterator>
+#include "../lib.h"
+
+
+vector <class process *> all_processes;
+
+void process::account_disk_dirty(void)
+{
+ disk_hits++;
+}
+
+void process::schedule_thread(uint64_t time, int thread_id)
+{
+ running_since = time;
+ running = 1;
+}
+
+
+uint64_t process::deschedule_thread(uint64_t time, int thread_id)
+{
+ uint64_t delta;
+
+ if (!running_since)
+ return 0;
+
+ delta = time - running_since;
+
+ if (time < running_since)
+ printf("%llu time %llu since \n", (unsigned long long)time,
+ (unsigned long long)running_since);
+
+ if (thread_id == 0) /* idle thread */
+ delta = 0;
+ accumulated_runtime += delta;
+ running = 0;
+
+ return delta;
+}
+
+static void cmdline_to_string(std::string& str)
+{
+ std::replace(str.begin(), str.end(), '\0', ' ');
+}
+
+
+process::process(const char *_comm, int _pid, int _tid) : power_consumer()
+{
+ char line[4097];
+ ifstream file;
+ ssize_t pos;
+
+ pt_strcpy(comm, _comm);
+ pid = _pid;
+ is_idle = 0;
+ running = 0;
+ last_waker = NULL;
+ waker = NULL;
+ is_kernel = 0;
+ tgid = _tid;
+
+ if (_tid == 0) {
+ sprintf(line, "/proc/%i/status", _pid);
+ file.open(line);
+ while (file) {
+ file.getline(line, 4096);
+ line[4096] = '\0';
+ if (strstr(line, "Tgid")) {
+ char *c;
+ c = strchr(line, ':');
+ if (!c)
+ continue;
+ c++;
+ tgid = strtoull(c, NULL, 10);
+ break;
+ }
+ }
+ file.close();
+ }
+
+ if (strncmp(_comm, "kondemand/", 10) == 0)
+ is_idle = 1;
+
+ pos = snprintf(desc, sizeof(desc), "[PID %d] ", pid);
+
+ if (pos < 0)
+ pos = 0;
+ if ((size_t)pos > sizeof(desc))
+ return;
+
+ strncpy(desc + pos, comm, sizeof(desc) - pos - 1);
+ desc[sizeof(desc) - 1] = '\0';
+
+ sprintf(line, "/proc/%i/cmdline", _pid);
+ file.open(line, ios::binary);
+ if (file) {
+ std::string cmdline(std::istreambuf_iterator<char>(file), (std::istreambuf_iterator<char>()));
+ file.close();
+ if (cmdline.size() < 1) {
+ is_kernel = 1;
+ snprintf(desc + pos, sizeof(desc) - pos, "[%s]", comm);
+ } else {
+ cmdline_to_string(cmdline);
+ strncpy(desc + pos, cmdline.c_str(), sizeof(desc) - pos - 1);
+ desc[sizeof(desc) - 1] = '\0';
+ }
+ }
+}
+
+const char * process::description(void)
+{
+
+ if (child_runtime > accumulated_runtime)
+ child_runtime = 0;
+
+ return desc;
+}
+
+double process::usage_summary(void)
+{
+ double t;
+ t = (accumulated_runtime - child_runtime) / 1000000.0 / measurement_time / 10;
+ return t;
+}
+
+const char * process::usage_units_summary(void)
+{
+ return "%";
+}
+
+class process * find_create_process(const char *comm, int pid)
+{
+ unsigned int i;
+ class process *new_proc;
+
+ for (i = 0; i < all_processes.size(); i++) {
+ if (all_processes[i]->pid == pid && strcmp(comm, all_processes[i]->comm) == 0)
+ return all_processes[i];
+ }
+
+ new_proc = new class process(comm, pid);
+ all_processes.push_back(new_proc);
+ return new_proc;
+}
+
+class process * find_create_process(char *comm, int pid)
+{
+ return find_create_process((const char*)comm, pid);
+}
+
+static void merge_process(class process *one, class process *two)
+{
+ one->accumulated_runtime += two->accumulated_runtime;
+ one->child_runtime += two->child_runtime;
+ one->wake_ups += two->wake_ups;
+ one->disk_hits += two->disk_hits;
+ one->hard_disk_hits += two->hard_disk_hits;
+ one->xwakes += two->xwakes;
+ one->gpu_ops += two->gpu_ops;
+ one->power_charge += two->power_charge;
+}
+
+
+void merge_processes(void)
+{
+ std::vector<class process*>::iterator it1, it2;
+ class process *one, *two;
+
+ it1 = all_processes.begin();
+ while (it1 != all_processes.end()) {
+ it2 = it1 + 1;
+ one = *it1;
+ while (it2 != all_processes.end()) {
+ two = *it2;
+ /* fold threads */
+ if (one->pid == two->tgid && two->tgid != 0) {
+ merge_process(one, two);
+ delete *it2;
+ it2 = all_processes.erase(it2);
+ continue;
+ }
+ /* find dupes and add up */
+ if (!strcmp(one->desc, two->desc)) {
+ merge_process(one, two);
+ delete *it2;
+ it2 = all_processes.erase(it2);
+ continue;
+ }
+ ++it2;
+ }
+ ++it1;
+ }
+}
+
+void all_processes_to_all_power(void)
+{
+ unsigned int i;
+ for (i = 0; i < all_processes.size() ; i++)
+ if (all_processes[i]->accumulated_runtime ||
+ all_processes[i]->power_charge)
+ all_power.push_back(all_processes[i]);
+}
+
+void clear_processes(void)
+{
+ std::vector <class process *>::iterator it = all_processes.begin();
+ while (it != all_processes.end()) {
+ delete *it;
+ it = all_processes.erase(it);
+ }
+}
diff --git a/src/process/process.h b/src/process/process.h
new file mode 100644
index 0000000..66293f7
--- /dev/null
+++ b/src/process/process.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_PROCESS_H
+#define _INCLUDE_GUARD_PROCESS_H
+
+#include <stdint.h>
+
+#include "powerconsumer.h"
+
+#ifdef __x86_64__
+#define BIT64 1
+#endif
+
+/*
+Need to collect
+ * CPU time consumed by each application
+ * Number of wakeups out of idle -- received and wakeups sent
+ * Number of disk dirties (inode for now)
+ */
+class process : public power_consumer {
+ uint64_t running_since;
+public:
+ char desc[256];
+ int tgid;
+ char comm[16];
+ int pid;
+
+
+ int is_idle; /* count this as if the cpu was idle */
+ int running;
+ int is_kernel; /* kernel thread */
+
+ process(const char *_comm, int _pid, int _tid = 0);
+
+ virtual void schedule_thread(uint64_t time, int thread_id);
+ virtual uint64_t deschedule_thread(uint64_t time, int thread_id = 0);
+
+ virtual void account_disk_dirty(void);
+
+ virtual const char * description(void);
+ virtual const char * name(void) { return "process"; };
+ virtual const char * type(void) { return "Process"; };
+
+ virtual double usage_summary(void);
+ virtual const char * usage_units_summary(void);
+
+};
+
+extern vector <class process *> all_processes;
+
+extern double measurement_time;
+
+
+extern void start_process_measurement(void);
+extern void end_process_measurement(void);
+extern void process_process_data(void);
+extern void end_process_data(void);
+extern void clear_process_data(void);
+extern void merge_processes(void);
+
+extern class process * find_create_process(const char *comm, int pid);
+extern class process * find_create_process(char *comm, int pid);
+extern void all_processes_to_all_power(void);
+
+extern void clear_processes(void);
+extern void process_update_display(void);
+extern void report_process_update_display(void);
+extern void report_summary(void);
+
+
+
+extern void clear_timers(void);
+
+#endif
diff --git a/src/process/processdevice.cpp b/src/process/processdevice.cpp
new file mode 100644
index 0000000..00f48c8
--- /dev/null
+++ b/src/process/processdevice.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include "processdevice.h"
+#include "../parameters/parameters.h"
+#include <stdio.h>
+
+vector<class device_consumer *> all_proc_devices;
+
+
+device_consumer::device_consumer(class device *dev) : power_consumer()
+{
+ device = dev;
+ power = device->power_usage(&all_results, &all_parameters);
+ prio = dev->grouping_prio();
+}
+
+
+const char * device_consumer::description(void)
+{
+ snprintf(str, sizeof(str), "%s", device->human_name());
+ return str;
+}
+
+double device_consumer::Witts(void)
+{
+ return power;
+}
+
+static void add_device(class device *device)
+{
+ class device_consumer *dev;
+ unsigned int i;
+
+ /* first check if we want to be shown at all */
+
+ if (device->show_in_list() == 0)
+ return;
+
+ /* then check if a device with the same underlying object is already registered */
+ for (i = 0; i < all_proc_devices.size(); i++) {
+ class device_consumer *cdev;
+ cdev = all_proc_devices[i];
+ if (device->real_path[0] != 0 && strcmp(cdev->device->real_path, device->real_path) == 0) {
+ /* we have a device with the same underlying object */
+
+ /* aggregate the power */
+ cdev->power += device->power_usage(&all_results, &all_parameters);
+
+ if (cdev->prio < device->grouping_prio()) {
+ cdev->device = device;
+ cdev->prio = device->grouping_prio();
+ }
+
+ return;
+ }
+ }
+
+ dev = new class device_consumer(device);
+ all_power.push_back(dev);
+ all_proc_devices.push_back(dev);
+}
+
+void all_devices_to_all_power(void)
+{
+ unsigned int i;
+ for (i = 0; i < all_devices.size(); i++)
+ add_device(all_devices[i]);
+}
+
+void clear_proc_devices(void)
+{
+ std::vector<class device_consumer *>::iterator it = all_proc_devices.begin();
+ while (it != all_proc_devices.end()) {
+ delete *it;
+ it = all_proc_devices.erase(it);
+ }
+}
diff --git a/src/process/processdevice.h b/src/process/processdevice.h
new file mode 100644
index 0000000..3392d3e
--- /dev/null
+++ b/src/process/processdevice.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_DEVICE2_H
+#define _INCLUDE_GUARD_DEVICE2_H
+
+#include <stdint.h>
+
+#include "powerconsumer.h"
+#include "../devices/device.h"
+
+class device_consumer : public power_consumer {
+ char str[4096];
+public:
+ int prio;
+ double power;
+ class device *device;
+ device_consumer(class device *dev);
+
+ virtual const char * description(void);
+ virtual const char * name(void) { return "device"; };
+ virtual const char * type(void) { return "Device"; };
+ virtual double Witts(void);
+ virtual double usage(void) { return device->utilization();};
+ virtual const char * usage_units(void) {return device->util_units();};
+ virtual int show_events(void) { return 0; };
+};
+
+extern void all_devices_to_all_power(void);
+extern vector<class device_consumer *> all_proc_devices;
+
+extern void clear_proc_devices(void);
+
+#endif
diff --git a/src/process/timer.cpp b/src/process/timer.cpp
new file mode 100644
index 0000000..5d9d2f8
--- /dev/null
+++ b/src/process/timer.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <map>
+#include <utility>
+
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "timer.h"
+#include "../lib.h"
+#include "process.h"
+
+using namespace std;
+
+static bool timer_is_deferred(const char *handler)
+{
+ FILE *file;
+ bool ret = false;
+ char line[4096];
+
+ file = fopen("/proc/timer_stats", "r");
+ if (!file) {
+ return ret;
+ }
+
+ while (!feof(file)) {
+ if (fgets(line, 4096, file) == NULL)
+ break;
+ if (strstr(line, handler)) {
+ ret = (strstr(line, "D,") != NULL);
+ if (ret == true)
+ break;
+ }
+ }
+ fclose(file);
+ return ret;
+}
+
+timer::timer(unsigned long address) : power_consumer()
+{
+ pt_strcpy(handler, kernel_function(address));
+ raw_count = 0;
+ deferred = timer_is_deferred(handler);
+}
+
+
+static map<unsigned long, class timer *> all_timers;
+static map<unsigned long, uint64_t> running_since;
+
+void timer::fire(uint64_t time, uint64_t timer_struct)
+{
+ running_since[timer_struct] = time;
+}
+
+uint64_t timer::done(uint64_t time, uint64_t timer_struct)
+{
+ int64_t delta;
+
+ if (running_since.find(timer_struct) == running_since.end())
+ return ~0ULL;
+
+ if (running_since[timer_struct] > time)
+ return 0;
+
+ delta = time - running_since[timer_struct];
+
+ accumulated_runtime += delta;
+
+ raw_count++;
+
+ return delta;
+}
+
+double timer::usage_summary(void)
+{
+ double t;
+ t = (accumulated_runtime - child_runtime) / 1000000.0 / measurement_time / 10;
+ return t;
+}
+
+const char * timer::usage_units_summary(void)
+{
+ return "%";
+}
+
+
+
+static void add_timer(const pair<unsigned long, class timer*>& elem)
+{
+ all_power.push_back(elem.second);
+}
+
+void all_timers_to_all_power(void)
+{
+ for_each(all_timers.begin(), all_timers.end(), add_timer);
+
+}
+
+
+const char * timer::description(void)
+{
+ if (child_runtime > accumulated_runtime)
+ child_runtime = 0;
+
+ snprintf(desc, sizeof(desc), "%s", handler);
+ return desc;
+}
+
+
+class timer * find_create_timer(uint64_t func)
+{
+ class timer * timer;
+ if (all_timers.find(func) != all_timers.end())
+ return all_timers[func];
+
+ timer = new class timer(func);
+ all_timers[func] = timer;
+ return timer;
+
+}
+
+void clear_timers(void)
+{
+ std::map<unsigned long, class timer *>::iterator it = all_timers.begin();
+ while (it != all_timers.end()) {
+ delete it->second;
+ all_timers.erase(it);
+ it = all_timers.begin();
+ }
+ running_since.clear();
+}
+
+bool timer::is_deferred(void)
+{
+ return deferred;
+}
diff --git a/src/process/timer.h b/src/process/timer.h
new file mode 100644
index 0000000..7718c3b
--- /dev/null
+++ b/src/process/timer.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_TIMER_H
+#define _INCLUDE_GUARD_TIMER_H
+
+#include <stdint.h>
+
+#include "powerconsumer.h"
+
+class timer : public power_consumer {
+ char desc[256];
+public:
+ char handler[32];
+ int raw_count;
+ bool deferred;
+
+ timer(unsigned long timer_func);
+
+ void fire(uint64_t time, uint64_t timer_struct);
+ uint64_t done(uint64_t time, uint64_t timer_struct);
+ bool is_deferred(void);
+
+ virtual const char * description(void);
+ virtual const char * name(void) { return "timer"; };
+ virtual const char * type(void) { return "Timer"; };
+ virtual double usage_summary(void);
+ virtual const char * usage_units_summary(void);
+
+};
+
+class timer_list {
+public:
+ uint64_t timer_address;
+ uint64_t timer_func;
+};
+
+
+extern void all_timers_to_all_power(void);
+extern class timer * find_create_timer(uint64_t func);
+extern void clear_timers(void);
+
+#endif
diff --git a/src/process/work.cpp b/src/process/work.cpp
new file mode 100644
index 0000000..1b5c71d
--- /dev/null
+++ b/src/process/work.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#include <map>
+#include <utility>
+
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "work.h"
+#include "../lib.h"
+#include "process.h"
+
+using namespace std;
+
+
+work::work(unsigned long address) : power_consumer()
+{
+ pt_strcpy(handler, kernel_function(address));
+ raw_count = 0;
+ snprintf(desc, sizeof(desc), "%s", handler);
+}
+
+
+static map<unsigned long, class work *> all_work;
+static map<unsigned long, uint64_t> running_since;
+
+void work::fire(uint64_t time, uint64_t work_struct)
+{
+ running_since[work_struct] = time;
+}
+
+uint64_t work::done(uint64_t time, uint64_t work_struct)
+{
+ int64_t delta;
+
+ if (running_since.find(work_struct) == running_since.end())
+ return ~0ULL;
+
+ if (running_since[work_struct] > time)
+ return 0;
+
+ delta = time - running_since[work_struct];
+
+ accumulated_runtime += delta;
+
+ raw_count++;
+
+ return delta;
+}
+
+double work::usage_summary(void)
+{
+ double t;
+ t = (accumulated_runtime - child_runtime) / 1000000.0 / measurement_time / 10;
+ return t;
+}
+
+const char * work::usage_units_summary(void)
+{
+ return "%";
+}
+
+
+
+
+static void add_work(const pair<unsigned long, class work*>& elem)
+{
+ all_power.push_back(elem.second);
+}
+
+void all_work_to_all_power(void)
+{
+ for_each(all_work.begin(), all_work.end(), add_work);
+
+}
+
+void clear_work(void)
+{
+ std::map<unsigned long, class work *>::iterator it = all_work.begin();
+ while (it != all_work.end()) {
+ delete it->second;
+ all_work.erase(it);
+ it = all_work.begin();
+ }
+ running_since.clear();
+}
+
+
+const char * work::description(void)
+{
+ if (child_runtime > accumulated_runtime)
+ child_runtime = 0;
+
+ return desc;
+}
+
+
+class work * find_create_work(uint64_t func)
+{
+ class work * work;
+ if (all_work.find(func) != all_work.end())
+ return all_work[func];
+
+ work = new class work(func);
+ all_work[func] = work;
+ return work;
+}
diff --git a/src/process/work.h b/src/process/work.h
new file mode 100644
index 0000000..ddd7c87
--- /dev/null
+++ b/src/process/work.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_WORK_H
+#define _INCLUDE_GUARD_WORK_H
+
+#include <stdint.h>
+
+#include "powerconsumer.h"
+
+class work : public power_consumer {
+ char desc[256];
+public:
+ char handler[32];
+ int raw_count;
+
+ work(unsigned long work_func);
+
+ void fire(uint64_t time, uint64_t work_struct);
+ uint64_t done(uint64_t time, uint64_t work_struct);
+
+ virtual const char * description(void);
+ virtual const char * name(void) { return "work"; };
+ virtual const char * type(void) { return "kWork"; };
+ virtual double usage_summary(void);
+ virtual const char * usage_units_summary(void);
+
+};
+
+
+extern void all_work_to_all_power(void);
+extern class work * find_create_work(uint64_t func);
+
+extern void clear_work(void);
+
+#endif
diff --git a/src/report/report-data-html.cpp b/src/report/report-data-html.cpp
new file mode 100644
index 0000000..d9b713e
--- /dev/null
+++ b/src/report/report-data-html.cpp
@@ -0,0 +1,128 @@
+#include "report-data-html.h"
+
+void init_div(struct tag_attr *div_attr, const char *css_class, const char *css_id)
+{
+ div_attr->css_class=css_class;
+ div_attr->css_id=css_id;
+}
+
+void
+init_top_table_attr(struct table_attributes *table_css, int rows, int cols){
+ table_css->pos_table_title=L;
+ table_css->table_class="emphasis1";
+ table_css->th_class="table_sysinfo";
+ table_css->td_class="";
+ table_css->tr_class="";
+ table_css->title_mod=0;
+ table_css->rows=rows;
+ table_css->cols=cols;
+}
+
+void init_title_attr(struct tag_attr *title_attr)
+{
+ title_attr->css_class="content_title";
+ title_attr->css_id="";
+}
+
+void init_std_table_attr(struct table_attributes *table_css, int rows, int cols){
+ table_css->table_class="emphasis2";
+ table_css->tr_class="emph1";
+ table_css->th_class="emph_title";
+ table_css->td_class="";
+ table_css->pos_table_title=T;
+ table_css->title_mod=0;
+ table_css->rows=rows;
+ table_css->cols=cols;
+}
+void init_std_side_table_attr(struct table_attributes *table_css, int rows, int cols){
+ table_css->table_class="emphasis2 side_by_side_left";
+ table_css->tr_class="emph1";
+ table_css->th_class="emph_title";
+ table_css->td_class="";
+ table_css->pos_table_title=T;
+ table_css->title_mod=0;
+ table_css->rows=rows;
+ table_css->cols=cols;
+}
+
+
+void init_pkg_table_attr(struct table_attributes *table_css, int rows, int cols){
+ table_css->table_class="emphasis2 side_by_side_left";
+ table_css->tr_class="";
+ table_css->th_class="title";
+ table_css->td_class="package";
+ table_css->pos_table_title=T;
+ table_css->title_mod=0;
+ table_css->rows=rows;
+ table_css->cols=cols;
+}
+
+void init_core_table_attr(struct table_attributes *table_css, int title_mod,
+ int rows, int cols){
+ table_css->table_class="emphasis2 side_by_side_left";
+ table_css->tr_class="";
+ table_css->th_class="title";
+ table_css->td_class="core";
+ table_css->pos_table_title=TC;
+ table_css->title_mod=title_mod;
+ table_css->rows=rows;
+ table_css->cols=cols;
+}
+
+void init_cpu_table_attr(struct table_attributes *table_css, int title_mod,
+ int rows, int cols){
+ table_css->table_class="emphasis2 side_by_side_left";
+ table_css->tr_class="";
+ table_css->th_class="title";
+ table_css->td_class="cpu";
+ table_css->pos_table_title=TLC;
+ table_css->title_mod=title_mod;
+ table_css->rows=rows;
+ table_css->cols=cols;
+}
+
+
+void init_nowarp_table_attr(struct table_attributes *table_css, int rows, int cols){
+ table_css->table_class="emphasis2";
+ table_css->tr_class="emph1";
+ table_css->th_class="emph_title";
+ table_css->td_class="no_wrap";
+ table_css->pos_table_title=T;
+ table_css->title_mod=0;
+ table_css->rows=rows;
+ table_css->cols=cols;
+}
+
+void init_tune_table_attr(struct table_attributes *table_css, int rows, int cols){
+ table_css->table_class="emphasis2";
+ table_css->tr_class="tune";
+ table_css->th_class="emph_title";
+ table_css->td_class="";
+ table_css->pos_table_title=T;
+ table_css->rows=rows;
+ table_css->cols=cols;
+}
+
+void init_wakeup_table_attr(struct table_attributes *table_css, int rows, int cols){
+ table_css->table_class="emphasis2";
+ table_css->tr_class="tune";
+ table_css->th_class="emph_title";
+ table_css->td_class="";
+ table_css->pos_table_title=T;
+ table_css->rows=rows;
+ table_css->cols=cols;
+}
+
+/* Other Helper Functions */
+string
+double_to_string(double dval)
+{
+ ostringstream dtmp;
+ string str;
+ dtmp << dval;
+ str= dtmp.str();
+ str = str.substr(0, str.find(".")+2);
+ return str;
+}
+
+
diff --git a/src/report/report-data-html.h b/src/report/report-data-html.h
new file mode 100644
index 0000000..e506f5a
--- /dev/null
+++ b/src/report/report-data-html.h
@@ -0,0 +1,76 @@
+#ifndef PowerTop_REPORT_DATA_HTML_H_C58C116411234A34AC2EFB8D23A69713
+#define PowerTop_REPORT_DATA_HTML_H_C58C116411234A34AC2EFB8D23A69713
+
+#include <string>
+#include <sstream>
+
+using namespace std;
+
+struct tag_attr {
+ const char *css_class;
+ const char *css_id;
+};
+/* T:Top, L:Left, TL:Top-Left, TLC: Top-Left-Center */
+enum position { T, L, TL, TC, TLC };
+
+struct table_attributes {
+ const char *table_class;
+ const char *td_class;
+ const char *tr_class;
+ const char *th_class;
+ position pos_table_title;
+ int title_mod;
+ int rows;
+ int cols;
+};
+
+struct table_size {
+ int rows;
+ int cols;
+};
+
+
+/* Definition of css attributes for the cases that apply to powertop
+ * html report
+ * */
+
+void
+init_div(struct tag_attr *div_attr, const char *css_class, const char *css_id);
+
+void
+init_top_table_attr(struct table_attributes *table_css, int rows, int cols);
+
+void
+init_title_attr(struct tag_attr *title_attr);
+
+void
+init_std_table_attr(struct table_attributes *table_css, int rows, int cols);
+
+void
+init_std_side_table_attr(struct table_attributes *table_css, int rows,
+ int cols);
+
+void
+init_pkg_table_attr(struct table_attributes *table_css, int rows, int cols);
+
+void
+init_core_table_attr(struct table_attributes *table_css, int title_mod,
+ int rows, int cols);
+
+void
+init_cpu_table_attr(struct table_attributes *table_css, int title_mod,
+ int rows, int cols);
+void
+init_nowarp_table_attr(struct table_attributes *table_css, int rows, int cols);
+
+void
+init_tune_table_attr(struct table_attributes *table_css, int rows, int cols);
+
+void
+init_wakeup_table_attr(struct table_attributes *table_css, int rows, int cols);
+
+/* Other helper functions */
+string
+double_to_string(double dval);
+
+#endif
diff --git a/src/report/report-formatter-base.cpp b/src/report/report-formatter-base.cpp
new file mode 100644
index 0000000..4e10603
--- /dev/null
+++ b/src/report/report-formatter-base.cpp
@@ -0,0 +1,114 @@
+/* Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Common part of report_formatter_csv and report_formatter_html.
+ * Written by Igor Zhbanov <i.zhbanov@samsung.com>
+ * 2012.10 */
+
+/* Uncomment to disable asserts */
+/*#define NDEBUG*/
+
+#include <stdio.h>
+#include <assert.h>
+#include <stdarg.h>
+
+#include "report-formatter-base.h"
+
+/* ************************************************************************ */
+
+const char *
+report_formatter_string_base::get_result()
+{
+ return result.c_str();
+}
+
+/* ************************************************************************ */
+
+void
+report_formatter_string_base::clear_result()
+{
+ result.clear();
+}
+
+/* ************************************************************************ */
+
+void
+report_formatter_string_base::add(const char *str)
+{
+ assert(str);
+
+ result += escape_string(str);
+}
+
+/* ************************************************************************ */
+
+void
+report_formatter_string_base::add_exact(const char *str)
+{
+ assert(str);
+
+ result += std::string(str);
+}
+
+/* ************************************************************************ */
+
+#define LINE_SIZE 8192
+
+void
+report_formatter_string_base::addv(const char *fmt, va_list ap)
+{
+ char str[LINE_SIZE];
+
+ assert(fmt);
+
+ vsnprintf(str, sizeof(str), fmt, ap);
+ add(str);
+}
+
+/* ************************************************************************ */
+
+void
+report_formatter_string_base::addf(const char *fmt, ...)
+{
+ va_list ap;
+
+ assert(fmt);
+
+ va_start(ap, fmt);
+ addv(fmt, ap);
+ va_end(ap);
+}
+
+/* ************************************************************************ */
+
+void
+report_formatter_string_base::addf_exact(const char *fmt, ...)
+{
+ char str[LINE_SIZE];
+ va_list ap;
+
+ assert(fmt);
+
+ va_start(ap, fmt);
+ vsnprintf(str, sizeof(str), fmt, ap);
+ add_exact(str);
+ va_end(ap);
+}
diff --git a/src/report/report-formatter-base.h b/src/report/report-formatter-base.h
new file mode 100644
index 0000000..e35a2ff
--- /dev/null
+++ b/src/report/report-formatter-base.h
@@ -0,0 +1,52 @@
+/* Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Common part of report_formatter_csv and report_formatter_html.
+ * Written by Igor Zhbanov <i.zhbanov@samsung.com>
+ * 2012.10 */
+
+#ifndef _REPORT_FORMATTER_BASE_H_
+#define _REPORT_FORMATTER_BASE_H_
+
+#include "report-formatter.h"
+
+class report_formatter_string_base: public report_formatter
+{
+public:
+ virtual const char *get_result();
+ virtual void clear_result();
+
+ virtual void add(const char *str);
+ virtual void addv(const char *fmt, va_list ap);
+
+protected:
+ void add_exact(const char *str);
+ void addf(const char *fmt, ...)
+ __attribute__ ((format (printf, 2, 3)));
+ void addf_exact(const char *fmt, ...)
+ __attribute__ ((format (printf, 2, 3)));
+
+ virtual std::string escape_string(const char *str) = 0;
+
+ std::string result;
+};
+
+#endif /* _REPORT_FORMATTER_BASE_H_ */
diff --git a/src/report/report-formatter-csv.cpp b/src/report/report-formatter-csv.cpp
new file mode 100644
index 0000000..0360fd8
--- /dev/null
+++ b/src/report/report-formatter-csv.cpp
@@ -0,0 +1,163 @@
+/* Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * CSV report generator.
+ * Written by Igor Zhbanov <i.zhbanov@samsung.com>
+ * 2012.10 */
+
+/* Uncomment to disable asserts */
+/*#define NDEBUG*/
+
+#include <stdio.h>
+#include <assert.h>
+#include <stdarg.h>
+
+#include "report-formatter-csv.h"
+#include "report-data-html.h"
+
+
+/* ************************************************************************ */
+report_formatter_csv::report_formatter_csv()
+{
+ /* Do nothing special */
+}
+
+/* ************************************************************************ */
+void
+report_formatter_csv::finish_report()
+{
+ /* Do nothing special */
+}
+
+
+string
+report_formatter_csv::escape_string(const char *str)
+{
+ string res;
+
+ assert(str);
+
+ for (const char *i = str; *i; i++) {
+ switch (*i) {
+ case '"':
+ res += '"';
+#ifdef REPORT_CSV_SPACE_NEED_QUOTES
+ case ' ':
+#endif /* REPORT_CSV_SPACE_NEED_QUOTES */
+ case '\n':
+ case REPORT_CSV_DELIMITER:
+ csv_need_quotes = true;
+ break;
+ }
+
+ res += *i;
+ }
+
+ return res;
+}
+
+
+
+
+/* Report Style */
+void
+report_formatter_csv::add_header()
+{
+ add_exact("____________________________________________________________________\n");
+}
+
+void
+report_formatter_csv::end_header()
+{
+ /* Do nothing */
+}
+
+void
+report_formatter_csv::add_logo()
+{
+ add_exact("\t\t\tP o w e r T O P\n");
+}
+
+
+void
+report_formatter_csv::add_div(struct tag_attr * div_attr)
+{
+ add_exact("\n");
+}
+
+void
+report_formatter_csv::end_div()
+{
+ /*Do nothing*/
+}
+
+void
+report_formatter_csv::add_title(struct tag_attr *title_att, const char *title)
+{
+ add_exact("____________________________________________________________________\n");
+ addf_exact(" * * * %s * * *\n", title);
+}
+
+void
+report_formatter_csv::add_navigation()
+{
+ /* No nav in csv - thinking on table of contents */
+}
+
+void
+report_formatter_csv::add_summary_list(string *list, int size)
+{
+ int i;
+ add_exact("\n");
+ for (i=0; i < size; i+=2){
+ addf_exact("%s %s", list[i].c_str(), list[i+1].c_str());
+ if(i < (size - 1))
+ add_exact(";");
+ }
+ add_exact("\n");
+}
+
+void
+report_formatter_csv::add_table(string *system_data, struct table_attributes* tb_attr)
+{
+ int i, j;
+ int offset=0;
+ string tmp_str="";
+ int empty_row=0;
+ add_exact("\n");
+ for (i=0; i < tb_attr->rows; i++){
+ for (j=0; j < tb_attr->cols; j++){
+ offset = i * (tb_attr->cols) + j;
+ tmp_str=system_data[offset];
+
+ if(tmp_str == "&nbsp;")
+ empty_row+=1;
+ else{
+ addf_exact("%s", system_data[offset].c_str());
+ if(j < (tb_attr->cols - 1))
+ add_exact(";");
+ }
+ }
+ if(empty_row < tb_attr->cols)
+ add_exact("\n");
+ empty_row=0;
+ }
+}
diff --git a/src/report/report-formatter-csv.h b/src/report/report-formatter-csv.h
new file mode 100644
index 0000000..7edfc01
--- /dev/null
+++ b/src/report/report-formatter-csv.h
@@ -0,0 +1,73 @@
+/* Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * CSV report generator.
+ * Written by Igor Zhbanov <i.zhbanov@samsung.com>
+ * 2012.10 */
+
+#ifndef _REPORT_FORMATTER_CSV_H_
+#define _REPORT_FORMATTER_CSV_H_
+
+#include <string>
+
+#include "report-formatter-base.h"
+
+/* Offices like semicolon separated values instead of comma */
+#define REPORT_CSV_DELIMITER ','
+
+/* "a,b,c" vs "a, b, c" */
+/*#define REPORT_CSV_ADD_SPACE*/
+
+/* Whether to escape with quotes empty cell values */
+/*#define REPORT_CSV_ESCAPE_EMPTY*/
+
+/* Whether to escape with quotes empty cell values with spaces */
+/*#define REPORT_CSV_SPACE_NEED_QUOTES*/
+
+using namespace std;
+
+/* ************************************************************************ */
+
+class report_formatter_csv: public report_formatter_string_base
+{
+public:
+ report_formatter_csv();
+ void finish_report();
+
+ /* Report Style */
+ void add_logo();
+ void add_header();
+ void end_header();
+ void add_div(struct tag_attr *div_attr);
+ void end_div();
+ void add_title(struct tag_attr *title_att, const char *title);
+ void add_navigation();
+ void add_summary_list(string *list, int size);
+ void add_table(string *system_data, struct table_attributes *tb_attr);
+
+private:
+ void add_quotes();
+ string escape_string(const char *str);
+ bool csv_need_quotes;
+ size_t text_start;
+};
+
+#endif /* _REPORT_FORMATTER_CSV_H_ */
diff --git a/src/report/report-formatter-html.cpp b/src/report/report-formatter-html.cpp
new file mode 100644
index 0000000..387bd76
--- /dev/null
+++ b/src/report/report-formatter-html.cpp
@@ -0,0 +1,376 @@
+/* Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * HTML report generator.
+ * Written by Igor Zhbanov <i.zhbanov@samsung.com>
+ * 2012.10 */
+
+/* Uncomment to disable asserts */
+/*#define NDEBUG*/
+
+#include <stdio.h>
+#include <assert.h>
+#include <stdarg.h>
+
+#include "report-formatter-html.h"
+#include "css.h" /* For HTML-report header */
+
+/* ************************************************************************ */
+
+#ifdef EXTERNAL_CSS_FILE /* Where is it defined? */
+static const char report_html_alternative_head[] =
+ "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" "
+ "\"http://www.w3.org/TR/html4/loose.dtd\">\n"
+ "<html>\n"
+ "<head>\n"
+ "<title>PowerTOP report</title>\n"
+ "<link rel=\"stylesheet\" href=\"powertop.css\">\n"
+ "</head>\n"
+ "<body>\n";
+#endif /* EXTERNAL_CSS_FILE */
+
+/* ************************************************************************ */
+
+static const char report_html_footer[] =
+ "</body>\n"
+ "</html>\n";
+
+/* ************************************************************************ */
+
+void
+report_formatter_html::init_markup()
+{
+ /*here all html code*/
+}
+
+/* ************************************************************************ */
+
+report_formatter_html::report_formatter_html()
+{
+ init_markup();
+ add_doc_header();
+}
+
+/* ************************************************************************ */
+
+void
+report_formatter_html::finish_report()
+{
+ add_doc_footer();
+}
+
+/* ************************************************************************ */
+
+void
+report_formatter_html::add_doc_header()
+{
+#ifdef EXTERNAL_CSS_FILE /* Where is it defined? */
+ add_exact(report_html_alternative_head);
+#else /* !EXTERNAL_CSS_FILE */
+ add_exact(css);
+#endif /* !EXTERNAL_CSS_FILE */
+}
+
+/* ************************************************************************ */
+
+void
+report_formatter_html::add_doc_footer()
+{
+ add_exact(report_html_footer);
+}
+
+/* ************************************************************************ */
+string
+report_formatter_html::escape_string(const char *str)
+{
+ string res;
+
+ assert(str);
+
+ for (const char *i = str; *i; i++) {
+ switch (*i) {
+ case '<':
+ res += "&lt;";
+ continue;
+ case '>':
+ res += "&gt;";
+ continue;
+ case '&':
+ res += "&amp;";
+ continue;
+#ifdef REPORT_HTML_ESCAPE_QUOTES
+ case '"':
+ res += "&quot;";
+ continue;
+ case '\'':
+ res += "&apos;";
+ continue;
+#endif /* REPORT_HTML_ESCAPE_QUOTES */
+ }
+
+ res += *i;
+ }
+
+ return res;
+}
+
+
+/* Report Style */
+void
+report_formatter_html::add_logo()
+{
+ add_exact("<img alt=\"PowerTop\" class=\"pwtop_logo\" src=\"data:image/png;base64,"
+ "iVBORw0KGgoAAAANSUhEUgAAAbQAAABDCAYAAAD01PBTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA"
+ "GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAGsxJREFUeNrsXQt4FNXZ/nLhmutq"
+ "VdAKMXJHTMhiLGAuLUEfSg2xSFSUgIkkRPQ3QiHxqcRwswQrRq2EBKjhapvU3yCgtaQ+CRGUSyAB"
+ "vNDfRhArqEA2FwjksvnPN0xokpnZPWd2dnd297w851kyt3OZ+c4773e+c8aro6MDODg4ODg4XB3e"
+ "vAk4ODg4ODihcXBwcHBwcELj4ODg4ODQDr68CWxCrPgbTlJwj33l4m81SSbeVBwcHBz2hRcPCqEG"
+ "ElaCSGKYBldXV4PJZILO325MF3uN68LDwyE4OLheJLjOVM2bk4ODg4MTmqMxB4mMENa08vJyKC0t"
+ "FQispqaG+gKDBw8WiA1JLiEhAUJCQk6TzXkklZJ0ijcxBwcHByc0e6qxDEyExILy8vJgx44dml08"
+ "LCwMMjIyBHIj6m0T2ZTDiY2Dwz3xzsEbM3tsWkV5ahVJJV3/fizyQhlvURsJzcvLaw/5iXNQmcrE"
+ "dP1vUsYqRzUIyQuJLKeoqCho6dKlcPr0abvlFRQUJBDbc88910lsGaStVY23kfMyGQwFcQOpa52K"
+ "fIrJzwwVRVSbXwH5SdU6Hwc/0ywoIeVP1FHZe3aqNtsj6eDVPkMOvxeEQBJV1A+fVyPjc8uCWpIK"
+ "8V6Q8mnaN5KyO7Wvt7U+egwKievZoMSAQTQqNPYSe2Ta3t6OgR1FFRUVYcnJyXYlsk7U19cDkiYq"
+ "wOzs7NmE2HCMbo6Pj0+pyoeDBaFiZwUqzlMDo4oysuZXpYY0dQa9ld8oJi3t0eAi96JWhRJb5YBy"
+ "hXbmQ/JEG84lRFDigs+6pK8n9bn+bKmpkyuF7eMbXTExpsMkGTUls7b2DFOd6eiC5xeETZo0iZrM"
+ "vG+6EXxHD4e+UydD34d+DYFD7oDFixZD9pJsiI+Ph+joaGpiW7hwIURERATVVNe8R8pTSlIwo7Ks"
+ "YuwMbSEmR57HUk53cMfUuqA9xtnxnur+5YJ0wjNIuuggMpOzq2JUViSFgntghlinwyQx9RuuGLaP"
+ "FUQjSiOdeKGtF2trayuqqamZPX36dKtE5tW/H/SOjIBe946FXqNHgJdf/277J9x4C6yceL/kPKL6"
+ "hITjcMeOHVO8Pu4zjjPCxo0bpyUlJZWTss3x9fVliYisZSAO5offxhcJNfkZWBWaGxhznQva4x5G"
+ "ezS4y73QkfsUXyr+TcqT6KJqTbGvJ3VKI3WierZceWJ1ATEi1Q9Sa2trMEnVmzZtmm1NlaEK83sm"
+ "BQxb3gK/Z1MEUutJZohdsVNRKUkSKrUlS5bA4cOH4dChQzBr1iyLZUtJSYHk5OQwcm45KWO4nRSK"
+ "GnIKtfHhtHd+tW5gxHUeYI8u73IknawBFQTobyywWCYIxdVRgCrY3QkNsUp8i2fC1atXg81mczkh"
+ "s7CnnnpKcPnJwSfkdghYthgCl2VCn19OpLo2ua7FNGbMGFi/fj2cPHkSnnjiCcXrbNmyBUkt6MKF"
+ "CxWkvLSkxqJQ1JCTLQrNqOJesZSxzpHBQ5zQFEnNYEXRhLrJvdhjoz3YtV90Q1LDOlntP1yd0NA4"
+ "mCOJUPls3rw5bO7cubL70bXY/8nHIOjVpYJrkRY/f2CSrEKTS4MGDRKI7aOPPhL+L4etW7dCampq"
+ "IJb3ypUrNKRWxth2jlRoas73tPEzV1eZBgp7dHlCIx3rKh2TWVcCMIL7gKqvd4elr7CSubQHNzc3"
+ "FxH1E5aWlqaoyvyfSQGfOwYxF+TurOeBdV5fVFQUHDhwABYtWiQQWE/s3LkTCPEGFRYWlpKyh/fr"
+ "189kgajryBtyFaWxGcixoeQclg7UVgOJY1SRLIquyk0M19WjNDOt2KOruBvhscgLtTJkNkOsIyuu"
+ "h6iT61L1VySvuC42pybgBN2P40h+dW5iG1b7endYnDiUNlih+fLljGM1NbORPGTZffRwwb2ohswQ"
+ "x1a9hqzCnIICA6GwoABW5+YqKrWVK1YMJseWUhqO5gSlIkDD0QrNHcbPwA2mHRisRD26ekAIK7Gg"
+ "PSKpTEYioyUzkfjKOs8hCedKZNlD1bhSX29NdWqt0GqJQd6p9mRiCGonJFp987906VJ4fX39a4mP"
+ "PAINDQ3ShhgxVCAztWg5eAQufvRP2Lxli8WxMUt4ev58CAwKgnnz5kn2rXz5ZbgvKiqGKLocPz+/"
+ "HI069lA7HauVwjMydhz2gE3PtJPhLHu0NOewhDZiTUG10E78rSX5aHrfxHEpFjtAIsrSKn8kNlIG"
+ "bNdihnJkknMK7aDSbGpfGyafW+zrdaXQMOyXJPQFTtb6TZ5ctyg1NRW+/fZbyb7ekWMhcOULcHF6"
+ "Mlx6c6MqMmvK/ZPwfySjlStXUo+l9UyPP/44rFu3TjYfdJOaTKaXmpqaLI2n2SswRAt/vFHr+9pZ"
+ "ZzdQNnpUi532OE6r++zi7i+WzrdESzLr0n5o34lA75o2gA5VGr7UkKR5X++tU0MqY5TXFivZ2NiY"
+ "sXfv3rDdu3dL9uGYGYbkC41x041wtXwfM6m1f3Om29+VlZWqCQ3TzJkzIT09XZIPkrFIlnkW2o5l"
+ "grWjFRr1XDYc39OBOuP47zOV5ehnRU8QFQVtvdBLkmZHMhBWB2E4JZMmQtBJxKZpX6/nMTRNIvYa"
+ "GhqCiUHmyLnxMJoRA0A655T1eyRB+EVS06ATsCmtWrUK7rrrLsl18/PzcQJ2DKlXggZtx6KYtIqY"
+ "itPiwe0Brs7sj0KtOh0XBctqKLn2VqLiWBzt8IIB9LluqaZ9va4JjVFpKL59mM3mjK1btwadOXNG"
+ "sg8JrGsACM41w3lnmNS6HzvJzNp8NJq0bds2CAwMlL5uZWbi/jwLRaB1OxoY5obREFqhLffKhk6R"
+ "KzT722MdYwfqTuoM60M7gRrbyVErdbCoNN0uBi0qzjotni29RznaVElTXV0wscQMVDs9IazB+Bup"
+ "+xbnnWFS637s0gPYnAbdfrus63Hfvn1w/NixwaR+sRp08FaJSiQ9a51ULWW+Wis0d5lQ7QqgDjhi"
+ "dBm7kzordOA4YQlDHxmn8zb2CEKzKRSbcELCrt27FdTZNIvn+o4aDv0DfFW7H63x1enT38LsJ5+A"
+ "hYueB5OpXvG4zMWZcDshtp7Iz1+H+zM0ULc0HQ+NOquivF+hGpaLRY1ycKgFi7vdYc+jSJy0L68G"
+ "nU+01mTajbc7P4XmDnPG9u3bZdWZpRVAmtIXQEvFfrjc2Cb83Tx7LpNSE1yOHWbF9Ld3/wbhY8Ph"
+ "/R0fwJ83boKhw4fA8RPHFY9fvHix1A3yl3egzlQ37cKFCyE2PiCaERolkRooA0M4oXG4IqE52v1d"
+ "Zad6uCTcltDOnz8fYjKZwj788EPJPjlXYyda8wuh5cfui3FcudTO7H60FPDxcu6ybse2tbbDbx+O"
+ "Vzx+ypQpsmNpH3zwAe5PsNGwQjU6poohX05oHO5IaFVOmJZg7/VbOaFpCNWDy9jRY4cvqfBNNwqr"
+ "5cuec+kyNH18QOZa135Z3I+WCO3KlSuS4y/8VA9r89+QPR7JDEmtJ3AaAtkfa+ODbtTomCqGfC0a"
+ "FuWYnbPeiDk8CGJACO2z6IzVatyF0DQJJNI7oVEHBsgQSiwGT/SEEpkhWt4qgA6zdC3GXgZ/5uhH"
+ "S4Q2zig/T/WVV/6oeM6jjz4qOX7//v24b5oOFFrXic00BmbU6L7X8gnVurRHWZv0gDo7nNAYFWGo"
+ "G7RznUsSmjjOYlBbyQ6zOVyO0PDjnEq4cvQL2e39lyy6Hv3YqdQskZpAQmazYtpQ8Db06dtbcl5T"
+ "YzMc+Owz2XPG/+IXErcjLuF1/Phx+OHcuViZMtTRvr1ZGtMSo9UMDIasBaFRu3gcYWikDTo0Tv92"
+ "tV6ddS1PN3rRYFEOzqqzS0+nEINVDFq0sZ4VWpzaG3ru7Lng+vqGwd99952U0BSCQVqPHIP2lnYp"
+ "mYUOBJ/B/40yxFVFOkP6LRu05ZS5SH5y/Btr1yieM2H8BMnxJ46fwH3hdlRpLO5GWiK1FhhC+3Dz"
+ "8TPHIVWtPXJVqhtC06tCi9OqrrokNHG17lVqK0n0UThGDfYELnOlSEAywSMCAT7TfYURnHwdvO4V"
+ "q+7HDiv/5qXPIyqtl+S8z/YfVDxn9F2jJcef+e4M7gu244NOYwRlKog0VAPD4+NnLmCPHBwW1Jmm"
+ "z5avzgxH7QrMtT3cHcFyX6H2uflnihdo/Uaq5nz6+HZTZ3JKD5WaHFHSfBfNeM9Y2F95sNs2dDsq"
+ "nTtq1CipQjtxQovAEFsVWq2KfPG6JbYQGp9QrVt79NT7wsdz6YlMk77e3oQmjDc4oX26vambzeZw"
+ "7OilCk35O2ftzS2SbX1uu8lipuh+bP5rKbSfOiMhM1y6yhrGR0ZJCA3x+eefw8iRIyXbAwICJNuQ"
+ "uJXywg6f3A80MmsuPKMNaklupXtbIx1Zpglw6M8e3aljd6cxNCSSULkPl6p5tsi1nN7X94Q7zEOT"
+ "Ln3Uwd7ObVdapY1z60CL53S6H/slTpNjE6vp3shI2esKwSwyx1++dElJqqh+ADRQaFUyRFpLYdxx"
+ "CqqANviAuxv1ixLeBBz26OvFdR/dmtByZTpU2U6+7V/Xgstw7Kvr+JfSOFjTJ0fAGGCAvuu2XD8H"
+ "/4/buv49sE/fbuc1trVC0rPz4fZBg4R0qOFit7/x/7gNPzYqh+J3C8F09RA8k5F0/Rz8+72dm2S4"
+ "rM2ae5NGyRjk1t6jXNGjViXhGBTW++MTql0bZeILDQeH3fv6nvB18QqiCiiUIzS5Lv6p8VGQZfwV"
+ "wKlT3XcU/QoGh4RIjn/44Yfh1WFjAda/Lb1Yl2u8lpcHXZe+P9ncBGeTHoIbSBLyPXkEoMvfNeI2"
+ "DCxpzF4tufT0+U1w/OJceCQTSLpB2IZ/j/9tO+z43x6kAz7WCI3lUzK1KsilzALhzLBTnpzQXLjT"
+ "ccE+hhbOCounjl7UyN2om77e3RRamtx8F7O5Q7aT7927t7BPLvn28pEc/58fvlE8vmvq6NDWlezn"
+ "L39bmhqlY2UdYn2VwLBQcagC4ViEhcAMtUtg0RhnHVcBukSJ+HFeT4WBPwL26+tpJpG7skJDMpP1"
+ "1ROKMckFUOBEZHntBsJE57bW5m7bTn75teLxWqDtxEnZ7YOH+TBdh6KMtRTkZFBBLlVW8lRDojSd"
+ "giM7TVyN5E7en1Ap5jTeDBx2IjOqcVlvFzWcyaSTKbSgGqrlQty/+OILxaWlQkJ/Ljn+4vl6IYqQ"
+ "5gvTatBy8Ihk288GKN+S0/+STvzGaEisrwYEYFSh0Mos3AOaCdZxKhUadzfqT5mNc9NlyFg8AXp3"
+ "ObqaV0Po6wmZUX8t3ZUIDRk6UTQcix10h9lsuvXWW+UJTWE5qrFh8usrrs1/0+IyVpjURFWafzwv"
+ "CfdHjDL2YiK0QKJEsb4aEEA38qKMNrTWgdEEhhgYSZQTmn5QJr5cJrpxHd1pDM1VXjiEvp4Q2TiS"
+ "mLwxenQ5VkH3sN8y1gm0dw4ZUi2nmhobGwGXw7rtttsk+57/n4WwdfM7ku2bijbD4t9lWcyvZ07e"
+ "fv2tlrH5rztkt4+L6QW+XkHg7dUbWsw/9SC0NsnxkZGRqIbKNVBoArl0ecvWInSe5r7F9bjfXKHp"
+ "u3PPFRV4rofUmUXVOHxpKfFrAPaoi1P6emth+Y4mNN2MN5ByVJDOPubgwe4Tl/+xZw/MmT1bcjyO"
+ "ud12+83wnzM/dtve0tIGz2akwxuvrVXMa3ZSEuwh1/3qq6/Aq38/+XlpXdD6+Veya0Giu3FcTG9o"
+ "66i/zpLeXn2IjO4DZ783wen/kyq0ESNGWHU5IkkRsqoCulXuq7oQjcXOjeJFg2kOnEIYv8QI+Ar7"
+ "2tgjae/DQL8QdC65VpanNSAGIhDSoFmcwCmEBmwf7dSS0GpJ2+hubNltP/BJBFp5pMzE5bI9ZYpz"
+ "nRc+L2+vf//gn1BcXKJ4XkBAIOwovaa4DFveAp87lFckEb65tupN2X0xv+kj2WbuuEoIrgEOV7TI"
+ "khnJu2bosGEmiiZhHUcz2GocIvHUMeTJJ1Q7FolA74bKJASY6aHtRP1tQUbF5MqEpku4LaGZO8zl"
+ "kyZNkmw/eOigsKAv2S9J+BHNmwfcIHu9l3KyobyiXPa8zmS1gydk1pCdCx2Xm2XV2ZRH+yqeu3fX"
+ "Vck2JGysp4YPcyiDodASSxmDQYZyo3SoFwPbkiUycRXlZHtPJTQaz4YzCc3tXfVuS2hEvZQPHz68"
+ "Xi445L333lOMVixc92d0xUjOaW83Q1paGixd/pLiuX1iJyqWB92MpnmLZANBEEkL+kP/AC/ZfV8c"
+ "aZV1NyYkJGC+RRo+zCyEVqtRvqFdAkMM3CgdTmo4hsEyHlYsE8jDCU0dwdgEUQ3SEmidreNTnNCc"
+ "b61FD5FOvyc2b94MjQ0Nsv7DYUOHQnJKkuIl/7K9GGIIcVWUl0vO9Xs2RaoUfzwvLK2FK4LIKTNE"
+ "9NQ+wtiZEt5dLz2PkDWMGD789MiRI6vpmoJqgrVAaGKHZdDIyGmUXBxlZ1DHV9i3C6llAduXGfZ4"
+ "WBOxuLlTHeh2nAH0kZUe4ar3dnNDzZs1a5ZkO0Y7biKkpqS0FmQsgphfjle87k8/1kH600/DveMj"
+ "IWPhs1BOyA2jJ3FtR3Qrohq7smsPNOW+Cab0xRY/BjoywhfmZfsp7kd19uURaXRjEqkXgzqjfaiN"
+ "WhML5XGhMgrRY43SSWAZTzOSl55VntIw4goVtAsuG8D6km9agWVM0yMWjHZrQhs1evQpPz+/imnx"
+ "8ZJ9a9euFeal4adX5NKfXi+AyPFjLV6/seES/OPvH8PT8+fD/Q88cK2nT3pGUGOX334HWg4etXj+"
+ "4KG9YOHqAIvHbFlzWbIN3ajx8fH1pJx5WrtOxDESo63XYTzeSElofPzMfi9/rONpGCQyw4OaiOVl"
+ "KtPeKk38nhjL/DOu0NzDUCEnPf1p2X0vLlli8QsvG9ZtggcT7rdLudDN+IetAeAfoBwIgq5GubGz"
+ "9HnpWL68u8aMMdnBKEPBtiWv1OQbqrGbk0MdqbGOpxV4SpCIuFoFyxfgC+xIZnh9FoWcS7MOIic0"
+ "F8CYu8eUDxw4cMe8efMk+06ePAm5q3MtLmm1IucVWJ27Gvr2661Jefr7e8GC1f7X3YxmuCrMM+sJ"
+ "dDW+u0E6djZw4ABBnaE7VUWHRTuO5gyFRtMxcpej/UmNZTwNX0A8KUiEhexnEOLR3C1Lrol2sgfY"
+ "ViXxmO/TeXuEkUJHxsyZMxsIsUn2bdu2DXa8v0NY4Ffp3/0P3A+ffXoQ4hN+Db16+6gqAxLZ9Kf6"
+ "wRulwZIAkJ6k9tNZM6xZ1CR7neXLV2CZcu4Ou9uksjmsvWXOAO1dfzREZG08wFkTqoWvPjswFevA"
+ "ZFjG0+yqRlxYpQnPNCGgPSIJaUFm6GY8DGwTuLNc+JMxzPD1hEqGhYWdqj569LVlS5e+NDc1VbI/"
+ "OztbWJMxXmasrSuWZq8QEob9by/eBKe/+R5aW9oskhiS16gIX4iWmTQtR2pNjVcImTXC5Sbp0l2E"
+ "lMEYEVFB6pNnQ3OUWVFDmkcaiiuV1FoxRGvhx55ilE53DeF4GrlfOJ5GS64zcNK1hyyHlcXQLp3P"
+ "9WFCRmWdL3aEYKjaSSTCTrtQo/bQZgrBg+DrKRUNHzs2hxhcbFpqakxBofQev5STI6w2Ff/gg1av"
+ "hfO/ErpMB0CCu9zcDLs/fh0eTu0nbAsZ6qs4r0wJP5xtJmR2SXbcbOiwIfC7hQvR1TjHxqawdRyq"
+ "zIZ8Q51YbleBLogbx9MISeUCfSQdTrquVfqkkxuptBJCNCzt0pXY4kSiclSEaKKnjJ11wtuTKkuM"
+ "LSE1NbU+NiZGdn8OITV0QdJ8LqZrQnKb+dhjkL0ukKixXkJiJTNcSf+FJ+oJmbVK9vn794c1f1yD"
+ "ec0ZGxFxykmEZGuHW+XkcnOFxm4vWYz3rYByPU5XJ7Us0P8LVpYnTKT2aEKLMBpNqNKys7MbcAK1"
+ "HF5dswYWLFx47WOgjMS2btklVeXCaMYXZtXLuhn9/PtCYcF6GDhw4FJS/lINOqk6G41R7bm2EJIn"
+ "TajW2xs1y3iaJwWJTNYxqWXRujU5obk4jOPGVfv7B8zOz18HQxVIraKiAh6Mj4f3398JZnMHddq7"
+ "+ypTWTCSEVWZXDTjNTLrAwX5G2DIkKGbSLlzNGwGW8hFlRFTRlhqrQo5odn+AsQ6Pw3Hfdw+SARd"
+ "efi9LtBfBGGip5KZRxIa4p7Ie0oDAvyfXJef3xARESF7TFNTEyxbvgymTYuHXbt2wrXvuVhLdED3"
+ "Iqq5FemNsuNlCH9/P4HMhg0buomUd47GTaCWIOrEDs7R+XpSuL7uyFvF/LQZnrIyPyGPREYVay+g"
+ "jdyJY3zgwfD21IrfExlZ5O/vH5O/dm391KlTFY87e+4cIbblED9tGhSuXy/MXVNyOW4/cIPidS43"
+ "dggr5i9PbxDci5bUHCrHrVu24u9SUs45dqi+M9yGtpzvSWMBuhzEVzGehkEicZ5ww5BESELjd8b3"
+ "4qpEVTbZk8LzleDryZWPvPfe6s8+/TT2xd//vig6Kips+YoVgjKTwzlCbBs2bBDSgAEDAJUdjsN1"
+ "ui2HDRsGH354RfgEDCqwS01mOP+9GU6R/3+psFq+HB5JTISUlJSGgICA2aR8pfaoN7r/SGdD+9FC"
+ "LYnFWUTqMtD5x0tRiRxmeG5wPC2R1Mkj7p/o6ssV54uh6zXVjioeQ7XLPDHwwxK8UFl4Oj7dvz+Y"
+ "/OScPXv2ubzXX4fKykqHlwFJ8sUXX4SIsWNryJ8J4ydMOMUfTw4O1wchuK7uV3wZoHXH9pxHVkUI"
+ "jK+WwwmNDvv37YslP0VHjx4dvHHjRjhaXW33PP38/SAlOQWVWT2S6oSJE/P4neDg4ODghKYJ9n2y"
+ "bw6SCxJbcXExVH6ivWJDRZacnAzRUdHg7+//OuY38b6JJt76HBwcHJzQNMcnlZVIbBnnzp0L21tZ"
+ "Kbgiq21QbbcMuBmi74uGKVOm4NjbaVSDJOXdFxXFiYyDg4ODE5r9Ubl3bwj5QXLD9a7C0BVZffQo"
+ "NDY1wddffy0c0yT+f8Att8AAcRFkorxg6JAhMIQkDB4hqgxJrJyk0qjo6FLeshwcHByc0JyGvRUV"
+ "GEASTlIsSSFiQuD2MJJwLKxTxpnE/wspOibmFG9BDg4ODk5oHBwcHBwcivDmTcDBwcHB4Q74fwEG"
+ "APNNNssrHc8WAAAAAElFTkSuQmCC\">");
+}
+
+void
+report_formatter_html::add_header()
+{
+ add_exact("<header id=\"main_header\">\n");
+}
+
+void
+report_formatter_html::end_header()
+{
+ add_exact("</header>\n\n");
+}
+
+void
+report_formatter_html::add_div(struct tag_attr * div_attr)
+{
+ string empty="";
+ string tmp_str;
+
+ if (div_attr->css_class == empty && div_attr->css_id == empty)
+ add_exact("<div>\n");
+
+ else if (div_attr->css_class == empty && div_attr->css_id != empty)
+ addf_exact("<div id=\"%s\">\n", div_attr->css_id);
+
+ else if (div_attr->css_class != empty && div_attr->css_id == empty)
+ addf_exact("<div class=\"%s\">\n", div_attr->css_class);
+
+ else if (div_attr->css_class != empty && div_attr->css_id != empty)
+ addf_exact("<div class=\"%s\" id=\"%s\">\n",
+ div_attr->css_class, div_attr->css_id);
+}
+
+void
+report_formatter_html::end_div()
+{
+ add_exact("</div>\n");
+}
+
+void
+report_formatter_html::add_title(struct tag_attr *title_att, const char *title)
+{
+ addf_exact("<h2 class=\"%s\"> %s </h2>\n", title_att->css_class, title);
+}
+
+void
+report_formatter_html::add_navigation()
+{
+ add_exact("<br/><div id=\"main_menu\"> </div>\n");
+}
+
+void
+report_formatter_html::add_summary_list(string *list, int size)
+{
+ int i;
+ add_exact("<div><br/> <ul>\n");
+ for (i=0; i < size; i+=2){
+ addf_exact("<li class=\"summary_list\"> <b> %s </b> %s </li>",
+ list[i].c_str(), list[i+1].c_str());
+ }
+ add_exact("</ul> </div> <br />\n");
+}
+
+
+void
+report_formatter_html::add_table(string *system_data, struct table_attributes* tb_attr)
+{
+ int i, j;
+ int offset=0;
+ string empty="";
+
+ if (tb_attr->table_class == empty)
+ add_exact("<table>\n");
+ else
+ addf_exact("<table class=\"%s\">\n", tb_attr->table_class);
+
+ for (i=0; i < tb_attr->rows; i++){
+ if (tb_attr->tr_class == empty)
+ add_exact("<tr> ");
+ else
+ addf_exact("<tr class=\"%s\"> ", tb_attr->tr_class);
+
+ for (j=0; j < tb_attr->cols; j++){
+ offset = i * (tb_attr->cols) + j;
+
+ if (tb_attr->pos_table_title == T && i==0)
+ addf_exact("<th class=\"%s\"> %s </th> ",
+ tb_attr->th_class,system_data[offset].c_str());
+ else if (tb_attr->pos_table_title == L && j==0)
+ addf_exact("<th class=\"%s\"> %s </th> ",
+ tb_attr->th_class, system_data[offset].c_str());
+ else if (tb_attr->pos_table_title == TL && ( i==0 || j==0 ))
+ addf_exact("<th class=\"%s\"> %s </th> ",
+ tb_attr->th_class, system_data[offset].c_str());
+ else if (tb_attr->pos_table_title == TC && ((i % tb_attr->title_mod ) == 0))
+ addf_exact("<th class=\"%s\"> %s </th> ", tb_attr->th_class,
+ system_data[offset].c_str());
+ else if (tb_attr->pos_table_title == TLC && ((i % tb_attr->title_mod) == 0 || j==0))
+ addf_exact("<th class=\"%s\"> %s </th> ", tb_attr->th_class,
+ system_data[offset].c_str());
+ else
+ if ( tb_attr->td_class == empty)
+ addf_exact("<td > %s </td> ", system_data[offset].c_str());
+ else
+ addf_exact("<td class=\"%s\"> %s </td> ", tb_attr->td_class,
+ system_data[offset].c_str());
+ }
+ add_exact("</tr>\n");
+ }
+ add_exact("</table>\n");
+}
+
diff --git a/src/report/report-formatter-html.h b/src/report/report-formatter-html.h
new file mode 100644
index 0000000..c003fd9
--- /dev/null
+++ b/src/report/report-formatter-html.h
@@ -0,0 +1,73 @@
+/* Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * HTML report generator.
+ * Written by Igor Zhbanov <i.zhbanov@samsung.com>
+ * 2012.10 */
+
+#ifndef _REPORT_FORMATTER_HTML_H_
+#define _REPORT_FORMATTER_HTML_H_
+
+#include <string>
+
+#include "report-formatter-base.h"
+#include "report-data-html.h"
+
+using namespace std;
+
+/* Whether to replace " and ' in HTML by &quot; and &apos; respectively */
+/*#define REPORT_HTML_ESCAPE_QUOTES*/
+
+/* ************************************************************************ */
+
+struct html_section {
+ const char *id;
+};
+
+/* ************************************************************************ */
+
+class report_formatter_html: public report_formatter_string_base
+{
+public:
+ report_formatter_html();
+ void finish_report();
+
+ /* Report Style */
+ void add_logo();
+ void add_header();
+ void end_header();
+ void add_div(struct tag_attr *div_attr);
+ void end_div();
+ void add_title(struct tag_attr *title_att, const char *title);
+ void add_navigation();
+ void add_summary_list(string *list, int size);
+ void add_table(string *system_data, struct table_attributes *tb_attr);
+
+private:
+ /* Document structure related functions */
+ void init_markup();
+ void add_doc_header();
+ void add_doc_footer();
+ string escape_string(const char *str);
+
+};
+
+#endif /* _REPORT_FORMATTER_HTML_H_ */
diff --git a/src/report/report-formatter.h b/src/report/report-formatter.h
new file mode 100644
index 0000000..940b5cf
--- /dev/null
+++ b/src/report/report-formatter.h
@@ -0,0 +1,57 @@
+/* Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * report_formatter interface.
+ * Written by Igor Zhbanov <i.zhbanov@samsung.com>
+ * 2012.10 */
+
+#ifndef _REPORT_FORMATTER_H_
+#define _REPORT_FORMATTER_H_
+
+#include "report-maker.h"
+using namespace std;
+
+class report_formatter
+{
+public:
+ virtual ~report_formatter() {}
+
+ virtual void finish_report() {}
+ virtual const char *get_result() {return "Basic report_formatter::get_result() call\n";}
+ virtual void clear_result() {}
+
+ virtual void add(const char *str) {}
+ virtual void addv(const char *fmt, va_list ap) {}
+
+ /* *** Report Style *** */
+ virtual void add_logo() {}
+ virtual void add_header() {}
+ virtual void end_header() {}
+ virtual void add_div(struct tag_attr *div_attr) {}
+ virtual void end_div() {}
+ virtual void add_title(struct tag_attr *att_title, const char *title) {}
+ virtual void add_navigation() {}
+ virtual void add_summary_list(string *list, int size) {}
+ virtual void add_table(string *system_data,
+ struct table_attributes *tb_attr) {}
+};
+
+#endif /* _REPORT_FORMATTER_H_ */
diff --git a/src/report/report-maker.cpp b/src/report/report-maker.cpp
new file mode 100644
index 0000000..4049a54
--- /dev/null
+++ b/src/report/report-maker.cpp
@@ -0,0 +1,187 @@
+/* Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Generic report generator.
+ * Written by Igor Zhbanov <i.zhbanov@samsung.com>
+ * 2012.10 */
+
+/* Uncomment to disable asserts */
+/*#define NDEBUG*/
+
+#include <assert.h>
+#include <stdarg.h>
+
+#include "report-maker.h"
+#include "report-formatter-csv.h"
+#include "report-formatter-html.h"
+
+/* ************************************************************************ */
+
+report_maker::report_maker(report_type t)
+{
+ type = t;
+ formatter = NULL;
+ setup_report_formatter();
+ clear_result(); /* To reset state and add document header */
+}
+
+/* ************************************************************************ */
+
+report_maker::~report_maker()
+{
+ delete formatter;
+}
+
+/* ************************************************************************ */
+
+void
+report_maker::finish_report()
+{
+ formatter->finish_report();
+}
+
+/* ************************************************************************ */
+
+const char *
+report_maker::get_result()
+{
+ return formatter->get_result();
+}
+
+/* ************************************************************************ */
+
+void
+report_maker::clear_result()
+{
+ formatter->clear_result();
+}
+
+/* ************************************************************************ */
+
+report_type
+report_maker::get_type()
+{
+ return type;
+}
+
+/* ************************************************************************ */
+
+void
+report_maker::set_type(report_type t)
+{
+ clear_result();
+ type = t;
+ setup_report_formatter();
+}
+
+/* ************************************************************************ */
+
+void
+report_maker::setup_report_formatter()
+{
+ delete formatter;
+
+ if (type == REPORT_HTML)
+ formatter = new report_formatter_html();
+ else if (type == REPORT_CSV)
+ formatter = new report_formatter_csv();
+ else if (type == REPORT_OFF)
+ formatter = new report_formatter();
+ else
+ assert(false);
+}
+
+/* ************************************************************************ */
+
+void
+report_maker::add(const char *str)
+{
+ assert(str);
+ formatter->add(str);
+}
+
+/* ************************************************************************ */
+
+void
+report_maker::addf(const char *fmt, ...)
+{
+ va_list ap;
+ assert(fmt);
+ va_start(ap, fmt);
+ formatter->addv(fmt, ap);
+ va_end(ap);
+}
+
+/* *** Report Style *** */
+void
+report_maker::add_logo()
+{
+ formatter->add_logo();
+}
+
+void
+report_maker::add_header()
+{
+ formatter->add_header();
+}
+
+void
+report_maker::end_header()
+{
+ formatter->end_header();
+}
+
+void
+report_maker::add_title(struct tag_attr *att_title, const char *title)
+{
+ formatter->add_title(att_title, title);
+}
+
+void
+report_maker::add_div(struct tag_attr * div_attr)
+{
+ formatter->add_div(div_attr);
+}
+
+void
+report_maker::end_div()
+{
+ formatter->end_div();
+}
+
+void
+report_maker::add_navigation()
+{
+ formatter->add_navigation();
+}
+
+void
+report_maker::add_summary_list(string *list, int size)
+{
+ formatter->add_summary_list(list, size);
+}
+
+void
+report_maker::add_table(string *system_data, struct table_attributes *tb_attr)
+{
+ formatter->add_table(system_data, tb_attr);
+}
+
diff --git a/src/report/report-maker.h b/src/report/report-maker.h
new file mode 100644
index 0000000..bda4cef
--- /dev/null
+++ b/src/report/report-maker.h
@@ -0,0 +1,139 @@
+/* Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Generic report generator.
+ * Written by Igor Zhbanov <i.zhbanov@samsung.com>
+ * 2012.10 */
+
+#ifndef _REPORT_MAKER_H_
+#define _REPORT_MAKER_H_
+
+/* This report generator implements the following document structure:
+ * body
+ * \---> section
+ * |---> Title
+ * |---> paragraph
+ * |---> table
+ * |---> list
+ *
+ * The report body consists of a number of sections (a.k.a. <div>s,
+ * a.k.a. tabs).
+ * Each section can contain titles (<h2>), paragraphs (<p>)
+ * and tables (<table>).
+ *
+ * A header is a single line of text.
+ *
+ * Paragraphs can contain only text.
+ *
+ *
+ * Each section, table, row or cell could have its own formatting.
+ *
+ * Example of usage:
+ * report_maker report(REPORT_OFF);
+ *
+ * report.set_type(REPORT_HTML);
+ * report.add_div
+ * report.add_title
+ * report.add_list
+ * report.add_table
+ * report.finish_report();
+ * const char *result = report.get_result();
+ */
+
+#include <stdarg.h>
+
+#include <string>
+using namespace std;
+/* Conditional gettext. We need original strings for CSV. */
+#ifdef ENABLE_NLS
+#define __(STRING) \
+ ((report.get_type() == REPORT_CSV) ? (STRING) : gettext(STRING))
+#else
+#define __(STRING) (STRING)
+#endif
+
+#ifndef UNUSED
+#define UNUSED __attribute__((unused))
+#endif /* UNUSED */
+
+/* ************************************************************************ */
+
+enum report_type {
+ REPORT_OFF,
+ REPORT_HTML,
+ REPORT_CSV
+};
+
+/* ************************************************************************ */
+
+enum section_type {
+ SECTION_DEFAULT,
+ SECTION_SYSINFO,
+ SECTION_CPUIDLE,
+ SECTION_CPUFREQ,
+ SECTION_DEVFREQ,
+ SECTION_DEVPOWER,
+ SECTION_SOFTWARE,
+ SECTION_SUMMARY,
+ SECTION_TUNING,
+ SECTION_MAX /* Must be last in this enum */
+};
+
+
+/* ************************************************************************ */
+
+class report_formatter;
+
+class report_maker
+{
+public:
+ report_maker(report_type t);
+ ~report_maker();
+
+ report_type get_type();
+ void set_type(report_type t);
+
+ void addf(const char *fmt, ...)
+ __attribute__ ((format (printf, 2, 3)));
+
+ void finish_report();
+ const char *get_result();
+ void clear_result();
+
+ void add(const char *str);
+
+ /* *** Report Style *** */
+ void add_header();
+ void end_header();
+ void add_logo();
+ void add_div(struct tag_attr *div_attr);
+ void end_div();
+ void add_title(struct tag_attr *att_title, const char *title);
+ void add_navigation();
+ void add_summary_list(string *list, int size);
+ void add_table(string *system_data, struct table_attributes *tb_attr);
+
+private:
+ void setup_report_formatter();
+ report_type type;
+ report_formatter *formatter;
+};
+#endif /* _REPORT_MAKER_H_ */
diff --git a/src/report/report.cpp b/src/report/report.cpp
new file mode 100644
index 0000000..2efe835
--- /dev/null
+++ b/src/report/report.cpp
@@ -0,0 +1,217 @@
+/*
+ * Copyright 2011, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ * Chris Ferron <chris.e.ferron@linux.intel.com>
+ */
+
+#include "lib.h"
+#include "report.h"
+#include "report-maker.h"
+#include <errno.h>
+#include <string.h>
+#include <utility>
+#include <iostream>
+#include <fstream>
+#include <string.h>
+#include <malloc.h>
+#include <unistd.h>
+#include <limits.h>
+#include "report-data-html.h"
+
+using namespace std;
+
+struct reportstream reportout;
+report_type reporttype = REPORT_OFF;
+report_maker report(REPORT_OFF);
+
+string cpu_model(void)
+{
+ ifstream file;
+
+ file.open("/proc/cpuinfo", ios::in);
+
+ if (!file)
+ return "";
+
+ while (file) {
+ char line[4096];
+ file.getline(line, 4096);
+ if (strstr(line, "model name")) {
+ char *c;
+ c = strchr(line, ':');
+ if (c) {
+ file.close();
+ c++;
+ return c;
+ }
+ }
+ }
+ file.close();
+ return "";
+}
+
+static string read_os_release(const string &filename)
+{
+ ifstream file;
+ char content[4096];
+ char *c;
+ const char *pname = "PRETTY_NAME=";
+ string os("");
+
+ file.open(filename.c_str(), ios::in);
+ if (!file)
+ return "";
+ while (file.getline(content, 4096)) {
+ if (strncasecmp(pname, content, strlen(pname)) == 0) {
+ c = strchr(content, '=');
+ if (!c)
+ break;
+ c += 1;
+ if (*c == '"' || *c == '\'')
+ c += 1;
+ *strchrnul(c, '"') = 0;
+ *strchrnul(c, '\'') = 0;
+ os = c;
+ break;
+ }
+ }
+ file.close();
+ return os;
+}
+
+static void system_info(void)
+{
+ string str;
+ char version_date[64];
+ time_t now = time(NULL);
+
+ /* div attr css_class and css_id */
+ tag_attr div_attr;
+ init_div(&div_attr, "sys_info", "");
+
+ /* Set Table attributes, rows, and cols */
+ table_attributes sys_table;
+ init_top_table_attr(&sys_table, 5, 2);
+
+ /* Set Title attributes */
+ tag_attr title_attr;
+ init_title_attr(&title_attr);
+
+ /* Set array of data in row Major order */
+ string *system_data = new string[sys_table.rows * sys_table.cols];
+ system_data[0]=__("PowerTOP Version");
+ snprintf(version_date, sizeof(version_date), "%s ran at %s", PACKAGE_VERSION, ctime(&now));
+ system_data[1]=version_date;
+
+ str = read_sysfs_string("/proc/version");
+ size_t found = str.find(" ");
+ found = str.find(" ", found+1);
+ found = str.find(" ", found+1);
+ str = str.substr(0,found);
+ system_data[2]=__("Kernel Version");
+ system_data[3]=str.c_str();
+
+ str = read_sysfs_string("/sys/devices/virtual/dmi/id/board_vendor");
+ system_data[4]=__("System Name");
+ system_data[5]= str.c_str();
+ str = read_sysfs_string("/sys/devices/virtual/dmi/id/board_name");
+ system_data[5].append(str.c_str());
+ str = read_sysfs_string("/sys/devices/virtual/dmi/id/product_version");
+ system_data[5].append(str.c_str());
+ str = cpu_model();
+ system_data[6]=__("CPU Information");
+ stringstream n_proc;
+ n_proc << sysconf(_SC_NPROCESSORS_ONLN);
+ system_data[7]= n_proc.str();
+ system_data[7].append(str.c_str());
+
+ str = read_sysfs_string("/etc/system-release");
+ if (str.length() < 1)
+ str = read_sysfs_string("/etc/redhat-release");
+ if (str.length() < 1)
+ str = read_os_release("/etc/os-release");
+
+ system_data[8]=__("OS Information");
+ system_data[9]=str;
+
+ /* Report Output */
+ report.add_header();
+ report.add_logo();
+ report.add_div(&div_attr);
+ report.add_title(&title_attr, __("System Information"));
+ report.add_table(system_data, &sys_table);
+ report.end_header();
+ report.end_div();
+ report.add_navigation();
+ delete [] system_data;
+}
+
+void init_report_output(char *filename_str, int iterations)
+{
+ size_t period;
+ string filename;
+ time_t stamp;
+ char datestr[200];
+
+ if (iterations == 1)
+ snprintf(reportout.filename, sizeof(reportout.filename), "%s", filename_str);
+ else
+ {
+ filename = string(filename_str);
+ period = filename.find_last_of(".");
+ if (period > filename.length())
+ period = filename.length();
+ memset(&datestr, 0, 200);
+ memset(&stamp, 0, sizeof(time_t));
+ stamp = time(NULL);
+ strftime(datestr, sizeof(datestr), "%Y%m%d-%H%M%S", localtime(&stamp));
+ snprintf(reportout.filename, sizeof(reportout.filename), "%s-%s%s",
+ filename.substr(0, period).c_str(), datestr,
+ filename.substr(period).c_str());
+ }
+
+ reportout.report_file = fopen(reportout.filename, "wm");
+ if (!reportout.report_file) {
+ fprintf(stderr, _("Cannot open output file %s (%s)\n"),
+ reportout.filename, strerror(errno));
+ }
+
+ report.set_type(reporttype);
+ system_info();
+}
+
+void finish_report_output(void)
+{
+ if (reporttype == REPORT_OFF)
+ return;
+
+ report.finish_report();
+ if (reportout.report_file)
+ {
+ fprintf(stderr, _("PowerTOP outputting using base filename %s\n"), reportout.filename);
+ fputs(report.get_result(), reportout.report_file);
+ fdatasync(fileno(reportout.report_file));
+ fclose(reportout.report_file);
+ }
+ report.clear_result();
+}
diff --git a/src/report/report.h b/src/report/report.h
new file mode 100644
index 0000000..c1aee1b
--- /dev/null
+++ b/src/report/report.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef __INCLUDE_GUARD_REPORT_H_
+#define __INCLUDE_GUARD_REPORT_H_
+
+#include <string>
+#include <stdio.h>
+#include <limits.h>
+
+#include "report-maker.h"
+
+using namespace std;
+
+struct reportstream {
+ FILE *report_file;
+ char filename[PATH_MAX];
+};
+
+extern report_type reporttype;
+extern report_maker report;
+extern struct reportstream reportout;
+extern void init_report_output(char *filename_str, int iterations);
+extern void finish_report_output(void);
+
+#endif
diff --git a/src/tuning/bluetooth.cpp b/src/tuning/bluetooth.cpp
new file mode 100644
index 0000000..2958849
--- /dev/null
+++ b/src/tuning/bluetooth.cpp
@@ -0,0 +1,228 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+
+#include "tuning.h"
+#include "tunable.h"
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <utility>
+#include <iostream>
+#include <fstream>
+#include <unistd.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#include "../lib.h"
+#include "bluetooth.h"
+
+bt_tunable::bt_tunable(void) : tunable("", 1.0, _("Good"), _("Bad"), _("Unknown"))
+{
+ sprintf(desc, _("Bluetooth device interface status"));
+ pt_strcpy(toggle_bad, "/usr/sbin/hciconfig hci0 up &> /dev/null &");
+ pt_strcpy(toggle_good, "/usr/sbin/hciconfig hci0 down &> /dev/null");
+}
+
+
+
+/* structure definitions copied from include/net/bluetooth/hci.h from the 2.6.20 kernel */
+#define HCIGETDEVINFO _IOR('H', 211, int)
+#define BTPROTO_HCI 1
+
+#define __u16 uint16_t
+#define __u8 uint8_t
+#define __u32 uint32_t
+
+typedef struct {
+ __u8 b[6];
+} __attribute__((packed)) bdaddr_t;
+
+struct hci_dev_stats {
+ __u32 err_rx;
+ __u32 err_tx;
+ __u32 cmd_tx;
+ __u32 evt_rx;
+ __u32 acl_tx;
+ __u32 acl_rx;
+ __u32 sco_tx;
+ __u32 sco_rx;
+ __u32 byte_rx;
+ __u32 byte_tx;
+};
+
+
+struct hci_dev_info {
+ __u16 dev_id;
+ char name[8];
+
+ bdaddr_t bdaddr;
+
+ __u32 flags;
+ __u8 type;
+
+ __u8 features[8];
+
+ __u32 pkt_type;
+ __u32 link_policy;
+ __u32 link_mode;
+
+ __u16 acl_mtu;
+ __u16 acl_pkts;
+ __u16 sco_mtu;
+ __u16 sco_pkts;
+
+ struct hci_dev_stats stat;
+};
+
+static int previous_bytes = -1;
+static time_t last_check_time = 0;
+static int last_check_result;
+
+int bt_tunable::good_bad(void)
+{
+ struct hci_dev_info devinfo;
+ FILE *file = 0;
+ int fd;
+ int thisbytes = 0;
+ int ret;
+ int result = TUNE_GOOD;
+
+ fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+ if (fd < 0)
+ return TUNE_GOOD;
+
+ memset(&devinfo, 0, sizeof(devinfo));
+ strcpy(devinfo.name, "hci0");
+ ret = ioctl(fd, HCIGETDEVINFO, (void *) &devinfo);
+ if (ret < 0)
+ goto out;
+
+ if ( (devinfo.flags & 1) == 0 &&
+ access("/sys/module/hci_usb",F_OK)) /* interface down already */
+ goto out;
+
+ thisbytes += devinfo.stat.byte_rx;
+ thisbytes += devinfo.stat.byte_tx;
+
+ /* device is active... so we need to leave it on */
+ if (thisbytes != previous_bytes)
+ goto out;
+
+
+ /* this check is expensive.. only do it once per minute */
+ if (time(NULL) - last_check_time > 60) {
+ last_check_result = TUNE_BAD;
+ /* now, also check for active connections */
+ file = popen("/usr/bin/hcitool con 2> /dev/null", "r");
+ if (file) {
+ char line[2048];
+ /* first line is standard header */
+ if (fgets(line, 2047, file) == NULL)
+ goto out;
+ memset(line, 0, 2048);
+ if (fgets(line, 2047, file) == NULL) {
+ result = last_check_result = TUNE_GOOD;
+ goto out;
+ }
+
+ if (strlen(line) > 0) {
+ result = last_check_result = TUNE_GOOD;
+ goto out;
+ }
+ }
+ last_check_time = time(NULL);
+ };
+
+ result = last_check_result;
+
+out:
+ previous_bytes = thisbytes;
+ if (file)
+ pclose(file);
+ close(fd);
+ return result;
+}
+
+void bt_tunable::toggle(void)
+{
+ int good;
+ good = good_bad();
+
+ if (good == TUNE_GOOD) {
+ if(system("/usr/sbin/hciconfig hci0 up &> /dev/null &"))
+ printf("System is not available\n");
+ return;
+ }
+ if(system("/usr/sbin/hciconfig hci0 down &> /dev/null"))
+ printf("System is not available\n");
+}
+
+const char *bt_tunable::toggle_script(void)
+{
+ int good;
+ good = good_bad();
+
+ if (good == TUNE_GOOD) {
+ return toggle_bad;
+ }
+ return toggle_good;
+}
+
+
+void add_bt_tunable(void)
+{
+ struct hci_dev_info devinfo;
+ class bt_tunable *bt;
+ int fd;
+ int ret;
+
+ /* first check if /sys/modules/bluetooth exists, if not, don't probe bluetooth because
+ it would trigger an autoload */
+
+// if (access("/sys/module/bluetooth",F_OK))
+// return;
+
+
+ /* check if hci0 exists */
+ fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+ if (fd < 0)
+ return;
+
+ memset(&devinfo, 0, sizeof(devinfo));
+ strcpy(devinfo.name, "hci0");
+ ret = ioctl(fd, HCIGETDEVINFO, (void *) &devinfo);
+ close(fd);
+ if (ret < 0)
+ return;
+
+
+ bt = new class bt_tunable();
+ all_tunables.push_back(bt);
+}
diff --git a/src/tuning/bluetooth.h b/src/tuning/bluetooth.h
new file mode 100644
index 0000000..ecb667d
--- /dev/null
+++ b/src/tuning/bluetooth.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_BLUETOOTH_TUNE_H
+#define _INCLUDE_GUARD_BLUETOOTH_TUNE_H
+
+#include <vector>
+
+#include "tunable.h"
+
+using namespace std;
+
+class bt_tunable : public tunable {
+public:
+ bt_tunable(void);
+
+ virtual int good_bad(void);
+
+ virtual void toggle(void);
+
+ virtual const char *toggle_script(void);
+
+};
+
+extern void add_bt_tunable(void);
+
+
+#endif
diff --git a/src/tuning/ethernet.cpp b/src/tuning/ethernet.cpp
new file mode 100644
index 0000000..5b128d1
--- /dev/null
+++ b/src/tuning/ethernet.cpp
@@ -0,0 +1,157 @@
+;/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+
+#include "tuning.h"
+#include "tunable.h"
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <utility>
+#include <iostream>
+#include <fstream>
+#include <sys/socket.h>
+#include <errno.h>
+#include <linux/types.h>
+#include <net/if.h>
+#include <linux/sockios.h>
+#include <sys/ioctl.h>
+
+#include <linux/ethtool.h>
+
+#include "../lib.h"
+#include "ethernet.h"
+
+extern void create_all_nics(callback fn);
+
+ethernet_tunable::ethernet_tunable(const char *iface) : tunable("", 0.3, _("Good"), _("Bad"), _("Unknown"))
+{
+ memset(interf, 0, sizeof(interf));
+ pt_strcpy(interf, iface);
+ sprintf(desc, _("Wake-on-lan status for device %s"), iface);
+ snprintf(toggle_good, sizeof(toggle_good), "ethtool -s %s wol d;", iface);
+
+}
+
+
+int ethernet_tunable::good_bad(void)
+{
+ int sock;
+ struct ifreq ifr;
+ struct ethtool_wolinfo wol;
+ int ret;
+ int result = TUNE_GOOD;
+
+ memset(&ifr, 0, sizeof(struct ifreq));
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock<0)
+ return result;
+
+ pt_strcpy(ifr.ifr_name, interf);
+
+ /* Check if the interf is up */
+ ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
+ if (ret<0) {
+ close(sock);
+ return result;
+ }
+
+ memset(&wol, 0, sizeof(wol));
+
+ wol.cmd = ETHTOOL_GWOL;
+ ifr.ifr_data = (caddr_t)&wol;
+ ioctl(sock, SIOCETHTOOL, &ifr);
+
+ if (wol.wolopts)
+ result = TUNE_BAD;
+
+ close(sock);
+
+ return result;
+}
+
+void ethernet_tunable::toggle(void)
+{
+ int sock;
+ struct ifreq ifr;
+ struct ethtool_wolinfo wol;
+ int ret;
+
+ memset(&ifr, 0, sizeof(struct ifreq));
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock<0)
+ return;
+
+ pt_strcpy(ifr.ifr_name, interf);
+
+ /* Check if the interface is up */
+ ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
+ if (ret<0) {
+ close(sock);
+ return;
+ }
+
+ memset(&wol, 0, sizeof(wol));
+
+ wol.cmd = ETHTOOL_GWOL;
+ ifr.ifr_data = (caddr_t)&wol;
+ ioctl(sock, SIOCETHTOOL, &ifr);
+ wol.cmd = ETHTOOL_SWOL;
+ wol.wolopts = 0;
+ ioctl(sock, SIOCETHTOOL, &ifr);
+
+ close(sock);
+}
+
+const char *ethernet_tunable::toggle_script(void)
+{
+ int good;
+ good = good_bad();
+
+ if (good != TUNE_GOOD) {
+ return toggle_good;
+ }
+
+ return NULL;
+}
+
+
+void ethtunable_callback(const char *d_name)
+{
+ class ethernet_tunable *eth;
+ if (strcmp(d_name, "lo") == 0)
+ return;
+ eth = new(std::nothrow) class ethernet_tunable(d_name);
+ if (eth)
+ all_tunables.push_back(eth);
+}
+
+void add_ethernet_tunable(void)
+{
+ create_all_nics(&ethtunable_callback);
+}
diff --git a/src/tuning/ethernet.h b/src/tuning/ethernet.h
new file mode 100644
index 0000000..85810fb
--- /dev/null
+++ b/src/tuning/ethernet.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_ETHERNET_TUNE_H
+#define _INCLUDE_GUARD_ETHERNET_TUNE_H
+
+#include <vector>
+
+#include "tunable.h"
+
+using namespace std;
+
+class ethernet_tunable : public tunable {
+public:
+ char interf[4096];
+ ethernet_tunable(const char *iface);
+
+ virtual int good_bad(void);
+
+ virtual void toggle(void);
+
+ virtual const char *toggle_script(void);
+
+};
+
+extern void add_ethernet_tunable(void);
+
+#endif
diff --git a/src/tuning/iw.c b/src/tuning/iw.c
new file mode 100644
index 0000000..68eb6dc
--- /dev/null
+++ b/src/tuning/iw.c
@@ -0,0 +1,303 @@
+/*
+ * This code has been blatently stolen from
+ *
+ * nl80211 userspace tool
+ *
+ * Copyright 2007, 2008 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * and has been stripped down to just the pieces needed.
+ */
+
+/*
+
+Copyright (c) 2007, 2008 Johannes Berg
+Copyright (c) 2007 Andy Lutomirski
+Copyright (c) 2007 Mike Kershaw
+Copyright (c) 2008-2009 Luis R. Rodriguez
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+*/
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <net/if.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdbool.h>
+
+#include "nl80211.h"
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+#include <netlink/msg.h>
+#include <netlink/attr.h>
+
+#include <asm/errno.h>
+#include <linux/genetlink.h>
+#include "iw.h"
+
+
+#ifndef HAVE_LIBNL20
+/* libnl 2.0 compatibility code */
+
+static inline struct nl_handle *nl_socket_alloc(void)
+{
+ return nl_handle_alloc();
+}
+
+static inline void nl_socket_free(struct nl_sock *h)
+{
+ nl_handle_destroy(h);
+}
+
+static inline int __genl_ctrl_alloc_cache(struct nl_sock *h, struct nl_cache **cache)
+{
+ struct nl_cache *tmp = genl_ctrl_alloc_cache(h);
+ if (!tmp)
+ return -ENOMEM;
+ *cache = tmp;
+ return 0;
+}
+#define genl_ctrl_alloc_cache __genl_ctrl_alloc_cache
+#endif /* HAVE_LIBNL20 */
+
+
+static int nl80211_init(struct nl80211_state *state)
+{
+ int err;
+
+ state->nl_sock = nl_socket_alloc();
+ if (!state->nl_sock) {
+ fprintf(stderr, "Failed to allocate netlink socket.\n");
+ return -ENOMEM;
+ }
+
+ if (genl_connect(state->nl_sock)) {
+ fprintf(stderr, "Failed to connect to generic netlink.\n");
+ err = -ENOLINK;
+ goto out_handle_destroy;
+ }
+
+ if (genl_ctrl_alloc_cache(state->nl_sock, &state->nl_cache)) {
+ fprintf(stderr, "Failed to allocate generic netlink cache.\n");
+ err = -ENOMEM;
+ goto out_handle_destroy;
+ }
+
+ state->nl80211 = genl_ctrl_search_by_name(state->nl_cache, "nl80211");
+ if (!state->nl80211) {
+ err = -ENOENT;
+ goto out_cache_free;
+ }
+
+ return 0;
+
+ out_cache_free:
+ nl_cache_free(state->nl_cache);
+ out_handle_destroy:
+ nl_socket_free(state->nl_sock);
+ return err;
+}
+
+static void nl80211_cleanup(struct nl80211_state *state)
+{
+ genl_family_put(state->nl80211);
+ nl_cache_free(state->nl_cache);
+ nl_socket_free(state->nl_sock);
+}
+
+static int enable_power_save;
+
+
+static int set_power_save(struct nl80211_state *state,
+ struct nl_cb *cb,
+ struct nl_msg *msg)
+{
+ enum nl80211_ps_state ps_state;
+
+ ps_state = NL80211_PS_DISABLED;
+ if (enable_power_save)
+ ps_state = NL80211_PS_ENABLED;
+
+ NLA_PUT_U32(msg, NL80211_ATTR_PS_STATE, ps_state);
+
+ return 0;
+
+ nla_put_failure:
+ return -ENOBUFS;
+}
+
+static int print_power_save_handler(struct nl_msg *msg, void *arg)
+{
+ struct nlattr *attrs[NL80211_ATTR_MAX + 1];
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+
+ nla_parse(attrs, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL);
+
+ if (!attrs[NL80211_ATTR_PS_STATE])
+ return 0;
+
+ switch (nla_get_u32(attrs[NL80211_ATTR_PS_STATE])) {
+ case NL80211_PS_ENABLED:
+ enable_power_save = 1;
+ break;
+ case NL80211_PS_DISABLED:
+ default:
+ enable_power_save = 0;
+ break;
+ }
+
+ return NL_SKIP;
+}
+
+static int get_power_save(struct nl80211_state *state,
+ struct nl_cb *cb,
+ struct nl_msg *msg)
+{
+ nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
+ print_power_save_handler, NULL);
+ return 0;
+}
+
+static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
+ void *arg)
+{
+ int *ret = arg;
+ *ret = err->error;
+ return NL_STOP;
+}
+
+static int finish_handler(struct nl_msg *msg, void *arg)
+{
+ int *ret = arg;
+ *ret = 0;
+ return NL_SKIP;
+}
+
+static int ack_handler(struct nl_msg *msg, void *arg)
+{
+ int *ret = arg;
+ *ret = 0;
+ return NL_STOP;
+}
+
+static int __handle_cmd(struct nl80211_state *state, const char *iface, int get)
+{
+ struct nl_cb *cb;
+ struct nl_msg *msg;
+ int devidx = 0;
+ int err;
+
+ devidx = if_nametoindex(iface);
+ if (devidx == 0)
+ devidx = -1;
+ if (devidx < 0)
+ return -errno;
+
+ msg = nlmsg_alloc();
+ if (!msg) {
+ fprintf(stderr, "failed to allocate netlink message\n");
+ return 2;
+ }
+
+ cb = nl_cb_alloc(NL_CB_DEFAULT);
+ if (!cb) {
+ fprintf(stderr, "failed to allocate netlink callbacks\n");
+ err = 2;
+ goto out_free_msg;
+ }
+
+ if (get)
+ genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0,
+ 0, NL80211_CMD_GET_POWER_SAVE, 0);
+ else
+ genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0,
+ 0, NL80211_CMD_SET_POWER_SAVE, 0);
+
+
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, devidx);
+
+ if (get)
+ err = get_power_save(state, cb, msg);
+ else
+ err = set_power_save(state, cb, msg);
+
+ if (err)
+ goto out;
+
+ err = nl_send_auto_complete(state->nl_sock, msg);
+ if (err < 0)
+ goto out;
+
+ err = 1;
+
+ nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
+ nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
+ nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
+
+ while (err > 0)
+ nl_recvmsgs(state->nl_sock, cb);
+ out:
+ nl_cb_put(cb);
+ out_free_msg:
+ nlmsg_free(msg);
+ return err;
+ nla_put_failure:
+ fprintf(stderr, "building message failed\n");
+ return 2;
+}
+
+
+int set_wifi_power_saving(const char *iface, int state)
+{
+ struct nl80211_state nlstate;
+ int err;
+
+ err = nl80211_init(&nlstate);
+ if (err)
+ return 1;
+
+ enable_power_save = state;
+ err = __handle_cmd(&nlstate, iface, 0);
+
+ nl80211_cleanup(&nlstate);
+
+ return err;
+}
+
+
+int get_wifi_power_saving(const char *iface)
+{
+ struct nl80211_state nlstate;
+ int err;
+
+ enable_power_save = 0;
+
+ err = nl80211_init(&nlstate);
+ if (err)
+ return 1;
+
+ err = __handle_cmd(&nlstate, iface, 1);
+
+ nl80211_cleanup(&nlstate);
+
+ if (err) /* not a wifi interface */
+ return 1;
+
+ return enable_power_save;
+}
diff --git a/src/tuning/iw.h b/src/tuning/iw.h
new file mode 100644
index 0000000..6ea5a3d
--- /dev/null
+++ b/src/tuning/iw.h
@@ -0,0 +1,69 @@
+#ifndef __IW_H
+#define __IW_H
+
+/*
+ * This code has been blatently stolen from
+ *
+ * nl80211 userspace tool
+ *
+ * Copyright 2007, 2008 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * and has been stripped down to just the pieces needed.
+ */
+
+/*
+
+Copyright (c) 2007, 2008 Johannes Berg
+Copyright (c) 2007 Andy Lutomirski
+Copyright (c) 2007 Mike Kershaw
+Copyright (c) 2008-2009 Luis R. Rodriguez
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+*/
+
+#include <stdbool.h>
+
+#define ETH_ALEN 6
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef HAVE_LIBNL20
+#define nl_sock nl_handle
+#endif
+
+struct nl80211_state {
+ struct nl_sock *nl_sock;
+ struct nl_cache *nl_cache;
+ struct genl_family *nl80211;
+};
+
+enum command_identify_by {
+ CIB_NONE,
+ CIB_PHY,
+ CIB_NETDEV,
+};
+
+enum id_input {
+ II_NONE,
+ II_NETDEV,
+ II_PHY_NAME,
+ II_PHY_IDX,
+};
+
+int get_wifi_power_saving(const char *iface);
+int set_wifi_power_saving(const char *iface, int state);
+
+#endif /* __IW_H */
diff --git a/src/tuning/nl80211.h b/src/tuning/nl80211.h
new file mode 100644
index 0000000..83b0514
--- /dev/null
+++ b/src/tuning/nl80211.h
@@ -0,0 +1,1897 @@
+#ifndef __LINUX_NL80211_H
+#define __LINUX_NL80211_H
+/*
+ * 802.11 netlink interface public header
+ *
+ * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2008 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2008 Luis Carlos Cobo <luisca@cozybit.com>
+ * Copyright 2008 Michael Buesch <mb@bu3sch.de>
+ * Copyright 2008, 2009 Luis R. Rodriguez <lrodriguez@atheros.com>
+ * Copyright 2008 Jouni Malinen <jouni.malinen@atheros.com>
+ * Copyright 2008 Colin McCabe <colin@cozybit.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include <linux/types.h>
+
+/**
+ * DOC: Station handling
+ *
+ * Stations are added per interface, but a special case exists with VLAN
+ * interfaces. When a station is bound to an AP interface, it may be moved
+ * into a VLAN identified by a VLAN interface index (%NL80211_ATTR_STA_VLAN).
+ * The station is still assumed to belong to the AP interface it was added
+ * to.
+ *
+ * TODO: need more info?
+ */
+
+/**
+ * DOC: Frame transmission/registration support
+ *
+ * Frame transmission and registration support exists to allow userspace
+ * management entities such as wpa_supplicant react to management frames
+ * that are not being handled by the kernel. This includes, for example,
+ * certain classes of action frames that cannot be handled in the kernel
+ * for various reasons.
+ *
+ * Frame registration is done on a per-interface basis and registrations
+ * cannot be removed other than by closing the socket. It is possible to
+ * specify a registration filter to register, for example, only for a
+ * certain type of action frame. In particular with action frames, those
+ * that userspace registers for will not be returned as unhandled by the
+ * driver, so that the registered application has to take responsibility
+ * for doing that.
+ *
+ * The type of frame that can be registered for is also dependent on the
+ * driver and interface type. The frame types are advertised in wiphy
+ * attributes so applications know what to expect.
+ *
+ * NOTE: When an interface changes type while registrations are active,
+ * these registrations are ignored until the interface type is
+ * changed again. This means that changing the interface type can
+ * lead to a situation that couldn't otherwise be produced, but
+ * any such registrations will be dormant in the sense that they
+ * will not be serviced, i.e. they will not receive any frames.
+ *
+ * Frame transmission allows userspace to send for example the required
+ * responses to action frames. It is subject to some sanity checking,
+ * but many frames can be transmitted. When a frame was transmitted, its
+ * status is indicated to the sending socket.
+ *
+ * For more technical details, see the corresponding command descriptions
+ * below.
+ */
+
+/**
+ * enum nl80211_commands - supported nl80211 commands
+ *
+ * @NL80211_CMD_UNSPEC: unspecified command to catch errors
+ *
+ * @NL80211_CMD_GET_WIPHY: request information about a wiphy or dump request
+ * to get a list of all present wiphys.
+ * @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or
+ * %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME,
+ * %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ,
+ * %NL80211_ATTR_WIPHY_CHANNEL_TYPE, %NL80211_ATTR_WIPHY_RETRY_SHORT,
+ * %NL80211_ATTR_WIPHY_RETRY_LONG, %NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
+ * and/or %NL80211_ATTR_WIPHY_RTS_THRESHOLD.
+ * However, for setting the channel, see %NL80211_CMD_SET_CHANNEL
+ * instead, the support here is for backward compatibility only.
+ * @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request
+ * or rename notification. Has attributes %NL80211_ATTR_WIPHY and
+ * %NL80211_ATTR_WIPHY_NAME.
+ * @NL80211_CMD_DEL_WIPHY: Wiphy deleted. Has attributes
+ * %NL80211_ATTR_WIPHY and %NL80211_ATTR_WIPHY_NAME.
+ *
+ * @NL80211_CMD_GET_INTERFACE: Request an interface's configuration;
+ * either a dump request on a %NL80211_ATTR_WIPHY or a specific get
+ * on an %NL80211_ATTR_IFINDEX is supported.
+ * @NL80211_CMD_SET_INTERFACE: Set type of a virtual interface, requires
+ * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_IFTYPE.
+ * @NL80211_CMD_NEW_INTERFACE: Newly created virtual interface or response
+ * to %NL80211_CMD_GET_INTERFACE. Has %NL80211_ATTR_IFINDEX,
+ * %NL80211_ATTR_WIPHY and %NL80211_ATTR_IFTYPE attributes. Can also
+ * be sent from userspace to request creation of a new virtual interface,
+ * then requires attributes %NL80211_ATTR_WIPHY, %NL80211_ATTR_IFTYPE and
+ * %NL80211_ATTR_IFNAME.
+ * @NL80211_CMD_DEL_INTERFACE: Virtual interface was deleted, has attributes
+ * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_WIPHY. Can also be sent from
+ * userspace to request deletion of a virtual interface, then requires
+ * attribute %NL80211_ATTR_IFINDEX.
+ *
+ * @NL80211_CMD_GET_KEY: Get sequence counter information for a key specified
+ * by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC.
+ * @NL80211_CMD_SET_KEY: Set key attributes %NL80211_ATTR_KEY_DEFAULT,
+ * %NL80211_ATTR_KEY_DEFAULT_MGMT, or %NL80211_ATTR_KEY_THRESHOLD.
+ * @NL80211_CMD_NEW_KEY: add a key with given %NL80211_ATTR_KEY_DATA,
+ * %NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC, %NL80211_ATTR_KEY_CIPHER,
+ * and %NL80211_ATTR_KEY_SEQ attributes.
+ * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX
+ * or %NL80211_ATTR_MAC.
+ *
+ * @NL80211_CMD_GET_BEACON: retrieve beacon information (returned in a
+ * %NL80222_CMD_NEW_BEACON message)
+ * @NL80211_CMD_SET_BEACON: set the beacon on an access point interface
+ * using the %NL80211_ATTR_BEACON_INTERVAL, %NL80211_ATTR_DTIM_PERIOD,
+ * %NL80211_ATTR_BEACON_HEAD and %NL80211_ATTR_BEACON_TAIL attributes.
+ * @NL80211_CMD_NEW_BEACON: add a new beacon to an access point interface,
+ * parameters are like for %NL80211_CMD_SET_BEACON.
+ * @NL80211_CMD_DEL_BEACON: remove the beacon, stop sending it
+ *
+ * @NL80211_CMD_GET_STATION: Get station attributes for station identified by
+ * %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX.
+ * @NL80211_CMD_SET_STATION: Set station attributes for station identified by
+ * %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX.
+ * @NL80211_CMD_NEW_STATION: Add a station with given attributes to the
+ * the interface identified by %NL80211_ATTR_IFINDEX.
+ * @NL80211_CMD_DEL_STATION: Remove a station identified by %NL80211_ATTR_MAC
+ * or, if no MAC address given, all stations, on the interface identified
+ * by %NL80211_ATTR_IFINDEX.
+ *
+ * @NL80211_CMD_GET_MPATH: Get mesh path attributes for mesh path to
+ * destination %NL80211_ATTR_MAC on the interface identified by
+ * %NL80211_ATTR_IFINDEX.
+ * @NL80211_CMD_SET_MPATH: Set mesh path attributes for mesh path to
+ * destination %NL80211_ATTR_MAC on the interface identified by
+ * %NL80211_ATTR_IFINDEX.
+ * @NL80211_CMD_NEW_PATH: Add a mesh path with given attributes to the
+ * the interface identified by %NL80211_ATTR_IFINDEX.
+ * @NL80211_CMD_DEL_PATH: Remove a mesh path identified by %NL80211_ATTR_MAC
+ * or, if no MAC address given, all mesh paths, on the interface identified
+ * by %NL80211_ATTR_IFINDEX.
+ * @NL80211_CMD_SET_BSS: Set BSS attributes for BSS identified by
+ * %NL80211_ATTR_IFINDEX.
+ *
+ * @NL80211_CMD_GET_REG: ask the wireless core to send us its currently set
+ * regulatory domain.
+ * @NL80211_CMD_SET_REG: Set current regulatory domain. CRDA sends this command
+ * after being queried by the kernel. CRDA replies by sending a regulatory
+ * domain structure which consists of %NL80211_ATTR_REG_ALPHA set to our
+ * current alpha2 if it found a match. It also provides
+ * NL80211_ATTR_REG_RULE_FLAGS, and a set of regulatory rules. Each
+ * regulatory rule is a nested set of attributes given by
+ * %NL80211_ATTR_REG_RULE_FREQ_[START|END] and
+ * %NL80211_ATTR_FREQ_RANGE_MAX_BW with an attached power rule given by
+ * %NL80211_ATTR_REG_RULE_POWER_MAX_ANT_GAIN and
+ * %NL80211_ATTR_REG_RULE_POWER_MAX_EIRP.
+ * @NL80211_CMD_REQ_SET_REG: ask the wireless core to set the regulatory domain
+ * to the specified ISO/IEC 3166-1 alpha2 country code. The core will
+ * store this as a valid request and then query userspace for it.
+ *
+ * @NL80211_CMD_GET_MESH_PARAMS: Get mesh networking properties for the
+ * interface identified by %NL80211_ATTR_IFINDEX
+ *
+ * @NL80211_CMD_SET_MESH_PARAMS: Set mesh networking properties for the
+ * interface identified by %NL80211_ATTR_IFINDEX
+ *
+ * @NL80211_CMD_SET_MGMT_EXTRA_IE: Set extra IEs for management frames. The
+ * interface is identified with %NL80211_ATTR_IFINDEX and the management
+ * frame subtype with %NL80211_ATTR_MGMT_SUBTYPE. The extra IE data to be
+ * added to the end of the specified management frame is specified with
+ * %NL80211_ATTR_IE. If the command succeeds, the requested data will be
+ * added to all specified management frames generated by
+ * kernel/firmware/driver.
+ * Note: This command has been removed and it is only reserved at this
+ * point to avoid re-using existing command number. The functionality this
+ * command was planned for has been provided with cleaner design with the
+ * option to specify additional IEs in NL80211_CMD_TRIGGER_SCAN,
+ * NL80211_CMD_AUTHENTICATE, NL80211_CMD_ASSOCIATE,
+ * NL80211_CMD_DEAUTHENTICATE, and NL80211_CMD_DISASSOCIATE.
+ *
+ * @NL80211_CMD_GET_SCAN: get scan results
+ * @NL80211_CMD_TRIGGER_SCAN: trigger a new scan with the given parameters
+ * @NL80211_CMD_NEW_SCAN_RESULTS: scan notification (as a reply to
+ * NL80211_CMD_GET_SCAN and on the "scan" multicast group)
+ * @NL80211_CMD_SCAN_ABORTED: scan was aborted, for unspecified reasons,
+ * partial scan results may be available
+ *
+ * @NL80211_CMD_GET_SURVEY: get survey resuls, e.g. channel occupation
+ * or noise level
+ * @NL80211_CMD_NEW_SURVEY_RESULTS: survey data notification (as a reply to
+ * NL80211_CMD_GET_SURVEY and on the "scan" multicast group)
+ *
+ * @NL80211_CMD_REG_CHANGE: indicates to userspace the regulatory domain
+ * has been changed and provides details of the request information
+ * that caused the change such as who initiated the regulatory request
+ * (%NL80211_ATTR_REG_INITIATOR), the wiphy_idx
+ * (%NL80211_ATTR_REG_ALPHA2) on which the request was made from if
+ * the initiator was %NL80211_REGDOM_SET_BY_COUNTRY_IE or
+ * %NL80211_REGDOM_SET_BY_DRIVER, the type of regulatory domain
+ * set (%NL80211_ATTR_REG_TYPE), if the type of regulatory domain is
+ * %NL80211_REG_TYPE_COUNTRY the alpha2 to which we have moved on
+ * to (%NL80211_ATTR_REG_ALPHA2).
+ * @NL80211_CMD_REG_BEACON_HINT: indicates to userspace that an AP beacon
+ * has been found while world roaming thus enabling active scan or
+ * any mode of operation that initiates TX (beacons) on a channel
+ * where we would not have been able to do either before. As an example
+ * if you are world roaming (regulatory domain set to world or if your
+ * driver is using a custom world roaming regulatory domain) and while
+ * doing a passive scan on the 5 GHz band you find an AP there (if not
+ * on a DFS channel) you will now be able to actively scan for that AP
+ * or use AP mode on your card on that same channel. Note that this will
+ * never be used for channels 1-11 on the 2 GHz band as they are always
+ * enabled world wide. This beacon hint is only sent if your device had
+ * either disabled active scanning or beaconing on a channel. We send to
+ * userspace the wiphy on which we removed a restriction from
+ * (%NL80211_ATTR_WIPHY) and the channel on which this occurred
+ * before (%NL80211_ATTR_FREQ_BEFORE) and after (%NL80211_ATTR_FREQ_AFTER)
+ * the beacon hint was processed.
+ *
+ * @NL80211_CMD_AUTHENTICATE: authentication request and notification.
+ * This command is used both as a command (request to authenticate) and
+ * as an event on the "mlme" multicast group indicating completion of the
+ * authentication process.
+ * When used as a command, %NL80211_ATTR_IFINDEX is used to identify the
+ * interface. %NL80211_ATTR_MAC is used to specify PeerSTAAddress (and
+ * BSSID in case of station mode). %NL80211_ATTR_SSID is used to specify
+ * the SSID (mainly for association, but is included in authentication
+ * request, too, to help BSS selection. %NL80211_ATTR_WIPHY_FREQ is used
+ * to specify the frequence of the channel in MHz. %NL80211_ATTR_AUTH_TYPE
+ * is used to specify the authentication type. %NL80211_ATTR_IE is used to
+ * define IEs (VendorSpecificInfo, but also including RSN IE and FT IEs)
+ * to be added to the frame.
+ * When used as an event, this reports reception of an Authentication
+ * frame in station and IBSS modes when the local MLME processed the
+ * frame, i.e., it was for the local STA and was received in correct
+ * state. This is similar to MLME-AUTHENTICATE.confirm primitive in the
+ * MLME SAP interface (kernel providing MLME, userspace SME). The
+ * included %NL80211_ATTR_FRAME attribute contains the management frame
+ * (including both the header and frame body, but not FCS). This event is
+ * also used to indicate if the authentication attempt timed out. In that
+ * case the %NL80211_ATTR_FRAME attribute is replaced with a
+ * %NL80211_ATTR_TIMED_OUT flag (and %NL80211_ATTR_MAC to indicate which
+ * pending authentication timed out).
+ * @NL80211_CMD_ASSOCIATE: association request and notification; like
+ * NL80211_CMD_AUTHENTICATE but for Association and Reassociation
+ * (similar to MLME-ASSOCIATE.request, MLME-REASSOCIATE.request,
+ * MLME-ASSOCIATE.confirm or MLME-REASSOCIATE.confirm primitives).
+ * @NL80211_CMD_DEAUTHENTICATE: deauthentication request and notification; like
+ * NL80211_CMD_AUTHENTICATE but for Deauthentication frames (similar to
+ * MLME-DEAUTHENTICATION.request and MLME-DEAUTHENTICATE.indication
+ * primitives).
+ * @NL80211_CMD_DISASSOCIATE: disassociation request and notification; like
+ * NL80211_CMD_AUTHENTICATE but for Disassociation frames (similar to
+ * MLME-DISASSOCIATE.request and MLME-DISASSOCIATE.indication primitives).
+ *
+ * @NL80211_CMD_MICHAEL_MIC_FAILURE: notification of a locally detected Michael
+ * MIC (part of TKIP) failure; sent on the "mlme" multicast group; the
+ * event includes %NL80211_ATTR_MAC to describe the source MAC address of
+ * the frame with invalid MIC, %NL80211_ATTR_KEY_TYPE to show the key
+ * type, %NL80211_ATTR_KEY_IDX to indicate the key identifier, and
+ * %NL80211_ATTR_KEY_SEQ to indicate the TSC value of the frame; this
+ * event matches with MLME-MICHAELMICFAILURE.indication() primitive
+ *
+ * @NL80211_CMD_JOIN_IBSS: Join a new IBSS -- given at least an SSID and a
+ * FREQ attribute (for the initial frequency if no peer can be found)
+ * and optionally a MAC (as BSSID) and FREQ_FIXED attribute if those
+ * should be fixed rather than automatically determined. Can only be
+ * executed on a network interface that is UP, and fixed BSSID/FREQ
+ * may be rejected. Another optional parameter is the beacon interval,
+ * given in the %NL80211_ATTR_BEACON_INTERVAL attribute, which if not
+ * given defaults to 100 TU (102.4ms).
+ * @NL80211_CMD_LEAVE_IBSS: Leave the IBSS -- no special arguments, the IBSS is
+ * determined by the network interface.
+ *
+ * @NL80211_CMD_TESTMODE: testmode command, takes a wiphy (or ifindex) attribute
+ * to identify the device, and the TESTDATA blob attribute to pass through
+ * to the driver.
+ *
+ * @NL80211_CMD_CONNECT: connection request and notification; this command
+ * requests to connect to a specified network but without separating
+ * auth and assoc steps. For this, you need to specify the SSID in a
+ * %NL80211_ATTR_SSID attribute, and can optionally specify the association
+ * IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_MAC,
+ * %NL80211_ATTR_WIPHY_FREQ, %NL80211_ATTR_CONTROL_PORT,
+ * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE and
+ * %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT.
+ * It is also sent as an event, with the BSSID and response IEs when the
+ * connection is established or failed to be established. This can be
+ * determined by the STATUS_CODE attribute.
+ * @NL80211_CMD_ROAM: request that the card roam (currently not implemented),
+ * sent as an event when the card/driver roamed by itself.
+ * @NL80211_CMD_DISCONNECT: drop a given connection; also used to notify
+ * userspace that a connection was dropped by the AP or due to other
+ * reasons, for this the %NL80211_ATTR_DISCONNECTED_BY_AP and
+ * %NL80211_ATTR_REASON_CODE attributes are used.
+ *
+ * @NL80211_CMD_SET_WIPHY_NETNS: Set a wiphy's netns. Note that all devices
+ * associated with this wiphy must be down and will follow.
+ *
+ * @NL80211_CMD_REMAIN_ON_CHANNEL: Request to remain awake on the specified
+ * channel for the specified amount of time. This can be used to do
+ * off-channel operations like transmit a Public Action frame and wait for
+ * a response while being associated to an AP on another channel.
+ * %NL80211_ATTR_IFINDEX is used to specify which interface (and thus
+ * radio) is used. %NL80211_ATTR_WIPHY_FREQ is used to specify the
+ * frequency for the operation and %NL80211_ATTR_WIPHY_CHANNEL_TYPE may be
+ * optionally used to specify additional channel parameters.
+ * %NL80211_ATTR_DURATION is used to specify the duration in milliseconds
+ * to remain on the channel. This command is also used as an event to
+ * notify when the requested duration starts (it may take a while for the
+ * driver to schedule this time due to other concurrent needs for the
+ * radio).
+ * When called, this operation returns a cookie (%NL80211_ATTR_COOKIE)
+ * that will be included with any events pertaining to this request;
+ * the cookie is also used to cancel the request.
+ * @NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL: This command can be used to cancel a
+ * pending remain-on-channel duration if the desired operation has been
+ * completed prior to expiration of the originally requested duration.
+ * %NL80211_ATTR_WIPHY or %NL80211_ATTR_IFINDEX is used to specify the
+ * radio. The %NL80211_ATTR_COOKIE attribute must be given as well to
+ * uniquely identify the request.
+ * This command is also used as an event to notify when a requested
+ * remain-on-channel duration has expired.
+ *
+ * @NL80211_CMD_SET_TX_BITRATE_MASK: Set the mask of rates to be used in TX
+ * rate selection. %NL80211_ATTR_IFINDEX is used to specify the interface
+ * and @NL80211_ATTR_TX_RATES the set of allowed rates.
+ *
+ * @NL80211_CMD_REGISTER_FRAME: Register for receiving certain mgmt frames
+ * (via @NL80211_CMD_FRAME) for processing in userspace. This command
+ * requires an interface index, a frame type attribute (optional for
+ * backward compatibility reasons, if not given assumes action frames)
+ * and a match attribute containing the first few bytes of the frame
+ * that should match, e.g. a single byte for only a category match or
+ * four bytes for vendor frames including the OUI. The registration
+ * cannot be dropped, but is removed automatically when the netlink
+ * socket is closed. Multiple registrations can be made.
+ * @NL80211_CMD_REGISTER_ACTION: Alias for @NL80211_CMD_REGISTER_FRAME for
+ * backward compatibility
+ * @NL80211_CMD_FRAME: Management frame TX request and RX notification. This
+ * command is used both as a request to transmit a management frame and
+ * as an event indicating reception of a frame that was not processed in
+ * kernel code, but is for us (i.e., which may need to be processed in a
+ * user space application). %NL80211_ATTR_FRAME is used to specify the
+ * frame contents (including header). %NL80211_ATTR_WIPHY_FREQ (and
+ * optionally %NL80211_ATTR_WIPHY_CHANNEL_TYPE) is used to indicate on
+ * which channel the frame is to be transmitted or was received. If this
+ * channel is not the current channel (remain-on-channel or the
+ * operational channel) the device will switch to the given channel and
+ * transmit the frame, optionally waiting for a response for the time
+ * specified using %NL80211_ATTR_DURATION. When called, this operation
+ * returns a cookie (%NL80211_ATTR_COOKIE) that will be included with the
+ * TX status event pertaining to the TX request.
+ * @NL80211_CMD_FRAME_WAIT_CANCEL: When an off-channel TX was requested, this
+ * command may be used with the corresponding cookie to cancel the wait
+ * time if it is known that it is no longer necessary.
+ * @NL80211_CMD_ACTION: Alias for @NL80211_CMD_FRAME for backward compatibility.
+ * @NL80211_CMD_FRAME_TX_STATUS: Report TX status of a management frame
+ * transmitted with %NL80211_CMD_FRAME. %NL80211_ATTR_COOKIE identifies
+ * the TX command and %NL80211_ATTR_FRAME includes the contents of the
+ * frame. %NL80211_ATTR_ACK flag is included if the recipient acknowledged
+ * the frame.
+ * @NL80211_CMD_ACTION_TX_STATUS: Alias for @NL80211_CMD_FRAME_TX_STATUS for
+ * backward compatibility.
+ * @NL80211_CMD_SET_CQM: Connection quality monitor configuration. This command
+ * is used to configure connection quality monitoring notification trigger
+ * levels.
+ * @NL80211_CMD_NOTIFY_CQM: Connection quality monitor notification. This
+ * command is used as an event to indicate the that a trigger level was
+ * reached.
+ * @NL80211_CMD_SET_CHANNEL: Set the channel (using %NL80211_ATTR_WIPHY_FREQ
+ * and %NL80211_ATTR_WIPHY_CHANNEL_TYPE) the given interface (identifed
+ * by %NL80211_ATTR_IFINDEX) shall operate on.
+ * In case multiple channels are supported by the device, the mechanism
+ * with which it switches channels is implementation-defined.
+ * When a monitor interface is given, it can only switch channel while
+ * no other interfaces are operating to avoid disturbing the operation
+ * of any other interfaces, and other interfaces will again take
+ * precedence when they are used.
+ *
+ * @NL80211_CMD_SET_WDS_PEER: Set the MAC address of the peer on a WDS interface.
+ *
+ * @NL80211_CMD_JOIN_MESH: Join a mesh. The mesh ID must be given, and initial
+ * mesh config parameters may be given.
+ * @NL80211_CMD_LEAVE_MESH: Leave the mesh network -- no special arguments, the
+ * network is determined by the network interface.
+ *
+ * @NL80211_CMD_MAX: highest used command number
+ * @__NL80211_CMD_AFTER_LAST: internal use
+ */
+enum nl80211_commands {
+/* don't change the order or add anything inbetween, this is ABI! */
+ NL80211_CMD_UNSPEC,
+
+ NL80211_CMD_GET_WIPHY, /* can dump */
+ NL80211_CMD_SET_WIPHY,
+ NL80211_CMD_NEW_WIPHY,
+ NL80211_CMD_DEL_WIPHY,
+
+ NL80211_CMD_GET_INTERFACE, /* can dump */
+ NL80211_CMD_SET_INTERFACE,
+ NL80211_CMD_NEW_INTERFACE,
+ NL80211_CMD_DEL_INTERFACE,
+
+ NL80211_CMD_GET_KEY,
+ NL80211_CMD_SET_KEY,
+ NL80211_CMD_NEW_KEY,
+ NL80211_CMD_DEL_KEY,
+
+ NL80211_CMD_GET_BEACON,
+ NL80211_CMD_SET_BEACON,
+ NL80211_CMD_NEW_BEACON,
+ NL80211_CMD_DEL_BEACON,
+
+ NL80211_CMD_GET_STATION,
+ NL80211_CMD_SET_STATION,
+ NL80211_CMD_NEW_STATION,
+ NL80211_CMD_DEL_STATION,
+
+ NL80211_CMD_GET_MPATH,
+ NL80211_CMD_SET_MPATH,
+ NL80211_CMD_NEW_MPATH,
+ NL80211_CMD_DEL_MPATH,
+
+ NL80211_CMD_SET_BSS,
+
+ NL80211_CMD_SET_REG,
+ NL80211_CMD_REQ_SET_REG,
+
+ NL80211_CMD_GET_MESH_PARAMS,
+ NL80211_CMD_SET_MESH_PARAMS,
+
+ NL80211_CMD_SET_MGMT_EXTRA_IE /* reserved; not used */,
+
+ NL80211_CMD_GET_REG,
+
+ NL80211_CMD_GET_SCAN,
+ NL80211_CMD_TRIGGER_SCAN,
+ NL80211_CMD_NEW_SCAN_RESULTS,
+ NL80211_CMD_SCAN_ABORTED,
+
+ NL80211_CMD_REG_CHANGE,
+
+ NL80211_CMD_AUTHENTICATE,
+ NL80211_CMD_ASSOCIATE,
+ NL80211_CMD_DEAUTHENTICATE,
+ NL80211_CMD_DISASSOCIATE,
+
+ NL80211_CMD_MICHAEL_MIC_FAILURE,
+
+ NL80211_CMD_REG_BEACON_HINT,
+
+ NL80211_CMD_JOIN_IBSS,
+ NL80211_CMD_LEAVE_IBSS,
+
+ NL80211_CMD_TESTMODE,
+
+ NL80211_CMD_CONNECT,
+ NL80211_CMD_ROAM,
+ NL80211_CMD_DISCONNECT,
+
+ NL80211_CMD_SET_WIPHY_NETNS,
+
+ NL80211_CMD_GET_SURVEY,
+ NL80211_CMD_NEW_SURVEY_RESULTS,
+
+ NL80211_CMD_SET_PMKSA,
+ NL80211_CMD_DEL_PMKSA,
+ NL80211_CMD_FLUSH_PMKSA,
+
+ NL80211_CMD_REMAIN_ON_CHANNEL,
+ NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
+
+ NL80211_CMD_SET_TX_BITRATE_MASK,
+
+ NL80211_CMD_REGISTER_FRAME,
+ NL80211_CMD_REGISTER_ACTION = NL80211_CMD_REGISTER_FRAME,
+ NL80211_CMD_FRAME,
+ NL80211_CMD_ACTION = NL80211_CMD_FRAME,
+ NL80211_CMD_FRAME_TX_STATUS,
+ NL80211_CMD_ACTION_TX_STATUS = NL80211_CMD_FRAME_TX_STATUS,
+
+ NL80211_CMD_SET_POWER_SAVE,
+ NL80211_CMD_GET_POWER_SAVE,
+
+ NL80211_CMD_SET_CQM,
+ NL80211_CMD_NOTIFY_CQM,
+
+ NL80211_CMD_SET_CHANNEL,
+ NL80211_CMD_SET_WDS_PEER,
+
+ NL80211_CMD_FRAME_WAIT_CANCEL,
+
+ NL80211_CMD_JOIN_MESH,
+ NL80211_CMD_LEAVE_MESH,
+
+ /* add new commands above here */
+
+ /* used to define NL80211_CMD_MAX below */
+ __NL80211_CMD_AFTER_LAST,
+ NL80211_CMD_MAX = __NL80211_CMD_AFTER_LAST - 1
+};
+
+/*
+ * Allow user space programs to use #ifdef on new commands by defining them
+ * here
+ */
+#define NL80211_CMD_SET_BSS NL80211_CMD_SET_BSS
+#define NL80211_CMD_SET_MGMT_EXTRA_IE NL80211_CMD_SET_MGMT_EXTRA_IE
+#define NL80211_CMD_REG_CHANGE NL80211_CMD_REG_CHANGE
+#define NL80211_CMD_AUTHENTICATE NL80211_CMD_AUTHENTICATE
+#define NL80211_CMD_ASSOCIATE NL80211_CMD_ASSOCIATE
+#define NL80211_CMD_DEAUTHENTICATE NL80211_CMD_DEAUTHENTICATE
+#define NL80211_CMD_DISASSOCIATE NL80211_CMD_DISASSOCIATE
+#define NL80211_CMD_REG_BEACON_HINT NL80211_CMD_REG_BEACON_HINT
+
+/**
+ * enum nl80211_attrs - nl80211 netlink attributes
+ *
+ * @NL80211_ATTR_UNSPEC: unspecified attribute to catch errors
+ *
+ * @NL80211_ATTR_WIPHY: index of wiphy to operate on, cf.
+ * /sys/class/ieee80211/<phyname>/index
+ * @NL80211_ATTR_WIPHY_NAME: wiphy name (used for renaming)
+ * @NL80211_ATTR_WIPHY_TXQ_PARAMS: a nested array of TX queue parameters
+ * @NL80211_ATTR_WIPHY_FREQ: frequency of the selected channel in MHz
+ * @NL80211_ATTR_WIPHY_CHANNEL_TYPE: included with NL80211_ATTR_WIPHY_FREQ
+ * if HT20 or HT40 are allowed (i.e., 802.11n disabled if not included):
+ * NL80211_CHAN_NO_HT = HT not allowed (i.e., same as not including
+ * this attribute)
+ * NL80211_CHAN_HT20 = HT20 only
+ * NL80211_CHAN_HT40MINUS = secondary channel is below the primary channel
+ * NL80211_CHAN_HT40PLUS = secondary channel is above the primary channel
+ * @NL80211_ATTR_WIPHY_RETRY_SHORT: TX retry limit for frames whose length is
+ * less than or equal to the RTS threshold; allowed range: 1..255;
+ * dot11ShortRetryLimit; u8
+ * @NL80211_ATTR_WIPHY_RETRY_LONG: TX retry limit for frames whose length is
+ * greater than the RTS threshold; allowed range: 1..255;
+ * dot11ShortLongLimit; u8
+ * @NL80211_ATTR_WIPHY_FRAG_THRESHOLD: fragmentation threshold, i.e., maximum
+ * length in octets for frames; allowed range: 256..8000, disable
+ * fragmentation with (u32)-1; dot11FragmentationThreshold; u32
+ * @NL80211_ATTR_WIPHY_RTS_THRESHOLD: RTS threshold (TX frames with length
+ * larger than or equal to this use RTS/CTS handshake); allowed range:
+ * 0..65536, disable with (u32)-1; dot11RTSThreshold; u32
+ * @NL80211_ATTR_WIPHY_COVERAGE_CLASS: Coverage Class as defined by IEEE 802.11
+ * section 7.3.2.9; dot11CoverageClass; u8
+ *
+ * @NL80211_ATTR_IFINDEX: network interface index of the device to operate on
+ * @NL80211_ATTR_IFNAME: network interface name
+ * @NL80211_ATTR_IFTYPE: type of virtual interface, see &enum nl80211_iftype
+ *
+ * @NL80211_ATTR_MAC: MAC address (various uses)
+ *
+ * @NL80211_ATTR_KEY_DATA: (temporal) key data; for TKIP this consists of
+ * 16 bytes encryption key followed by 8 bytes each for TX and RX MIC
+ * keys
+ * @NL80211_ATTR_KEY_IDX: key ID (u8, 0-3)
+ * @NL80211_ATTR_KEY_CIPHER: key cipher suite (u32, as defined by IEEE 802.11
+ * section 7.3.2.25.1, e.g. 0x000FAC04)
+ * @NL80211_ATTR_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and
+ * CCMP keys, each six bytes in little endian
+ *
+ * @NL80211_ATTR_BEACON_INTERVAL: beacon interval in TU
+ * @NL80211_ATTR_DTIM_PERIOD: DTIM period for beaconing
+ * @NL80211_ATTR_BEACON_HEAD: portion of the beacon before the TIM IE
+ * @NL80211_ATTR_BEACON_TAIL: portion of the beacon after the TIM IE
+ *
+ * @NL80211_ATTR_STA_AID: Association ID for the station (u16)
+ * @NL80211_ATTR_STA_FLAGS: flags, nested element with NLA_FLAG attributes of
+ * &enum nl80211_sta_flags (deprecated, use %NL80211_ATTR_STA_FLAGS2)
+ * @NL80211_ATTR_STA_LISTEN_INTERVAL: listen interval as defined by
+ * IEEE 802.11 7.3.1.6 (u16).
+ * @NL80211_ATTR_STA_SUPPORTED_RATES: supported rates, array of supported
+ * rates as defined by IEEE 802.11 7.3.2.2 but without the length
+ * restriction (at most %NL80211_MAX_SUPP_RATES).
+ * @NL80211_ATTR_STA_VLAN: interface index of VLAN interface to move station
+ * to, or the AP interface the station was originally added to to.
+ * @NL80211_ATTR_STA_INFO: information about a station, part of station info
+ * given for %NL80211_CMD_GET_STATION, nested attribute containing
+ * info as possible, see &enum nl80211_sta_info.
+ *
+ * @NL80211_ATTR_WIPHY_BANDS: Information about an operating bands,
+ * consisting of a nested array.
+ *
+ * @NL80211_ATTR_MESH_ID: mesh id (1-32 bytes).
+ * @NL80211_ATTR_PLINK_ACTION: action to perform on the mesh peer link.
+ * @NL80211_ATTR_MPATH_NEXT_HOP: MAC address of the next hop for a mesh path.
+ * @NL80211_ATTR_MPATH_INFO: information about a mesh_path, part of mesh path
+ * info given for %NL80211_CMD_GET_MPATH, nested attribute described at
+ * &enum nl80211_mpath_info.
+ *
+ * @NL80211_ATTR_MNTR_FLAGS: flags, nested element with NLA_FLAG attributes of
+ * &enum nl80211_mntr_flags.
+ *
+ * @NL80211_ATTR_REG_ALPHA2: an ISO-3166-alpha2 country code for which the
+ * current regulatory domain should be set to or is already set to.
+ * For example, 'CR', for Costa Rica. This attribute is used by the kernel
+ * to query the CRDA to retrieve one regulatory domain. This attribute can
+ * also be used by userspace to query the kernel for the currently set
+ * regulatory domain. We chose an alpha2 as that is also used by the
+ * IEEE-802.11d country information element to identify a country.
+ * Users can also simply ask the wireless core to set regulatory domain
+ * to a specific alpha2.
+ * @NL80211_ATTR_REG_RULES: a nested array of regulatory domain regulatory
+ * rules.
+ *
+ * @NL80211_ATTR_BSS_CTS_PROT: whether CTS protection is enabled (u8, 0 or 1)
+ * @NL80211_ATTR_BSS_SHORT_PREAMBLE: whether short preamble is enabled
+ * (u8, 0 or 1)
+ * @NL80211_ATTR_BSS_SHORT_SLOT_TIME: whether short slot time enabled
+ * (u8, 0 or 1)
+ * @NL80211_ATTR_BSS_BASIC_RATES: basic rates, array of basic
+ * rates in format defined by IEEE 802.11 7.3.2.2 but without the length
+ * restriction (at most %NL80211_MAX_SUPP_RATES).
+ *
+ * @NL80211_ATTR_HT_CAPABILITY: HT Capability information element (from
+ * association request when used with NL80211_CMD_NEW_STATION)
+ *
+ * @NL80211_ATTR_SUPPORTED_IFTYPES: nested attribute containing all
+ * supported interface types, each a flag attribute with the number
+ * of the interface mode.
+ *
+ * @NL80211_ATTR_MGMT_SUBTYPE: Management frame subtype for
+ * %NL80211_CMD_SET_MGMT_EXTRA_IE.
+ *
+ * @NL80211_ATTR_IE: Information element(s) data (used, e.g., with
+ * %NL80211_CMD_SET_MGMT_EXTRA_IE).
+ *
+ * @NL80211_ATTR_MAX_NUM_SCAN_SSIDS: number of SSIDs you can scan with
+ * a single scan request, a wiphy attribute.
+ * @NL80211_ATTR_MAX_SCAN_IE_LEN: maximum length of information elements
+ * that can be added to a scan request
+ *
+ * @NL80211_ATTR_SCAN_FREQUENCIES: nested attribute with frequencies (in MHz)
+ * @NL80211_ATTR_SCAN_SSIDS: nested attribute with SSIDs, leave out for passive
+ * scanning and include a zero-length SSID (wildcard) for wildcard scan
+ * @NL80211_ATTR_BSS: scan result BSS
+ *
+ * @NL80211_ATTR_REG_INITIATOR: indicates who requested the regulatory domain
+ * currently in effect. This could be any of the %NL80211_REGDOM_SET_BY_*
+ * @NL80211_ATTR_REG_TYPE: indicates the type of the regulatory domain currently
+ * set. This can be one of the nl80211_reg_type (%NL80211_REGDOM_TYPE_*)
+ *
+ * @NL80211_ATTR_SUPPORTED_COMMANDS: wiphy attribute that specifies
+ * an array of command numbers (i.e. a mapping index to command number)
+ * that the driver for the given wiphy supports.
+ *
+ * @NL80211_ATTR_FRAME: frame data (binary attribute), including frame header
+ * and body, but not FCS; used, e.g., with NL80211_CMD_AUTHENTICATE and
+ * NL80211_CMD_ASSOCIATE events
+ * @NL80211_ATTR_SSID: SSID (binary attribute, 0..32 octets)
+ * @NL80211_ATTR_AUTH_TYPE: AuthenticationType, see &enum nl80211_auth_type,
+ * represented as a u32
+ * @NL80211_ATTR_REASON_CODE: ReasonCode for %NL80211_CMD_DEAUTHENTICATE and
+ * %NL80211_CMD_DISASSOCIATE, u16
+ *
+ * @NL80211_ATTR_KEY_TYPE: Key Type, see &enum nl80211_key_type, represented as
+ * a u32
+ *
+ * @NL80211_ATTR_FREQ_BEFORE: A channel which has suffered a regulatory change
+ * due to considerations from a beacon hint. This attribute reflects
+ * the state of the channel _before_ the beacon hint processing. This
+ * attributes consists of a nested attribute containing
+ * NL80211_FREQUENCY_ATTR_*
+ * @NL80211_ATTR_FREQ_AFTER: A channel which has suffered a regulatory change
+ * due to considerations from a beacon hint. This attribute reflects
+ * the state of the channel _after_ the beacon hint processing. This
+ * attributes consists of a nested attribute containing
+ * NL80211_FREQUENCY_ATTR_*
+ *
+ * @NL80211_ATTR_CIPHER_SUITES: a set of u32 values indicating the supported
+ * cipher suites
+ *
+ * @NL80211_ATTR_FREQ_FIXED: a flag indicating the IBSS should not try to look
+ * for other networks on different channels
+ *
+ * @NL80211_ATTR_TIMED_OUT: a flag indicating than an operation timed out; this
+ * is used, e.g., with %NL80211_CMD_AUTHENTICATE event
+ *
+ * @NL80211_ATTR_USE_MFP: Whether management frame protection (IEEE 802.11w) is
+ * used for the association (&enum nl80211_mfp, represented as a u32);
+ * this attribute can be used
+ * with %NL80211_CMD_ASSOCIATE request
+ *
+ * @NL80211_ATTR_STA_FLAGS2: Attribute containing a
+ * &struct nl80211_sta_flag_update.
+ *
+ * @NL80211_ATTR_CONTROL_PORT: A flag indicating whether user space controls
+ * IEEE 802.1X port, i.e., sets/clears %NL80211_STA_FLAG_AUTHORIZED, in
+ * station mode. If the flag is included in %NL80211_CMD_ASSOCIATE
+ * request, the driver will assume that the port is unauthorized until
+ * authorized by user space. Otherwise, port is marked authorized by
+ * default in station mode.
+ * @NL80211_ATTR_CONTROL_PORT_ETHERTYPE: A 16-bit value indicating the
+ * ethertype that will be used for key negotiation. It can be
+ * specified with the associate and connect commands. If it is not
+ * specified, the value defaults to 0x888E (PAE, 802.1X). This
+ * attribute is also used as a flag in the wiphy information to
+ * indicate that protocols other than PAE are supported.
+ * @NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT: When included along with
+ * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE, indicates that the custom
+ * ethertype frames used for key negotiation must not be encrypted.
+ *
+ * @NL80211_ATTR_TESTDATA: Testmode data blob, passed through to the driver.
+ * We recommend using nested, driver-specific attributes within this.
+ *
+ * @NL80211_ATTR_DISCONNECTED_BY_AP: A flag indicating that the DISCONNECT
+ * event was due to the AP disconnecting the station, and not due to
+ * a local disconnect request.
+ * @NL80211_ATTR_STATUS_CODE: StatusCode for the %NL80211_CMD_CONNECT
+ * event (u16)
+ * @NL80211_ATTR_PRIVACY: Flag attribute, used with connect(), indicating
+ * that protected APs should be used.
+ *
+ * @NL80211_ATTR_CIPHERS_PAIRWISE: Used with CONNECT and ASSOCIATE to
+ * indicate which unicast key ciphers will be used with the connection
+ * (an array of u32).
+ * @NL80211_ATTR_CIPHER_GROUP: Used with CONNECT and ASSOCIATE to indicate
+ * which group key cipher will be used with the connection (a u32).
+ * @NL80211_ATTR_WPA_VERSIONS: Used with CONNECT and ASSOCIATE to indicate
+ * which WPA version(s) the AP we want to associate with is using
+ * (a u32 with flags from &enum nl80211_wpa_versions).
+ * @NL80211_ATTR_AKM_SUITES: Used with CONNECT and ASSOCIATE to indicate
+ * which key management algorithm(s) to use (an array of u32).
+ *
+ * @NL80211_ATTR_REQ_IE: (Re)association request information elements as
+ * sent out by the card, for ROAM and successful CONNECT events.
+ * @NL80211_ATTR_RESP_IE: (Re)association response information elements as
+ * sent by peer, for ROAM and successful CONNECT events.
+ *
+ * @NL80211_ATTR_PREV_BSSID: previous BSSID, to be used by in ASSOCIATE
+ * commands to specify using a reassociate frame
+ *
+ * @NL80211_ATTR_KEY: key information in a nested attribute with
+ * %NL80211_KEY_* sub-attributes
+ * @NL80211_ATTR_KEYS: array of keys for static WEP keys for connect()
+ * and join_ibss(), key information is in a nested attribute each
+ * with %NL80211_KEY_* sub-attributes
+ *
+ * @NL80211_ATTR_PID: Process ID of a network namespace.
+ *
+ * @NL80211_ATTR_GENERATION: Used to indicate consistent snapshots for
+ * dumps. This number increases whenever the object list being
+ * dumped changes, and as such userspace can verify that it has
+ * obtained a complete and consistent snapshot by verifying that
+ * all dump messages contain the same generation number. If it
+ * changed then the list changed and the dump should be repeated
+ * completely from scratch.
+ *
+ * @NL80211_ATTR_4ADDR: Use 4-address frames on a virtual interface
+ *
+ * @NL80211_ATTR_SURVEY_INFO: survey information about a channel, part of
+ * the survey response for %NL80211_CMD_GET_SURVEY, nested attribute
+ * containing info as possible, see &enum survey_info.
+ *
+ * @NL80211_ATTR_PMKID: PMK material for PMKSA caching.
+ * @NL80211_ATTR_MAX_NUM_PMKIDS: maximum number of PMKIDs a firmware can
+ * cache, a wiphy attribute.
+ *
+ * @NL80211_ATTR_DURATION: Duration of an operation in milliseconds, u32.
+ *
+ * @NL80211_ATTR_COOKIE: Generic 64-bit cookie to identify objects.
+ *
+ * @NL80211_ATTR_TX_RATES: Nested set of attributes
+ * (enum nl80211_tx_rate_attributes) describing TX rates per band. The
+ * enum nl80211_band value is used as the index (nla_type() of the nested
+ * data. If a band is not included, it will be configured to allow all
+ * rates based on negotiated supported rates information. This attribute
+ * is used with %NL80211_CMD_SET_TX_BITRATE_MASK.
+ *
+ * @NL80211_ATTR_FRAME_MATCH: A binary attribute which typically must contain
+ * at least one byte, currently used with @NL80211_CMD_REGISTER_FRAME.
+ * @NL80211_ATTR_FRAME_TYPE: A u16 indicating the frame type/subtype for the
+ * @NL80211_CMD_REGISTER_FRAME command.
+ * @NL80211_ATTR_TX_FRAME_TYPES: wiphy capability attribute, which is a
+ * nested attribute of %NL80211_ATTR_FRAME_TYPE attributes, containing
+ * information about which frame types can be transmitted with
+ * %NL80211_CMD_FRAME.
+ * @NL80211_ATTR_RX_FRAME_TYPES: wiphy capability attribute, which is a
+ * nested attribute of %NL80211_ATTR_FRAME_TYPE attributes, containing
+ * information about which frame types can be registered for RX.
+ *
+ * @NL80211_ATTR_ACK: Flag attribute indicating that the frame was
+ * acknowledged by the recipient.
+ *
+ * @NL80211_ATTR_CQM: connection quality monitor configuration in a
+ * nested attribute with %NL80211_ATTR_CQM_* sub-attributes.
+ *
+ * @NL80211_ATTR_LOCAL_STATE_CHANGE: Flag attribute to indicate that a command
+ * is requesting a local authentication/association state change without
+ * invoking actual management frame exchange. This can be used with
+ * NL80211_CMD_AUTHENTICATE, NL80211_CMD_DEAUTHENTICATE,
+ * NL80211_CMD_DISASSOCIATE.
+ *
+ * @NL80211_ATTR_AP_ISOLATE: (AP mode) Do not forward traffic between stations
+ * connected to this BSS.
+ *
+ * @NL80211_ATTR_WIPHY_TX_POWER_SETTING: Transmit power setting type. See
+ * &enum nl80211_tx_power_setting for possible values.
+ * @NL80211_ATTR_WIPHY_TX_POWER_LEVEL: Transmit power level in signed mBm units.
+ * This is used in association with @NL80211_ATTR_WIPHY_TX_POWER_SETTING
+ * for non-automatic settings.
+ *
+ * @NL80211_ATTR_SUPPORT_IBSS_RSN: The device supports IBSS RSN, which mostly
+ * means support for per-station GTKs.
+ *
+ * @NL80211_ATTR_WIPHY_ANTENNA_TX: Bitmap of allowed antennas for transmitting.
+ * This can be used to mask out antennas which are not attached or should
+ * not be used for transmitting. If an antenna is not selected in this
+ * bitmap the hardware is not allowed to transmit on this antenna.
+ *
+ * Each bit represents one antenna, starting with antenna 1 at the first
+ * bit. Depending on which antennas are selected in the bitmap, 802.11n
+ * drivers can derive which chainmasks to use (if all antennas belonging to
+ * a particular chain are disabled this chain should be disabled) and if
+ * a chain has diversity antennas whether diversity should be used or not.
+ * HT capabilities (STBC, TX Beamforming, Antenna selection) can be
+ * derived from the available chains after applying the antenna mask.
+ * Non-802.11n drivers can derive wether to use diversity or not.
+ * Drivers may reject configurations or RX/TX mask combinations they cannot
+ * support by returning -EINVAL.
+ *
+ * @NL80211_ATTR_WIPHY_ANTENNA_RX: Bitmap of allowed antennas for receiving.
+ * This can be used to mask out antennas which are not attached or should
+ * not be used for receiving. If an antenna is not selected in this bitmap
+ * the hardware should not be configured to receive on this antenna.
+ * For a more detailed description see @NL80211_ATTR_WIPHY_ANTENNA_TX.
+ *
+ * @NL80211_ATTR_MCAST_RATE: Multicast tx rate (in 100 kbps) for IBSS
+ *
+ * @NL80211_ATTR_OFFCHANNEL_TX_OK: For management frame TX, the frame may be
+ * transmitted on another channel when the channel given doesn't match
+ * the current channel. If the current channel doesn't match and this
+ * flag isn't set, the frame will be rejected. This is also used as an
+ * nl80211 capability flag.
+ *
+ * @NL80211_ATTR_BSS_HTOPMODE: HT operation mode (u16)
+ *
+ * @NL80211_ATTR_MAX: highest attribute number currently defined
+ * @__NL80211_ATTR_AFTER_LAST: internal use
+ */
+enum nl80211_attrs {
+/* don't change the order or add anything between, this is ABI! */
+ NL80211_ATTR_UNSPEC,
+
+ NL80211_ATTR_WIPHY,
+ NL80211_ATTR_WIPHY_NAME,
+
+ NL80211_ATTR_IFINDEX,
+ NL80211_ATTR_IFNAME,
+ NL80211_ATTR_IFTYPE,
+
+ NL80211_ATTR_MAC,
+
+ NL80211_ATTR_KEY_DATA,
+ NL80211_ATTR_KEY_IDX,
+ NL80211_ATTR_KEY_CIPHER,
+ NL80211_ATTR_KEY_SEQ,
+ NL80211_ATTR_KEY_DEFAULT,
+
+ NL80211_ATTR_BEACON_INTERVAL,
+ NL80211_ATTR_DTIM_PERIOD,
+ NL80211_ATTR_BEACON_HEAD,
+ NL80211_ATTR_BEACON_TAIL,
+
+ NL80211_ATTR_STA_AID,
+ NL80211_ATTR_STA_FLAGS,
+ NL80211_ATTR_STA_LISTEN_INTERVAL,
+ NL80211_ATTR_STA_SUPPORTED_RATES,
+ NL80211_ATTR_STA_VLAN,
+ NL80211_ATTR_STA_INFO,
+
+ NL80211_ATTR_WIPHY_BANDS,
+
+ NL80211_ATTR_MNTR_FLAGS,
+
+ NL80211_ATTR_MESH_ID,
+ NL80211_ATTR_STA_PLINK_ACTION,
+ NL80211_ATTR_MPATH_NEXT_HOP,
+ NL80211_ATTR_MPATH_INFO,
+
+ NL80211_ATTR_BSS_CTS_PROT,
+ NL80211_ATTR_BSS_SHORT_PREAMBLE,
+ NL80211_ATTR_BSS_SHORT_SLOT_TIME,
+
+ NL80211_ATTR_HT_CAPABILITY,
+
+ NL80211_ATTR_SUPPORTED_IFTYPES,
+
+ NL80211_ATTR_REG_ALPHA2,
+ NL80211_ATTR_REG_RULES,
+
+ NL80211_ATTR_MESH_PARAMS,
+
+ NL80211_ATTR_BSS_BASIC_RATES,
+
+ NL80211_ATTR_WIPHY_TXQ_PARAMS,
+ NL80211_ATTR_WIPHY_FREQ,
+ NL80211_ATTR_WIPHY_CHANNEL_TYPE,
+
+ NL80211_ATTR_KEY_DEFAULT_MGMT,
+
+ NL80211_ATTR_MGMT_SUBTYPE,
+ NL80211_ATTR_IE,
+
+ NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
+
+ NL80211_ATTR_SCAN_FREQUENCIES,
+ NL80211_ATTR_SCAN_SSIDS,
+ NL80211_ATTR_GENERATION, /* replaces old SCAN_GENERATION */
+ NL80211_ATTR_BSS,
+
+ NL80211_ATTR_REG_INITIATOR,
+ NL80211_ATTR_REG_TYPE,
+
+ NL80211_ATTR_SUPPORTED_COMMANDS,
+
+ NL80211_ATTR_FRAME,
+ NL80211_ATTR_SSID,
+ NL80211_ATTR_AUTH_TYPE,
+ NL80211_ATTR_REASON_CODE,
+
+ NL80211_ATTR_KEY_TYPE,
+
+ NL80211_ATTR_MAX_SCAN_IE_LEN,
+ NL80211_ATTR_CIPHER_SUITES,
+
+ NL80211_ATTR_FREQ_BEFORE,
+ NL80211_ATTR_FREQ_AFTER,
+
+ NL80211_ATTR_FREQ_FIXED,
+
+
+ NL80211_ATTR_WIPHY_RETRY_SHORT,
+ NL80211_ATTR_WIPHY_RETRY_LONG,
+ NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
+ NL80211_ATTR_WIPHY_RTS_THRESHOLD,
+
+ NL80211_ATTR_TIMED_OUT,
+
+ NL80211_ATTR_USE_MFP,
+
+ NL80211_ATTR_STA_FLAGS2,
+
+ NL80211_ATTR_CONTROL_PORT,
+
+ NL80211_ATTR_TESTDATA,
+
+ NL80211_ATTR_PRIVACY,
+
+ NL80211_ATTR_DISCONNECTED_BY_AP,
+ NL80211_ATTR_STATUS_CODE,
+
+ NL80211_ATTR_CIPHER_SUITES_PAIRWISE,
+ NL80211_ATTR_CIPHER_SUITE_GROUP,
+ NL80211_ATTR_WPA_VERSIONS,
+ NL80211_ATTR_AKM_SUITES,
+
+ NL80211_ATTR_REQ_IE,
+ NL80211_ATTR_RESP_IE,
+
+ NL80211_ATTR_PREV_BSSID,
+
+ NL80211_ATTR_KEY,
+ NL80211_ATTR_KEYS,
+
+ NL80211_ATTR_PID,
+
+ NL80211_ATTR_4ADDR,
+
+ NL80211_ATTR_SURVEY_INFO,
+
+ NL80211_ATTR_PMKID,
+ NL80211_ATTR_MAX_NUM_PMKIDS,
+
+ NL80211_ATTR_DURATION,
+
+ NL80211_ATTR_COOKIE,
+
+ NL80211_ATTR_WIPHY_COVERAGE_CLASS,
+
+ NL80211_ATTR_TX_RATES,
+
+ NL80211_ATTR_FRAME_MATCH,
+
+ NL80211_ATTR_ACK,
+
+ NL80211_ATTR_PS_STATE,
+
+ NL80211_ATTR_CQM,
+
+ NL80211_ATTR_LOCAL_STATE_CHANGE,
+
+ NL80211_ATTR_AP_ISOLATE,
+
+ NL80211_ATTR_WIPHY_TX_POWER_SETTING,
+ NL80211_ATTR_WIPHY_TX_POWER_LEVEL,
+
+ NL80211_ATTR_TX_FRAME_TYPES,
+ NL80211_ATTR_RX_FRAME_TYPES,
+ NL80211_ATTR_FRAME_TYPE,
+
+ NL80211_ATTR_CONTROL_PORT_ETHERTYPE,
+ NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT,
+
+ NL80211_ATTR_SUPPORT_IBSS_RSN,
+
+ NL80211_ATTR_WIPHY_ANTENNA_TX,
+ NL80211_ATTR_WIPHY_ANTENNA_RX,
+
+ NL80211_ATTR_MCAST_RATE,
+
+ NL80211_ATTR_OFFCHANNEL_TX_OK,
+
+ NL80211_ATTR_BSS_HT_OPMODE,
+
+ /* add attributes here, update the policy in nl80211.c */
+
+ __NL80211_ATTR_AFTER_LAST,
+ NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
+};
+
+/* source-level API compatibility */
+#define NL80211_ATTR_SCAN_GENERATION NL80211_ATTR_GENERATION
+
+/*
+ * Allow user space programs to use #ifdef on new attributes by defining them
+ * here
+ */
+#define NL80211_CMD_CONNECT NL80211_CMD_CONNECT
+#define NL80211_ATTR_HT_CAPABILITY NL80211_ATTR_HT_CAPABILITY
+#define NL80211_ATTR_BSS_BASIC_RATES NL80211_ATTR_BSS_BASIC_RATES
+#define NL80211_ATTR_WIPHY_TXQ_PARAMS NL80211_ATTR_WIPHY_TXQ_PARAMS
+#define NL80211_ATTR_WIPHY_FREQ NL80211_ATTR_WIPHY_FREQ
+#define NL80211_ATTR_WIPHY_CHANNEL_TYPE NL80211_ATTR_WIPHY_CHANNEL_TYPE
+#define NL80211_ATTR_MGMT_SUBTYPE NL80211_ATTR_MGMT_SUBTYPE
+#define NL80211_ATTR_IE NL80211_ATTR_IE
+#define NL80211_ATTR_REG_INITIATOR NL80211_ATTR_REG_INITIATOR
+#define NL80211_ATTR_REG_TYPE NL80211_ATTR_REG_TYPE
+#define NL80211_ATTR_FRAME NL80211_ATTR_FRAME
+#define NL80211_ATTR_SSID NL80211_ATTR_SSID
+#define NL80211_ATTR_AUTH_TYPE NL80211_ATTR_AUTH_TYPE
+#define NL80211_ATTR_REASON_CODE NL80211_ATTR_REASON_CODE
+#define NL80211_ATTR_CIPHER_SUITES_PAIRWISE NL80211_ATTR_CIPHER_SUITES_PAIRWISE
+#define NL80211_ATTR_CIPHER_SUITE_GROUP NL80211_ATTR_CIPHER_SUITE_GROUP
+#define NL80211_ATTR_WPA_VERSIONS NL80211_ATTR_WPA_VERSIONS
+#define NL80211_ATTR_AKM_SUITES NL80211_ATTR_AKM_SUITES
+#define NL80211_ATTR_KEY NL80211_ATTR_KEY
+#define NL80211_ATTR_KEYS NL80211_ATTR_KEYS
+
+#define NL80211_MAX_SUPP_RATES 32
+#define NL80211_MAX_SUPP_REG_RULES 32
+#define NL80211_TKIP_DATA_OFFSET_ENCR_KEY 0
+#define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16
+#define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24
+#define NL80211_HT_CAPABILITY_LEN 26
+
+#define NL80211_MAX_NR_CIPHER_SUITES 5
+#define NL80211_MAX_NR_AKM_SUITES 2
+
+/**
+ * enum nl80211_iftype - (virtual) interface types
+ *
+ * @NL80211_IFTYPE_UNSPECIFIED: unspecified type, driver decides
+ * @NL80211_IFTYPE_ADHOC: independent BSS member
+ * @NL80211_IFTYPE_STATION: managed BSS member
+ * @NL80211_IFTYPE_AP: access point
+ * @NL80211_IFTYPE_AP_VLAN: VLAN interface for access points
+ * @NL80211_IFTYPE_WDS: wireless distribution interface
+ * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames
+ * @NL80211_IFTYPE_MESH_POINT: mesh point
+ * @NL80211_IFTYPE_P2P_CLIENT: P2P client
+ * @NL80211_IFTYPE_P2P_GO: P2P group owner
+ * @NL80211_IFTYPE_MAX: highest interface type number currently defined
+ * @NUM_NL80211_IFTYPES: number of defined interface types
+ *
+ * These values are used with the %NL80211_ATTR_IFTYPE
+ * to set the type of an interface.
+ *
+ */
+enum nl80211_iftype {
+ NL80211_IFTYPE_UNSPECIFIED,
+ NL80211_IFTYPE_ADHOC,
+ NL80211_IFTYPE_STATION,
+ NL80211_IFTYPE_AP,
+ NL80211_IFTYPE_AP_VLAN,
+ NL80211_IFTYPE_WDS,
+ NL80211_IFTYPE_MONITOR,
+ NL80211_IFTYPE_MESH_POINT,
+ NL80211_IFTYPE_P2P_CLIENT,
+ NL80211_IFTYPE_P2P_GO,
+
+ /* keep last */
+ NUM_NL80211_IFTYPES,
+ NL80211_IFTYPE_MAX = NUM_NL80211_IFTYPES - 1
+};
+
+/**
+ * enum nl80211_sta_flags - station flags
+ *
+ * Station flags. When a station is added to an AP interface, it is
+ * assumed to be already associated (and hence authenticated.)
+ *
+ * @__NL80211_STA_FLAG_INVALID: attribute number 0 is reserved
+ * @NL80211_STA_FLAG_AUTHORIZED: station is authorized (802.1X)
+ * @NL80211_STA_FLAG_SHORT_PREAMBLE: station is capable of receiving frames
+ * with short barker preamble
+ * @NL80211_STA_FLAG_WME: station is WME/QoS capable
+ * @NL80211_STA_FLAG_MFP: station uses management frame protection
+ * @NL80211_STA_FLAG_MAX: highest station flag number currently defined
+ * @__NL80211_STA_FLAG_AFTER_LAST: internal use
+ */
+enum nl80211_sta_flags {
+ __NL80211_STA_FLAG_INVALID,
+ NL80211_STA_FLAG_AUTHORIZED,
+ NL80211_STA_FLAG_SHORT_PREAMBLE,
+ NL80211_STA_FLAG_WME,
+ NL80211_STA_FLAG_MFP,
+
+ /* keep last */
+ __NL80211_STA_FLAG_AFTER_LAST,
+ NL80211_STA_FLAG_MAX = __NL80211_STA_FLAG_AFTER_LAST - 1
+};
+
+/**
+ * struct nl80211_sta_flag_update - station flags mask/set
+ * @mask: mask of station flags to set
+ * @set: which values to set them to
+ *
+ * Both mask and set contain bits as per &enum nl80211_sta_flags.
+ */
+struct nl80211_sta_flag_update {
+ __u32 mask;
+ __u32 set;
+} __attribute__((packed));
+
+/**
+ * enum nl80211_rate_info - bitrate information
+ *
+ * These attribute types are used with %NL80211_STA_INFO_TXRATE
+ * when getting information about the bitrate of a station.
+ *
+ * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
+ * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s)
+ * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
+ * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 MHz dualchannel bitrate
+ * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
+ * @NL80211_RATE_INFO_MAX: highest rate_info number currently defined
+ * @__NL80211_RATE_INFO_AFTER_LAST: internal use
+ */
+enum nl80211_rate_info {
+ __NL80211_RATE_INFO_INVALID,
+ NL80211_RATE_INFO_BITRATE,
+ NL80211_RATE_INFO_MCS,
+ NL80211_RATE_INFO_40_MHZ_WIDTH,
+ NL80211_RATE_INFO_SHORT_GI,
+
+ /* keep last */
+ __NL80211_RATE_INFO_AFTER_LAST,
+ NL80211_RATE_INFO_MAX = __NL80211_RATE_INFO_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_sta_info - station information
+ *
+ * These attribute types are used with %NL80211_ATTR_STA_INFO
+ * when getting information about a station.
+ *
+ * @__NL80211_STA_INFO_INVALID: attribute number 0 is reserved
+ * @NL80211_STA_INFO_INACTIVE_TIME: time since last activity (u32, msecs)
+ * @NL80211_STA_INFO_RX_BYTES: total received bytes (u32, from this station)
+ * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
+ * @__NL80211_STA_INFO_AFTER_LAST: internal
+ * @NL80211_STA_INFO_MAX: highest possible station info attribute
+ * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm)
+ * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute
+ * containing info as possible, see &enum nl80211_sta_info_txrate.
+ * @NL80211_STA_INFO_RX_PACKETS: total received packet (u32, from this station)
+ * @NL80211_STA_INFO_TX_PACKETS: total transmitted packets (u32, to this
+ * station)
+ * @NL80211_STA_INFO_TX_RETRIES: total retries (u32, to this station)
+ * @NL80211_STA_INFO_TX_FAILED: total failed packets (u32, to this station)
+ * @NL80211_STA_INFO_SIGNAL_AVG: signal strength average (u8, dBm)
+ */
+enum nl80211_sta_info {
+ __NL80211_STA_INFO_INVALID,
+ NL80211_STA_INFO_INACTIVE_TIME,
+ NL80211_STA_INFO_RX_BYTES,
+ NL80211_STA_INFO_TX_BYTES,
+ NL80211_STA_INFO_LLID,
+ NL80211_STA_INFO_PLID,
+ NL80211_STA_INFO_PLINK_STATE,
+ NL80211_STA_INFO_SIGNAL,
+ NL80211_STA_INFO_TX_BITRATE,
+ NL80211_STA_INFO_RX_PACKETS,
+ NL80211_STA_INFO_TX_PACKETS,
+ NL80211_STA_INFO_TX_RETRIES,
+ NL80211_STA_INFO_TX_FAILED,
+ NL80211_STA_INFO_SIGNAL_AVG,
+
+ /* keep last */
+ __NL80211_STA_INFO_AFTER_LAST,
+ NL80211_STA_INFO_MAX = __NL80211_STA_INFO_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_mpath_flags - nl80211 mesh path flags
+ *
+ * @NL80211_MPATH_FLAG_ACTIVE: the mesh path is active
+ * @NL80211_MPATH_FLAG_RESOLVING: the mesh path discovery process is running
+ * @NL80211_MPATH_FLAG_SN_VALID: the mesh path contains a valid SN
+ * @NL80211_MPATH_FLAG_FIXED: the mesh path has been manually set
+ * @NL80211_MPATH_FLAG_RESOLVED: the mesh path discovery process succeeded
+ */
+enum nl80211_mpath_flags {
+ NL80211_MPATH_FLAG_ACTIVE = 1<<0,
+ NL80211_MPATH_FLAG_RESOLVING = 1<<1,
+ NL80211_MPATH_FLAG_SN_VALID = 1<<2,
+ NL80211_MPATH_FLAG_FIXED = 1<<3,
+ NL80211_MPATH_FLAG_RESOLVED = 1<<4,
+};
+
+/**
+ * enum nl80211_mpath_info - mesh path information
+ *
+ * These attribute types are used with %NL80211_ATTR_MPATH_INFO when getting
+ * information about a mesh path.
+ *
+ * @__NL80211_MPATH_INFO_INVALID: attribute number 0 is reserved
+ * @NL80211_MPATH_INFO_FRAME_QLEN: number of queued frames for this destination
+ * @NL80211_MPATH_INFO_SN: destination sequence number
+ * @NL80211_MPATH_INFO_METRIC: metric (cost) of this mesh path
+ * @NL80211_MPATH_INFO_EXPTIME: expiration time for the path, in msec from now
+ * @NL80211_MPATH_INFO_FLAGS: mesh path flags, enumerated in
+ * &enum nl80211_mpath_flags;
+ * @NL80211_MPATH_INFO_DISCOVERY_TIMEOUT: total path discovery timeout, in msec
+ * @NL80211_MPATH_INFO_DISCOVERY_RETRIES: mesh path discovery retries
+ * @NL80211_MPATH_INFO_MAX: highest mesh path information attribute number
+ * currently defind
+ * @__NL80211_MPATH_INFO_AFTER_LAST: internal use
+ */
+enum nl80211_mpath_info {
+ __NL80211_MPATH_INFO_INVALID,
+ NL80211_MPATH_INFO_FRAME_QLEN,
+ NL80211_MPATH_INFO_SN,
+ NL80211_MPATH_INFO_METRIC,
+ NL80211_MPATH_INFO_EXPTIME,
+ NL80211_MPATH_INFO_FLAGS,
+ NL80211_MPATH_INFO_DISCOVERY_TIMEOUT,
+ NL80211_MPATH_INFO_DISCOVERY_RETRIES,
+
+ /* keep last */
+ __NL80211_MPATH_INFO_AFTER_LAST,
+ NL80211_MPATH_INFO_MAX = __NL80211_MPATH_INFO_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_band_attr - band attributes
+ * @__NL80211_BAND_ATTR_INVALID: attribute number 0 is reserved
+ * @NL80211_BAND_ATTR_FREQS: supported frequencies in this band,
+ * an array of nested frequency attributes
+ * @NL80211_BAND_ATTR_RATES: supported bitrates in this band,
+ * an array of nested bitrate attributes
+ * @NL80211_BAND_ATTR_HT_MCS_SET: 16-byte attribute containing the MCS set as
+ * defined in 802.11n
+ * @NL80211_BAND_ATTR_HT_CAPA: HT capabilities, as in the HT information IE
+ * @NL80211_BAND_ATTR_HT_AMPDU_FACTOR: A-MPDU factor, as in 11n
+ * @NL80211_BAND_ATTR_HT_AMPDU_DENSITY: A-MPDU density, as in 11n
+ * @NL80211_BAND_ATTR_MAX: highest band attribute currently defined
+ * @__NL80211_BAND_ATTR_AFTER_LAST: internal use
+ */
+enum nl80211_band_attr {
+ __NL80211_BAND_ATTR_INVALID,
+ NL80211_BAND_ATTR_FREQS,
+ NL80211_BAND_ATTR_RATES,
+
+ NL80211_BAND_ATTR_HT_MCS_SET,
+ NL80211_BAND_ATTR_HT_CAPA,
+ NL80211_BAND_ATTR_HT_AMPDU_FACTOR,
+ NL80211_BAND_ATTR_HT_AMPDU_DENSITY,
+
+ /* keep last */
+ __NL80211_BAND_ATTR_AFTER_LAST,
+ NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1
+};
+
+#define NL80211_BAND_ATTR_HT_CAPA NL80211_BAND_ATTR_HT_CAPA
+
+/**
+ * enum nl80211_frequency_attr - frequency attributes
+ * @__NL80211_FREQUENCY_ATTR_INVALID: attribute number 0 is reserved
+ * @NL80211_FREQUENCY_ATTR_FREQ: Frequency in MHz
+ * @NL80211_FREQUENCY_ATTR_DISABLED: Channel is disabled in current
+ * regulatory domain.
+ * @NL80211_FREQUENCY_ATTR_PASSIVE_SCAN: Only passive scanning is
+ * permitted on this channel in current regulatory domain.
+ * @NL80211_FREQUENCY_ATTR_NO_IBSS: IBSS networks are not permitted
+ * on this channel in current regulatory domain.
+ * @NL80211_FREQUENCY_ATTR_RADAR: Radar detection is mandatory
+ * on this channel in current regulatory domain.
+ * @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm
+ * (100 * dBm).
+ * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number
+ * currently defined
+ * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use
+ */
+enum nl80211_frequency_attr {
+ __NL80211_FREQUENCY_ATTR_INVALID,
+ NL80211_FREQUENCY_ATTR_FREQ,
+ NL80211_FREQUENCY_ATTR_DISABLED,
+ NL80211_FREQUENCY_ATTR_PASSIVE_SCAN,
+ NL80211_FREQUENCY_ATTR_NO_IBSS,
+ NL80211_FREQUENCY_ATTR_RADAR,
+ NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
+
+ /* keep last */
+ __NL80211_FREQUENCY_ATTR_AFTER_LAST,
+ NL80211_FREQUENCY_ATTR_MAX = __NL80211_FREQUENCY_ATTR_AFTER_LAST - 1
+};
+
+#define NL80211_FREQUENCY_ATTR_MAX_TX_POWER NL80211_FREQUENCY_ATTR_MAX_TX_POWER
+
+/**
+ * enum nl80211_bitrate_attr - bitrate attributes
+ * @__NL80211_BITRATE_ATTR_INVALID: attribute number 0 is reserved
+ * @NL80211_BITRATE_ATTR_RATE: Bitrate in units of 100 kbps
+ * @NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE: Short preamble supported
+ * in 2.4 GHz band.
+ * @NL80211_BITRATE_ATTR_MAX: highest bitrate attribute number
+ * currently defined
+ * @__NL80211_BITRATE_ATTR_AFTER_LAST: internal use
+ */
+enum nl80211_bitrate_attr {
+ __NL80211_BITRATE_ATTR_INVALID,
+ NL80211_BITRATE_ATTR_RATE,
+ NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE,
+
+ /* keep last */
+ __NL80211_BITRATE_ATTR_AFTER_LAST,
+ NL80211_BITRATE_ATTR_MAX = __NL80211_BITRATE_ATTR_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_initiator - Indicates the initiator of a reg domain request
+ * @NL80211_REGDOM_SET_BY_CORE: Core queried CRDA for a dynamic world
+ * regulatory domain.
+ * @NL80211_REGDOM_SET_BY_USER: User asked the wireless core to set the
+ * regulatory domain.
+ * @NL80211_REGDOM_SET_BY_DRIVER: a wireless drivers has hinted to the
+ * wireless core it thinks its knows the regulatory domain we should be in.
+ * @NL80211_REGDOM_SET_BY_COUNTRY_IE: the wireless core has received an
+ * 802.11 country information element with regulatory information it
+ * thinks we should consider. cfg80211 only processes the country
+ * code from the IE, and relies on the regulatory domain information
+ * structure passed by userspace (CRDA) from our wireless-regdb.
+ * If a channel is enabled but the country code indicates it should
+ * be disabled we disable the channel and re-enable it upon disassociation.
+ */
+enum nl80211_reg_initiator {
+ NL80211_REGDOM_SET_BY_CORE,
+ NL80211_REGDOM_SET_BY_USER,
+ NL80211_REGDOM_SET_BY_DRIVER,
+ NL80211_REGDOM_SET_BY_COUNTRY_IE,
+};
+
+/**
+ * enum nl80211_reg_type - specifies the type of regulatory domain
+ * @NL80211_REGDOM_TYPE_COUNTRY: the regulatory domain set is one that pertains
+ * to a specific country. When this is set you can count on the
+ * ISO / IEC 3166 alpha2 country code being valid.
+ * @NL80211_REGDOM_TYPE_WORLD: the regulatory set domain is the world regulatory
+ * domain.
+ * @NL80211_REGDOM_TYPE_CUSTOM_WORLD: the regulatory domain set is a custom
+ * driver specific world regulatory domain. These do not apply system-wide
+ * and are only applicable to the individual devices which have requested
+ * them to be applied.
+ * @NL80211_REGDOM_TYPE_INTERSECTION: the regulatory domain set is the product
+ * of an intersection between two regulatory domains -- the previously
+ * set regulatory domain on the system and the last accepted regulatory
+ * domain request to be processed.
+ */
+enum nl80211_reg_type {
+ NL80211_REGDOM_TYPE_COUNTRY,
+ NL80211_REGDOM_TYPE_WORLD,
+ NL80211_REGDOM_TYPE_CUSTOM_WORLD,
+ NL80211_REGDOM_TYPE_INTERSECTION,
+};
+
+/**
+ * enum nl80211_reg_rule_attr - regulatory rule attributes
+ * @__NL80211_REG_RULE_ATTR_INVALID: attribute number 0 is reserved
+ * @NL80211_ATTR_REG_RULE_FLAGS: a set of flags which specify additional
+ * considerations for a given frequency range. These are the
+ * &enum nl80211_reg_rule_flags.
+ * @NL80211_ATTR_FREQ_RANGE_START: starting frequencry for the regulatory
+ * rule in KHz. This is not a center of frequency but an actual regulatory
+ * band edge.
+ * @NL80211_ATTR_FREQ_RANGE_END: ending frequency for the regulatory rule
+ * in KHz. This is not a center a frequency but an actual regulatory
+ * band edge.
+ * @NL80211_ATTR_FREQ_RANGE_MAX_BW: maximum allowed bandwidth for this
+ * frequency range, in KHz.
+ * @NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN: the maximum allowed antenna gain
+ * for a given frequency range. The value is in mBi (100 * dBi).
+ * If you don't have one then don't send this.
+ * @NL80211_ATTR_POWER_RULE_MAX_EIRP: the maximum allowed EIRP for
+ * a given frequency range. The value is in mBm (100 * dBm).
+ * @NL80211_REG_RULE_ATTR_MAX: highest regulatory rule attribute number
+ * currently defined
+ * @__NL80211_REG_RULE_ATTR_AFTER_LAST: internal use
+ */
+enum nl80211_reg_rule_attr {
+ __NL80211_REG_RULE_ATTR_INVALID,
+ NL80211_ATTR_REG_RULE_FLAGS,
+
+ NL80211_ATTR_FREQ_RANGE_START,
+ NL80211_ATTR_FREQ_RANGE_END,
+ NL80211_ATTR_FREQ_RANGE_MAX_BW,
+
+ NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
+ NL80211_ATTR_POWER_RULE_MAX_EIRP,
+
+ /* keep last */
+ __NL80211_REG_RULE_ATTR_AFTER_LAST,
+ NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_reg_rule_flags - regulatory rule flags
+ *
+ * @NL80211_RRF_NO_OFDM: OFDM modulation not allowed
+ * @NL80211_RRF_NO_CCK: CCK modulation not allowed
+ * @NL80211_RRF_NO_INDOOR: indoor operation not allowed
+ * @NL80211_RRF_NO_OUTDOOR: outdoor operation not allowed
+ * @NL80211_RRF_DFS: DFS support is required to be used
+ * @NL80211_RRF_PTP_ONLY: this is only for Point To Point links
+ * @NL80211_RRF_PTMP_ONLY: this is only for Point To Multi Point links
+ * @NL80211_RRF_PASSIVE_SCAN: passive scan is required
+ * @NL80211_RRF_NO_IBSS: no IBSS is allowed
+ */
+enum nl80211_reg_rule_flags {
+ NL80211_RRF_NO_OFDM = 1<<0,
+ NL80211_RRF_NO_CCK = 1<<1,
+ NL80211_RRF_NO_INDOOR = 1<<2,
+ NL80211_RRF_NO_OUTDOOR = 1<<3,
+ NL80211_RRF_DFS = 1<<4,
+ NL80211_RRF_PTP_ONLY = 1<<5,
+ NL80211_RRF_PTMP_ONLY = 1<<6,
+ NL80211_RRF_PASSIVE_SCAN = 1<<7,
+ NL80211_RRF_NO_IBSS = 1<<8,
+};
+
+/**
+ * enum nl80211_survey_info - survey information
+ *
+ * These attribute types are used with %NL80211_ATTR_SURVEY_INFO
+ * when getting information about a survey.
+ *
+ * @__NL80211_SURVEY_INFO_INVALID: attribute number 0 is reserved
+ * @NL80211_SURVEY_INFO_FREQUENCY: center frequency of channel
+ * @NL80211_SURVEY_INFO_NOISE: noise level of channel (u8, dBm)
+ * @NL80211_SURVEY_INFO_IN_USE: channel is currently being used
+ * @NL80211_SURVEY_INFO_CHANNEL_TIME: amount of time (in ms) that the radio
+ * spent on this channel
+ * @NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY: amount of the time the primary
+ * channel was sensed busy (either due to activity or energy detect)
+ * @NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY: amount of time the extension
+ * channel was sensed busy
+ * @NL80211_SURVEY_INFO_CHANNEL_TIME_RX: amount of time the radio spent
+ * receiving data
+ * @NL80211_SURVEY_INFO_CHANNEL_TIME_TX: amount of time the radio spent
+ * transmitting data
+ * @NL80211_SURVEY_INFO_MAX: highest survey info attribute number
+ * currently defined
+ * @__NL80211_SURVEY_INFO_AFTER_LAST: internal use
+ */
+enum nl80211_survey_info {
+ __NL80211_SURVEY_INFO_INVALID,
+ NL80211_SURVEY_INFO_FREQUENCY,
+ NL80211_SURVEY_INFO_NOISE,
+ NL80211_SURVEY_INFO_IN_USE,
+ NL80211_SURVEY_INFO_CHANNEL_TIME,
+ NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
+ NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY,
+ NL80211_SURVEY_INFO_CHANNEL_TIME_RX,
+ NL80211_SURVEY_INFO_CHANNEL_TIME_TX,
+
+ /* keep last */
+ __NL80211_SURVEY_INFO_AFTER_LAST,
+ NL80211_SURVEY_INFO_MAX = __NL80211_SURVEY_INFO_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_mntr_flags - monitor configuration flags
+ *
+ * Monitor configuration flags.
+ *
+ * @__NL80211_MNTR_FLAG_INVALID: reserved
+ *
+ * @NL80211_MNTR_FLAG_FCSFAIL: pass frames with bad FCS
+ * @NL80211_MNTR_FLAG_PLCPFAIL: pass frames with bad PLCP
+ * @NL80211_MNTR_FLAG_CONTROL: pass control frames
+ * @NL80211_MNTR_FLAG_OTHER_BSS: disable BSSID filtering
+ * @NL80211_MNTR_FLAG_COOK_FRAMES: report frames after processing.
+ * overrides all other flags.
+ *
+ * @__NL80211_MNTR_FLAG_AFTER_LAST: internal use
+ * @NL80211_MNTR_FLAG_MAX: highest possible monitor flag
+ */
+enum nl80211_mntr_flags {
+ __NL80211_MNTR_FLAG_INVALID,
+ NL80211_MNTR_FLAG_FCSFAIL,
+ NL80211_MNTR_FLAG_PLCPFAIL,
+ NL80211_MNTR_FLAG_CONTROL,
+ NL80211_MNTR_FLAG_OTHER_BSS,
+ NL80211_MNTR_FLAG_COOK_FRAMES,
+
+ /* keep last */
+ __NL80211_MNTR_FLAG_AFTER_LAST,
+ NL80211_MNTR_FLAG_MAX = __NL80211_MNTR_FLAG_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_meshconf_params - mesh configuration parameters
+ *
+ * Mesh configuration parameters
+ *
+ * @__NL80211_MESHCONF_INVALID: internal use
+ *
+ * @NL80211_MESHCONF_RETRY_TIMEOUT: specifies the initial retry timeout in
+ * millisecond units, used by the Peer Link Open message
+ *
+ * @NL80211_MESHCONF_CONFIRM_TIMEOUT: specifies the initial confirm timeout, in
+ * millisecond units, used by the peer link management to close a peer link
+ *
+ * @NL80211_MESHCONF_HOLDING_TIMEOUT: specifies the holding timeout, in
+ * millisecond units
+ *
+ * @NL80211_MESHCONF_MAX_PEER_LINKS: maximum number of peer links allowed
+ * on this mesh interface
+ *
+ * @NL80211_MESHCONF_MAX_RETRIES: specifies the maximum number of peer link
+ * open retries that can be sent to establish a new peer link instance in a
+ * mesh
+ *
+ * @NL80211_MESHCONF_TTL: specifies the value of TTL field set at a source mesh
+ * point.
+ *
+ * @NL80211_MESHCONF_ELEMENT_TTL: specifies the value of TTL field set at a
+ * source mesh point for path selection elements.
+ *
+ * @NL80211_MESHCONF_AUTO_OPEN_PLINKS: whether we should automatically
+ * open peer links when we detect compatible mesh peers.
+ *
+ * @NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES: the number of action frames
+ * containing a PREQ that an MP can send to a particular destination (path
+ * target)
+ *
+ * @NL80211_MESHCONF_PATH_REFRESH_TIME: how frequently to refresh mesh paths
+ * (in milliseconds)
+ *
+ * @NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT: minimum length of time to wait
+ * until giving up on a path discovery (in milliseconds)
+ *
+ * @NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT: The time (in TUs) for which mesh
+ * points receiving a PREQ shall consider the forwarding information from the
+ * root to be valid. (TU = time unit)
+ *
+ * @NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL: The minimum interval of time (in
+ * TUs) during which an MP can send only one action frame containing a PREQ
+ * reference element
+ *
+ * @NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME: The interval of time (in TUs)
+ * that it takes for an HWMP information element to propagate across the mesh
+ *
+ * @NL80211_MESHCONF_ROOTMODE: whether root mode is enabled or not
+ *
+ * @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute
+ *
+ * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use
+ */
+enum nl80211_meshconf_params {
+ __NL80211_MESHCONF_INVALID,
+ NL80211_MESHCONF_RETRY_TIMEOUT,
+ NL80211_MESHCONF_CONFIRM_TIMEOUT,
+ NL80211_MESHCONF_HOLDING_TIMEOUT,
+ NL80211_MESHCONF_MAX_PEER_LINKS,
+ NL80211_MESHCONF_MAX_RETRIES,
+ NL80211_MESHCONF_TTL,
+ NL80211_MESHCONF_AUTO_OPEN_PLINKS,
+ NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
+ NL80211_MESHCONF_PATH_REFRESH_TIME,
+ NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
+ NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
+ NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
+ NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
+ NL80211_MESHCONF_HWMP_ROOTMODE,
+ NL80211_MESHCONF_ELEMENT_TTL,
+
+ /* keep last */
+ __NL80211_MESHCONF_ATTR_AFTER_LAST,
+ NL80211_MESHCONF_ATTR_MAX = __NL80211_MESHCONF_ATTR_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_txq_attr - TX queue parameter attributes
+ * @__NL80211_TXQ_ATTR_INVALID: Attribute number 0 is reserved
+ * @NL80211_TXQ_ATTR_QUEUE: TX queue identifier (NL80211_TXQ_Q_*)
+ * @NL80211_TXQ_ATTR_TXOP: Maximum burst time in units of 32 usecs, 0 meaning
+ * disabled
+ * @NL80211_TXQ_ATTR_CWMIN: Minimum contention window [a value of the form
+ * 2^n-1 in the range 1..32767]
+ * @NL80211_TXQ_ATTR_CWMAX: Maximum contention window [a value of the form
+ * 2^n-1 in the range 1..32767]
+ * @NL80211_TXQ_ATTR_AIFS: Arbitration interframe space [0..255]
+ * @__NL80211_TXQ_ATTR_AFTER_LAST: Internal
+ * @NL80211_TXQ_ATTR_MAX: Maximum TXQ attribute number
+ */
+enum nl80211_txq_attr {
+ __NL80211_TXQ_ATTR_INVALID,
+ NL80211_TXQ_ATTR_QUEUE,
+ NL80211_TXQ_ATTR_TXOP,
+ NL80211_TXQ_ATTR_CWMIN,
+ NL80211_TXQ_ATTR_CWMAX,
+ NL80211_TXQ_ATTR_AIFS,
+
+ /* keep last */
+ __NL80211_TXQ_ATTR_AFTER_LAST,
+ NL80211_TXQ_ATTR_MAX = __NL80211_TXQ_ATTR_AFTER_LAST - 1
+};
+
+enum nl80211_txq_q {
+ NL80211_TXQ_Q_VO,
+ NL80211_TXQ_Q_VI,
+ NL80211_TXQ_Q_BE,
+ NL80211_TXQ_Q_BK
+};
+
+enum nl80211_channel_type {
+ NL80211_CHAN_NO_HT,
+ NL80211_CHAN_HT20,
+ NL80211_CHAN_HT40MINUS,
+ NL80211_CHAN_HT40PLUS
+};
+
+/**
+ * enum nl80211_bss - netlink attributes for a BSS
+ *
+ * @__NL80211_BSS_INVALID: invalid
+ * @NL80211_BSS_BSSID: BSSID of the BSS (6 octets)
+ * @NL80211_BSS_FREQUENCY: frequency in MHz (u32)
+ * @NL80211_BSS_TSF: TSF of the received probe response/beacon (u64)
+ * @NL80211_BSS_BEACON_INTERVAL: beacon interval of the (I)BSS (u16)
+ * @NL80211_BSS_CAPABILITY: capability field (CPU order, u16)
+ * @NL80211_BSS_INFORMATION_ELEMENTS: binary attribute containing the
+ * raw information elements from the probe response/beacon (bin);
+ * if the %NL80211_BSS_BEACON_IES attribute is present, the IEs here are
+ * from a Probe Response frame; otherwise they are from a Beacon frame.
+ * However, if the driver does not indicate the source of the IEs, these
+ * IEs may be from either frame subtype.
+ * @NL80211_BSS_SIGNAL_MBM: signal strength of probe response/beacon
+ * in mBm (100 * dBm) (s32)
+ * @NL80211_BSS_SIGNAL_UNSPEC: signal strength of the probe response/beacon
+ * in unspecified units, scaled to 0..100 (u8)
+ * @NL80211_BSS_STATUS: status, if this BSS is "used"
+ * @NL80211_BSS_SEEN_MS_AGO: age of this BSS entry in ms
+ * @NL80211_BSS_BEACON_IES: binary attribute containing the raw information
+ * elements from a Beacon frame (bin); not present if no Beacon frame has
+ * yet been received
+ * @__NL80211_BSS_AFTER_LAST: internal
+ * @NL80211_BSS_MAX: highest BSS attribute
+ */
+enum nl80211_bss {
+ __NL80211_BSS_INVALID,
+ NL80211_BSS_BSSID,
+ NL80211_BSS_FREQUENCY,
+ NL80211_BSS_TSF,
+ NL80211_BSS_BEACON_INTERVAL,
+ NL80211_BSS_CAPABILITY,
+ NL80211_BSS_INFORMATION_ELEMENTS,
+ NL80211_BSS_SIGNAL_MBM,
+ NL80211_BSS_SIGNAL_UNSPEC,
+ NL80211_BSS_STATUS,
+ NL80211_BSS_SEEN_MS_AGO,
+ NL80211_BSS_BEACON_IES,
+
+ /* keep last */
+ __NL80211_BSS_AFTER_LAST,
+ NL80211_BSS_MAX = __NL80211_BSS_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_bss_status - BSS "status"
+ * @NL80211_BSS_STATUS_AUTHENTICATED: Authenticated with this BSS.
+ * @NL80211_BSS_STATUS_ASSOCIATED: Associated with this BSS.
+ * @NL80211_BSS_STATUS_IBSS_JOINED: Joined to this IBSS.
+ *
+ * The BSS status is a BSS attribute in scan dumps, which
+ * indicates the status the interface has wrt. this BSS.
+ */
+enum nl80211_bss_status {
+ NL80211_BSS_STATUS_AUTHENTICATED,
+ NL80211_BSS_STATUS_ASSOCIATED,
+ NL80211_BSS_STATUS_IBSS_JOINED,
+};
+
+/**
+ * enum nl80211_auth_type - AuthenticationType
+ *
+ * @NL80211_AUTHTYPE_OPEN_SYSTEM: Open System authentication
+ * @NL80211_AUTHTYPE_SHARED_KEY: Shared Key authentication (WEP only)
+ * @NL80211_AUTHTYPE_FT: Fast BSS Transition (IEEE 802.11r)
+ * @NL80211_AUTHTYPE_NETWORK_EAP: Network EAP (some Cisco APs and mainly LEAP)
+ * @__NL80211_AUTHTYPE_NUM: internal
+ * @NL80211_AUTHTYPE_MAX: maximum valid auth algorithm
+ * @NL80211_AUTHTYPE_AUTOMATIC: determine automatically (if necessary by
+ * trying multiple times); this is invalid in netlink -- leave out
+ * the attribute for this on CONNECT commands.
+ */
+enum nl80211_auth_type {
+ NL80211_AUTHTYPE_OPEN_SYSTEM,
+ NL80211_AUTHTYPE_SHARED_KEY,
+ NL80211_AUTHTYPE_FT,
+ NL80211_AUTHTYPE_NETWORK_EAP,
+
+ /* keep last */
+ __NL80211_AUTHTYPE_NUM,
+ NL80211_AUTHTYPE_MAX = __NL80211_AUTHTYPE_NUM - 1,
+ NL80211_AUTHTYPE_AUTOMATIC
+};
+
+/**
+ * enum nl80211_key_type - Key Type
+ * @NL80211_KEYTYPE_GROUP: Group (broadcast/multicast) key
+ * @NL80211_KEYTYPE_PAIRWISE: Pairwise (unicast/individual) key
+ * @NL80211_KEYTYPE_PEERKEY: PeerKey (DLS)
+ * @NUM_NL80211_KEYTYPES: number of defined key types
+ */
+enum nl80211_key_type {
+ NL80211_KEYTYPE_GROUP,
+ NL80211_KEYTYPE_PAIRWISE,
+ NL80211_KEYTYPE_PEERKEY,
+
+ NUM_NL80211_KEYTYPES
+};
+
+/**
+ * enum nl80211_mfp - Management frame protection state
+ * @NL80211_MFP_NO: Management frame protection not used
+ * @NL80211_MFP_REQUIRED: Management frame protection required
+ */
+enum nl80211_mfp {
+ NL80211_MFP_NO,
+ NL80211_MFP_REQUIRED,
+};
+
+enum nl80211_wpa_versions {
+ NL80211_WPA_VERSION_1 = 1 << 0,
+ NL80211_WPA_VERSION_2 = 1 << 1,
+};
+
+/**
+ * enum nl80211_key_attributes - key attributes
+ * @__NL80211_KEY_INVALID: invalid
+ * @NL80211_KEY_DATA: (temporal) key data; for TKIP this consists of
+ * 16 bytes encryption key followed by 8 bytes each for TX and RX MIC
+ * keys
+ * @NL80211_KEY_IDX: key ID (u8, 0-3)
+ * @NL80211_KEY_CIPHER: key cipher suite (u32, as defined by IEEE 802.11
+ * section 7.3.2.25.1, e.g. 0x000FAC04)
+ * @NL80211_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and
+ * CCMP keys, each six bytes in little endian
+ * @NL80211_KEY_DEFAULT: flag indicating default key
+ * @NL80211_KEY_DEFAULT_MGMT: flag indicating default management key
+ * @NL80211_KEY_TYPE: the key type from enum nl80211_key_type, if not
+ * specified the default depends on whether a MAC address was
+ * given with the command using the key or not (u32)
+ * @__NL80211_KEY_AFTER_LAST: internal
+ * @NL80211_KEY_MAX: highest key attribute
+ */
+enum nl80211_key_attributes {
+ __NL80211_KEY_INVALID,
+ NL80211_KEY_DATA,
+ NL80211_KEY_IDX,
+ NL80211_KEY_CIPHER,
+ NL80211_KEY_SEQ,
+ NL80211_KEY_DEFAULT,
+ NL80211_KEY_DEFAULT_MGMT,
+ NL80211_KEY_TYPE,
+
+ /* keep last */
+ __NL80211_KEY_AFTER_LAST,
+ NL80211_KEY_MAX = __NL80211_KEY_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_tx_rate_attributes - TX rate set attributes
+ * @__NL80211_TXRATE_INVALID: invalid
+ * @NL80211_TXRATE_LEGACY: Legacy (non-MCS) rates allowed for TX rate selection
+ * in an array of rates as defined in IEEE 802.11 7.3.2.2 (u8 values with
+ * 1 = 500 kbps) but without the IE length restriction (at most
+ * %NL80211_MAX_SUPP_RATES in a single array).
+ * @__NL80211_TXRATE_AFTER_LAST: internal
+ * @NL80211_TXRATE_MAX: highest TX rate attribute
+ */
+enum nl80211_tx_rate_attributes {
+ __NL80211_TXRATE_INVALID,
+ NL80211_TXRATE_LEGACY,
+
+ /* keep last */
+ __NL80211_TXRATE_AFTER_LAST,
+ NL80211_TXRATE_MAX = __NL80211_TXRATE_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_band - Frequency band
+ * @NL80211_BAND_2GHZ: 2.4 GHz ISM band
+ * @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz)
+ */
+enum nl80211_band {
+ NL80211_BAND_2GHZ,
+ NL80211_BAND_5GHZ,
+};
+
+enum nl80211_ps_state {
+ NL80211_PS_DISABLED,
+ NL80211_PS_ENABLED,
+};
+
+/**
+ * enum nl80211_attr_cqm - connection quality monitor attributes
+ * @__NL80211_ATTR_CQM_INVALID: invalid
+ * @NL80211_ATTR_CQM_RSSI_THOLD: RSSI threshold in dBm. This value specifies
+ * the threshold for the RSSI level at which an event will be sent. Zero
+ * to disable.
+ * @NL80211_ATTR_CQM_RSSI_HYST: RSSI hysteresis in dBm. This value specifies
+ * the minimum amount the RSSI level must change after an event before a
+ * new event may be issued (to reduce effects of RSSI oscillation).
+ * @NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT: RSSI threshold event
+ * @NL80211_ATTR_CQM_PKT_LOSS_EVENT: a u32 value indicating that this many
+ * consecutive packets were not acknowledged by the peer
+ * @__NL80211_ATTR_CQM_AFTER_LAST: internal
+ * @NL80211_ATTR_CQM_MAX: highest key attribute
+ */
+enum nl80211_attr_cqm {
+ __NL80211_ATTR_CQM_INVALID,
+ NL80211_ATTR_CQM_RSSI_THOLD,
+ NL80211_ATTR_CQM_RSSI_HYST,
+ NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT,
+ NL80211_ATTR_CQM_PKT_LOSS_EVENT,
+
+ /* keep last */
+ __NL80211_ATTR_CQM_AFTER_LAST,
+ NL80211_ATTR_CQM_MAX = __NL80211_ATTR_CQM_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_cqm_rssi_threshold_event - RSSI threshold event
+ * @NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW: The RSSI level is lower than the
+ * configured threshold
+ * @NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH: The RSSI is higher than the
+ * configured threshold
+ */
+enum nl80211_cqm_rssi_threshold_event {
+ NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
+ NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
+};
+
+
+/**
+ * enum nl80211_tx_power_setting - TX power adjustment
+ * @NL80211_TX_POWER_AUTOMATIC: automatically determine transmit power
+ * @NL80211_TX_POWER_LIMITED: limit TX power by the mBm parameter
+ * @NL80211_TX_POWER_FIXED: fix TX power to the mBm parameter
+ */
+enum nl80211_tx_power_setting {
+ NL80211_TX_POWER_AUTOMATIC,
+ NL80211_TX_POWER_LIMITED,
+ NL80211_TX_POWER_FIXED,
+};
+
+#endif /* __LINUX_NL80211_H */
diff --git a/src/tuning/runtime.cpp b/src/tuning/runtime.cpp
new file mode 100644
index 0000000..cb62533
--- /dev/null
+++ b/src/tuning/runtime.cpp
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+
+#include "tuning.h"
+#include "tunable.h"
+#include "unistd.h"
+#include "runtime.h"
+#include <string.h>
+#include <utility>
+#include <iostream>
+#include <fstream>
+#include <unistd.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <limits.h>
+
+#include "../lib.h"
+#include "../devices/runtime_pm.h"
+
+runtime_tunable::runtime_tunable(const char *path, const char *bus, const char *dev, const char *port) : tunable("", 0.4, _("Good"), _("Bad"), _("Unknown"))
+{
+ ifstream file;
+ sprintf(runtime_path, "%s/power/control", path);
+
+
+ sprintf(desc, _("Runtime PM for %s device %s"), bus, dev);
+ if (!device_has_runtime_pm(path))
+ sprintf(desc, _("%s device %s has no runtime power management"), bus, dev);
+
+ if (strcmp(bus, "pci") == 0) {
+ char filename[PATH_MAX];
+ uint16_t vendor = 0, device = 0;
+
+ snprintf(filename, sizeof(filename), "/sys/bus/%s/devices/%s/vendor", bus, dev);
+
+ file.open(filename, ios::in);
+ if (file) {
+ file >> hex >> vendor;
+ file.close();
+ }
+
+
+ snprintf(filename, sizeof(filename), "/sys/bus/%s/devices/%s/device", bus, dev);
+ file.open(filename, ios::in);
+ if (file) {
+ file >> hex >> device;
+ file.close();
+ }
+
+ if (vendor && device) {
+ if (!device_has_runtime_pm(path))
+ sprintf(desc, _("PCI Device %s has no runtime power management"), pci_id_to_name(vendor, device, filename, 4095));
+ else
+ sprintf(desc, _("Runtime PM for PCI Device %s"), pci_id_to_name(vendor, device, filename, 4095));
+ }
+
+ if (string(path).find("ata") != string::npos)
+ sprintf(desc, _("Runtime PM for port %s of PCI device: %s"), port, pci_id_to_name(vendor, device, filename, 4095));
+
+ if (string(path).find("block") != string::npos)
+ sprintf(desc, _("Runtime PM for disk %s"), port);
+
+ }
+ snprintf(toggle_good, sizeof(toggle_good), "echo 'auto' > '%s';", runtime_path);
+ snprintf(toggle_bad, sizeof(toggle_bad), "echo 'on' > '%s';", runtime_path);
+}
+
+int runtime_tunable::good_bad(void)
+{
+ string content;
+
+ content = read_sysfs_string(runtime_path);
+
+ if (strcmp(content.c_str(), "auto") == 0)
+ return TUNE_GOOD;
+
+ return TUNE_BAD;
+}
+
+void runtime_tunable::toggle(void)
+{
+ int good;
+ good = good_bad();
+
+ if (good == TUNE_GOOD) {
+ write_sysfs(runtime_path, "on");
+ return;
+ }
+
+ write_sysfs(runtime_path, "auto");
+}
+
+const char *runtime_tunable::toggle_script(void)
+{
+ int good;
+ good = good_bad();
+
+ if (good == TUNE_GOOD) {
+ return toggle_bad;
+ }
+
+ return toggle_good;
+}
+
+
+void add_runtime_tunables(const char *bus)
+{
+ struct dirent *entry;
+ DIR *dir;
+ char filename[PATH_MAX], port[PATH_MAX];
+ int max_ports = 32, count=0;
+
+ snprintf(filename, sizeof(filename), "/sys/bus/%s/devices/", bus);
+ dir = opendir(filename);
+ if (!dir)
+ return;
+ while (1) {
+ class runtime_tunable *runtime, *runtime_ahci_port, *runtime_ahci_disk;
+
+ entry = readdir(dir);
+
+ if (!entry)
+ break;
+ if (entry->d_name[0] == '.')
+ continue;
+
+ snprintf(filename, sizeof(filename), "/sys/bus/%s/devices/%s/power/control", bus, entry->d_name);
+
+ if (access(filename, R_OK) != 0)
+ continue;
+
+
+ snprintf(filename, sizeof(filename), "/sys/bus/%s/devices/%s", bus, entry->d_name);
+
+ runtime = new class runtime_tunable(filename, bus, entry->d_name, NULL);
+
+ if (!device_has_runtime_pm(filename))
+ all_untunables.push_back(runtime);
+ else
+ all_tunables.push_back(runtime);
+
+ for (int i=0; i < max_ports; i++) {
+ snprintf(port, sizeof(port), "ata%d", i);
+ snprintf(filename, sizeof(filename), "/sys/bus/%s/devices/%s/%s/power/control", bus, entry->d_name, port);
+
+ if (access(filename, R_OK) != 0)
+ continue;
+
+ snprintf(filename, sizeof(filename), "/sys/bus/%s/devices/%s/%s", bus, entry->d_name, port);
+ runtime_ahci_port = new class runtime_tunable(filename, bus, entry->d_name, port);
+
+ if (!device_has_runtime_pm(filename))
+ all_untunables.push_back(runtime_ahci_port);
+ else
+ all_tunables.push_back(runtime_ahci_port);
+ }
+
+ for (char blk = 'a'; blk <= 'z'; blk++)
+ {
+ if (count != 0)
+ break;
+
+ snprintf(filename, sizeof(filename), "/sys/block/sd%c/device/power/control", blk);
+
+ if (access(filename, R_OK) != 0)
+ continue;
+
+ snprintf(port, sizeof(port), "sd%c", blk);
+ snprintf(filename, sizeof(filename), "/sys/block/%s/device", port);
+ runtime_ahci_disk = new class runtime_tunable(filename, bus, entry->d_name, port);
+ if (!device_has_runtime_pm(filename))
+ all_untunables.push_back(runtime_ahci_disk);
+ else
+ all_tunables.push_back(runtime_ahci_disk);
+ }
+ count = 1;
+
+ }
+ closedir(dir);
+}
diff --git a/src/tuning/runtime.h b/src/tuning/runtime.h
new file mode 100644
index 0000000..84a8ef5
--- /dev/null
+++ b/src/tuning/runtime.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_RUNTIME_TUNE_H
+#define _INCLUDE_GUARD_RUNTIME_TUNE_H
+
+#include <vector>
+#include <limits.h>
+
+#include "tunable.h"
+using namespace std;
+
+class runtime_tunable : public tunable {
+ char runtime_path[PATH_MAX];
+public:
+ runtime_tunable(const char *runtime_path, const char *bus, const char *dev, const char *port);
+
+ virtual int good_bad(void);
+
+ virtual void toggle(void);
+
+ virtual const char *toggle_script(void);
+
+};
+
+extern void add_runtime_tunables(const char *bus);
+
+
+#endif
diff --git a/src/tuning/tunable.cpp b/src/tuning/tunable.cpp
new file mode 100644
index 0000000..827b913
--- /dev/null
+++ b/src/tuning/tunable.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+
+#include "tuning.h"
+#include "tunable.h"
+#include <string.h>
+#include "../lib.h"
+
+vector<class tunable *> all_tunables;
+vector<class tunable *> all_untunables;
+
+
+tunable::tunable(const char *str, double _score, const char *good, const char *bad, const char *neutral)
+{
+ score = _score;
+ pt_strcpy(desc, str);
+ pt_strcpy(good_string, good);
+ pt_strcpy(bad_string, bad);
+ pt_strcpy(neutral_string, neutral);
+}
+
+
+tunable::tunable(void)
+{
+ score = 0;
+ desc[0] = 0;
+ pt_strcpy(good_string, _("Good"));
+ pt_strcpy(bad_string, _("Bad"));
+ pt_strcpy(neutral_string, _("Unknown"));
+}
diff --git a/src/tuning/tunable.h b/src/tuning/tunable.h
new file mode 100644
index 0000000..3372378
--- /dev/null
+++ b/src/tuning/tunable.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_TUNABLE_H
+#define _INCLUDE_GUARD_TUNABLE_H
+
+#include <vector>
+
+#include "../lib.h"
+
+using namespace std;
+
+#define TUNE_GOOD 1
+#define TUNE_BAD -1
+#define TUNE_UNFIXABLE -2
+#define TUNE_UNKNOWN 0
+#define TUNE_NEUTRAL 0
+
+class tunable {
+
+ char good_string[128];
+ char bad_string[128];
+ char neutral_string[128];
+protected:
+ char toggle_good[4096];
+ char toggle_bad[4096];
+public:
+ char desc[4096];
+ double score;
+
+ tunable(void);
+ tunable(const char *str, double _score, const char *good = "", const char *bad = "", const char *neutral ="");
+ virtual ~tunable() {};
+
+ virtual int good_bad(void) { return TUNE_NEUTRAL; }
+
+ virtual char *result_string(void)
+ {
+ switch (good_bad()) {
+ case TUNE_GOOD:
+ return good_string;
+ case TUNE_BAD:
+ case TUNE_UNFIXABLE:
+ return bad_string;
+ }
+ return neutral_string;
+ }
+
+
+ virtual const char *description(void) { return desc; };
+
+ virtual void toggle(void) { };
+
+ virtual const char *toggle_script(void) { return NULL; }
+};
+
+extern vector<class tunable *> all_tunables;
+extern vector<class tunable *> all_untunables;
+
+#endif
diff --git a/src/tuning/tuning.cpp b/src/tuning/tuning.cpp
new file mode 100644
index 0000000..bc34741
--- /dev/null
+++ b/src/tuning/tuning.cpp
@@ -0,0 +1,332 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+
+#include <algorithm>
+
+#include <stdio.h>
+#include <string.h>
+#include <ncurses.h>
+
+
+#include "tuning.h"
+#include "tuningi2c.h"
+#include "tuningsysfs.h"
+#include "tuningusb.h"
+#include "runtime.h"
+#include "bluetooth.h"
+#include "ethernet.h"
+#include "wifi.h"
+#include "../display.h"
+#include "../report/report.h"
+#include "../report/report-maker.h"
+#include "../report/report-data-html.h"
+#include "../lib.h"
+
+static void sort_tunables(void);
+static bool should_clear = false;
+
+class tuning_window *tune_window;
+
+class tuning_window: public tab_window {
+public:
+ virtual void repaint(void);
+ virtual void cursor_enter(void);
+ virtual void expose(void);
+ virtual void window_refresh(void);
+};
+
+static void init_tuning(void)
+{
+ add_sysfs_tunable(_("Enable Audio codec power management"), "/sys/module/snd_hda_intel/parameters/power_save", "1");
+ add_sysfs_tunable(_("NMI watchdog should be turned off"), "/proc/sys/kernel/nmi_watchdog", "0");
+ add_sysfs_tunable(_("Power Aware CPU scheduler"), "/sys/devices/system/cpu/sched_mc_power_savings", "1");
+ add_sysfs_tunable(_("VM writeback timeout"), "/proc/sys/vm/dirty_writeback_centisecs", "1500");
+ add_sata_tunables();
+ add_usb_tunables();
+ add_runtime_tunables("pci");
+ add_bt_tunable();
+ add_wifi_tunables();
+ add_i2c_tunables();
+
+ sort_tunables();
+}
+
+void initialize_tuning(void)
+{
+ class tuning_window *w;
+
+ w = new tuning_window();
+ create_tab("Tunables", _("Tunables"), w, _(" <ESC> Exit | <Enter> Toggle tunable | <r> Window refresh"));
+
+ init_tuning();
+
+ w->cursor_max = all_tunables.size() - 1;
+
+ if (tune_window)
+ delete tune_window;
+
+ tune_window = w;
+}
+
+
+
+static void __tuning_update_display(int cursor_pos)
+{
+ WINDOW *win;
+ unsigned int i;
+
+ win = get_ncurses_win("Tunables");
+
+ if (!win)
+ return;
+
+ if (should_clear) {
+ should_clear = false;
+ wclear(win);
+ }
+
+ wmove(win, 2,0);
+
+ for (i = 0; i < all_tunables.size(); i++) {
+ char res[128];
+ char desc[4096];
+ pt_strcpy(res, all_tunables[i]->result_string());
+ pt_strcpy(desc, all_tunables[i]->description());
+ while (strlen(res) < 12)
+ strcat(res, " ");
+
+ while (strlen(desc) < 103)
+ strcat(desc, " ");
+ if ((int)i != cursor_pos) {
+ wattrset(win, A_NORMAL);
+ wprintw(win, " ");
+ } else {
+ wattrset(win, A_REVERSE);
+ wprintw(win, ">> ");
+ }
+ wprintw(win, "%s %s\n", _(res), _(desc));
+ }
+}
+
+void tuning_update_display(void)
+{
+ class tab_window *w;
+
+ w = tab_windows["Tunables"];
+ if (!w)
+ return;
+ w->repaint();
+}
+
+void tuning_window::repaint(void)
+{
+ __tuning_update_display(cursor_pos);
+}
+
+void tuning_window::cursor_enter(void)
+{
+ class tunable *tun;
+ const char *toggle_script;
+ tun = all_tunables[cursor_pos];
+ if (!tun)
+ return;
+ /** device will change its state so need to store toggle script before
+ * we toggle()*/
+ toggle_script = tun->toggle_script();
+ tun->toggle();
+ ui_notify_user(">> %s\n", toggle_script);
+}
+
+static bool tunables_sort(class tunable * i, class tunable * j)
+{
+ int i_g, j_g;
+ double d;
+
+ i_g = i->good_bad();
+ j_g = j->good_bad();
+
+ if (!equals(i_g, j_g))
+ return i_g < j_g;
+
+ d = i->score - j->score;
+ if (d < 0.0)
+ d = -d;
+ if (d > 0.0001)
+ return i->score > j->score;
+
+ if (strcasecmp(i->description(), j->description()) == -1)
+ return true;
+
+ return false;
+}
+
+void tuning_window::window_refresh()
+{
+ clear_tuning();
+ should_clear = true;
+ init_tuning();
+}
+
+static void sort_tunables(void)
+{
+ sort(all_tunables.begin(), all_tunables.end(), tunables_sort);
+}
+
+void tuning_window::expose(void)
+{
+ cursor_pos = 0;
+ sort_tunables();
+ repaint();
+}
+
+void report_show_tunables(void)
+{
+ unsigned int i;
+ /* three tables; bad, unfixable, good */
+ sort_tunables();
+ int idx, rows = 0, cols;
+
+ /* First Table */
+
+ /* div attr css_class and css_id */
+ tag_attr div_attr;
+ init_div(&div_attr, "clear_block", "tuning");
+
+ /* Set Title attributes */
+ tag_attr title_attr;
+ init_title_attr(&title_attr);
+
+ /* Set Table attributes, rows, and cols */
+ table_attributes tune_table_css;
+ cols=2;
+ idx = cols;
+
+ for (i = 0; i < all_tunables.size(); i++) {
+ int tgb;
+ tgb = all_tunables[i]->good_bad();
+ if (tgb == TUNE_BAD)
+ rows+=1;
+ }
+ /* add section */
+ report.add_div(&div_attr);
+
+ if (rows > 0){
+ rows= rows + 1;
+ init_tune_table_attr(&tune_table_css, rows, cols);
+
+ /* Set array of data in row Major order */
+ string *tunable_data = new string[cols * rows];
+
+ tunable_data[0]=__("Description");
+ tunable_data[1]=__("Script");
+
+ for (i = 0; i < all_tunables.size(); i++) {
+ int gb;
+ gb = all_tunables[i]->good_bad();
+ if (gb != TUNE_BAD)
+ continue;
+ tunable_data[idx]=string(all_tunables[i]->description());
+ idx+=1;
+ tunable_data[idx]=string(all_tunables[i]->toggle_script());
+ idx+=1;
+ }
+
+ /* Report Output */
+ report.add_title(&title_attr,__("Software Settings in Need of Tuning"));
+ report.add_table(tunable_data, &tune_table_css);
+ delete [] tunable_data;
+ }
+
+ /* Second Table */
+ /* Set Table attributes, rows, and cols */
+ cols=1;
+ rows= all_untunables.size() + 1;
+ init_tune_table_attr(&tune_table_css, rows, cols);
+
+ /* Set array of data in row Major order */
+ string *untunable_data = new string[rows];
+ untunable_data[0]=__("Description");
+
+ for (i = 0; i < all_untunables.size(); i++)
+ untunable_data[i+1]= string(all_untunables[i]->description());
+
+ /* Report Output */
+ report.add_title(&title_attr,__("Untunable Software Issues"));
+ report.add_table(untunable_data, &tune_table_css);
+ delete [] untunable_data;
+
+ /* Third Table */
+ /* Set Table attributes, rows, and cols */
+ rows = 1;
+ for (i = 0; i < all_tunables.size(); i++) {
+ int gb;
+ gb = all_tunables[i]->good_bad();
+ if (gb != TUNE_GOOD)
+ continue;
+ rows+=1;
+ }
+ cols = 1;
+ init_tune_table_attr(&tune_table_css, rows, cols);
+
+ /* Set array of data in row Major order */
+ string *tuned_data = new string[rows];
+ tuned_data[0]=__("Description");
+ idx=cols;
+ for (i = 0; i < all_tunables.size(); i++) {
+ int gb;
+ gb = all_tunables[i]->good_bad();
+ if (gb != TUNE_GOOD)
+ continue;
+
+ tuned_data[idx]=string(all_tunables[i]->description());
+ idx+=1;
+ }
+ /* Report Output */
+ report.add_title(&title_attr,__("Optimal Tuned Software Settings"));
+ report.add_table(tuned_data, &tune_table_css);
+ report.end_div();
+ delete [] tuned_data;
+}
+
+void clear_tuning()
+{
+ for (size_t i = 0; i < all_tunables.size(); i++) {
+ delete all_tunables[i];
+ }
+ all_tunables.clear();
+
+ for (size_t i = 0; i < all_untunables.size(); i++) {
+ delete all_untunables[i];
+ }
+ all_untunables.clear();
+}
+
+void auto_toggle_tuning()
+{
+ for (unsigned int i = 0; i < all_tunables.size(); i++) {
+ if (all_tunables[i]->good_bad() == TUNE_BAD)
+ all_tunables[i]->toggle();
+ }
+}
diff --git a/src/tuning/tuning.h b/src/tuning/tuning.h
new file mode 100644
index 0000000..f70001b
--- /dev/null
+++ b/src/tuning/tuning.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_TUNING_H
+#define _INCLUDE_GUARD_TUNING_H
+
+extern void initialize_tuning(void);
+extern void tuning_update_display(void);
+extern void report_show_tunables(void);
+extern void clear_tuning(void);
+extern void auto_toggle_tuning(void);
+#endif
diff --git a/src/tuning/tuningi2c.cpp b/src/tuning/tuningi2c.cpp
new file mode 100644
index 0000000..b75e811
--- /dev/null
+++ b/src/tuning/tuningi2c.cpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2015, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ * Daniel Leung <daniel.leung@linux.intel.com>
+ */
+
+#include "tuning.h"
+#include "tunable.h"
+#include "unistd.h"
+#include "tuningi2c.h"
+#include <string.h>
+#include <dirent.h>
+#include <utility>
+#include <iostream>
+#include <fstream>
+#include <ctype.h>
+#include <limits.h>
+
+#include "../lib.h"
+#include "../devices/runtime_pm.h"
+
+i2c_tunable::i2c_tunable(const char *path, const char *name, bool is_adapter) : tunable("", 0.9, _("Good"), _("Bad"), _("Unknown"))
+{
+ ifstream file;
+ char filename[PATH_MAX];
+ string devname;
+
+ snprintf(filename, sizeof(filename), "%s/name", path);
+ file.open(filename, ios::in);
+ if (file) {
+ getline(file, devname);
+ file.close();
+ }
+
+ if (is_adapter) {
+ snprintf(i2c_path, sizeof(i2c_path), "%s/device/power/control", path);
+ snprintf(filename, sizeof(filename), "%s/device", path);
+ } else {
+ snprintf(i2c_path, sizeof(i2c_path), "%s/power/control", path);
+ snprintf(filename, sizeof(filename), "%s/device", path);
+ }
+
+ if (device_has_runtime_pm(filename))
+ snprintf(desc, sizeof(desc), _("Runtime PM for I2C %s %s (%s)"), (is_adapter ? _("Adapter") : _("Device")), name, (devname.empty() ? "" : devname.c_str()));
+ else
+ snprintf(desc, sizeof(desc), _("I2C %s %s has no runtime power management"), (is_adapter ? _("Adapter") : _("Device")), name);
+
+ snprintf(toggle_good, sizeof(toggle_good), "echo 'auto' > '%s';", i2c_path);
+ snprintf(toggle_bad, sizeof(toggle_bad), "echo 'on' > '%s';", i2c_path);
+}
+
+int i2c_tunable::good_bad(void)
+{
+ string content;
+
+ content = read_sysfs_string(i2c_path);
+
+ if (strcmp(content.c_str(), "auto") == 0)
+ return TUNE_GOOD;
+
+ return TUNE_BAD;
+}
+
+void i2c_tunable::toggle(void)
+{
+ int good;
+ good = good_bad();
+
+ if (good == TUNE_GOOD) {
+ write_sysfs(i2c_path, "on");
+ return;
+ }
+
+ write_sysfs(i2c_path, "auto");
+}
+
+const char *i2c_tunable::toggle_script(void)
+{
+ int good;
+ good = good_bad();
+
+ if (good == TUNE_GOOD) {
+ return toggle_bad;
+ }
+
+ return toggle_good;
+}
+
+static void add_i2c_callback(const char *d_name)
+{
+ class i2c_tunable *i2c;
+ char filename[PATH_MAX];
+ bool is_adapter = false;
+
+ snprintf(filename, PATH_MAX, "/sys/bus/i2c/devices/%s/new_device", d_name);
+ if (access(filename, W_OK) == 0)
+ is_adapter = true;
+
+ snprintf(filename, PATH_MAX, "/sys/bus/i2c/devices/%s", d_name);
+ i2c = new class i2c_tunable(filename, d_name, is_adapter);
+
+ if (is_adapter)
+ snprintf(filename, PATH_MAX, "/sys/bus/i2c/devices/%s/device", d_name);
+ else
+ snprintf(filename, PATH_MAX, "/sys/bus/i2c/devices/%s", d_name);
+
+ if (device_has_runtime_pm(filename))
+ all_tunables.push_back(i2c);
+ else
+ all_untunables.push_back(i2c);
+}
+
+void add_i2c_tunables(void)
+{
+ process_directory("/sys/bus/i2c/devices/", add_i2c_callback);
+}
diff --git a/src/tuning/tuningi2c.h b/src/tuning/tuningi2c.h
new file mode 100644
index 0000000..8fd8784
--- /dev/null
+++ b/src/tuning/tuningi2c.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2015, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ * Daniel Leung <daniel.leung@linux.intel.com>
+ */
+
+#ifndef _INCLUDE_GUARD_I2C_TUNE_H
+#define _INCLUDE_GUARD_I2C_TUNE_H
+
+#include <vector>
+#include <limits.h>
+
+#include "tunable.h"
+
+using namespace std;
+
+class i2c_tunable : public tunable {
+ char i2c_path[PATH_MAX];
+public:
+ i2c_tunable(const char *path, const char *name, bool is_adapter);
+
+ virtual int good_bad(void);
+
+ virtual void toggle(void);
+
+ virtual const char *toggle_script(void);
+
+};
+
+extern void add_i2c_tunables(void);
+
+
+#endif
diff --git a/src/tuning/tuningsysfs.cpp b/src/tuning/tuningsysfs.cpp
new file mode 100644
index 0000000..631e9fd
--- /dev/null
+++ b/src/tuning/tuningsysfs.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+
+#include "tuning.h"
+#include "tunable.h"
+#include "unistd.h"
+#include "tuningsysfs.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <utility>
+#include <iostream>
+#include <fstream>
+#include <unistd.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <limits.h>
+
+
+#include "../lib.h"
+
+sysfs_tunable::sysfs_tunable(const char *str, const char *_sysfs_path, const char *_target_content) : tunable(str, 1.0, _("Good"), _("Bad"), _("Unknown"))
+{
+ pt_strcpy(sysfs_path, _sysfs_path);
+ pt_strcpy(target_value, _target_content);
+ bad_value[0] = 0;
+ snprintf(toggle_good, sizeof(toggle_good), "echo '%s' > '%s';", target_value, sysfs_path);
+ snprintf(toggle_bad, sizeof(toggle_bad), "echo '%s' > '%s';", bad_value, sysfs_path);
+}
+
+int sysfs_tunable::good_bad(void)
+{
+ char current_value[4096], *c;
+ ifstream file;
+
+ file.open(sysfs_path, ios::in);
+ if (!file)
+ return TUNE_NEUTRAL;
+ file.getline(current_value, 4096);
+ file.close();
+
+ c = strchr(current_value, '\n');
+ if (c)
+ *c = 0;
+
+ if (strcmp(current_value, target_value) == 0)
+ return TUNE_GOOD;
+
+ pt_strcpy(bad_value, current_value);
+ return TUNE_BAD;
+}
+
+void sysfs_tunable::toggle(void)
+{
+ int good;
+ good = good_bad();
+
+ if (good == TUNE_GOOD) {
+ if (strlen(bad_value) > 0)
+ write_sysfs(sysfs_path, bad_value);
+ return;
+ }
+
+ write_sysfs(sysfs_path, target_value);
+}
+
+const char *sysfs_tunable::toggle_script(void) {
+ int good;
+ good = good_bad();
+
+ if (good == TUNE_GOOD) {
+ if (strlen(bad_value) > 0)
+ return toggle_bad;
+ return NULL;
+ }
+
+ return toggle_good;
+}
+
+
+void add_sysfs_tunable(const char *str, const char *_sysfs_path, const char *_target_content)
+{
+ class sysfs_tunable *tunable;
+
+ if (access(_sysfs_path, R_OK) != 0)
+ return;
+
+ tunable = new class sysfs_tunable(str, _sysfs_path, _target_content);
+
+
+ all_tunables.push_back(tunable);
+}
+
+static void add_sata_tunables_callback(const char *d_name)
+{
+ char filename[PATH_MAX];
+ char msg[4096];
+
+ snprintf(filename, sizeof(filename), "/sys/class/scsi_host/%s/link_power_management_policy", d_name);
+ snprintf(msg, sizeof(msg), _("Enable SATA link power management for %s"), d_name);
+ add_sysfs_tunable(msg, filename, "med_power_with_dipm");
+}
+
+void add_sata_tunables(void)
+{
+ process_directory("/sys/class/scsi_host", add_sata_tunables_callback);
+}
diff --git a/src/tuning/tuningsysfs.h b/src/tuning/tuningsysfs.h
new file mode 100644
index 0000000..57b9de7
--- /dev/null
+++ b/src/tuning/tuningsysfs.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_SYSFS_TUNE_H
+#define _INCLUDE_GUARD_SYSFS_TUNE_H
+
+#include <vector>
+#include <limits.h>
+
+#include "tunable.h"
+
+using namespace std;
+
+class sysfs_tunable : public tunable {
+ char sysfs_path[PATH_MAX];
+ char target_value[4096];
+ char bad_value[4096];
+public:
+ sysfs_tunable(const char *str, const char *sysfs_path, const char *target_content);
+
+ virtual int good_bad(void);
+
+ virtual void toggle(void);
+
+ virtual const char *toggle_script(void);
+
+};
+
+extern void add_sysfs_tunable(const char *str, const char *_sysfs_path, const char *_target_content);
+extern void add_sata_tunables(void);
+
+#endif
diff --git a/src/tuning/tuningusb.cpp b/src/tuning/tuningusb.cpp
new file mode 100644
index 0000000..3b7b2b1
--- /dev/null
+++ b/src/tuning/tuningusb.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+
+#include "tuning.h"
+#include "tunable.h"
+#include "unistd.h"
+#include "tuningusb.h"
+#include <string.h>
+#include <dirent.h>
+#include <utility>
+#include <iostream>
+#include <fstream>
+#include <limits.h>
+
+#include "../lib.h"
+
+usb_tunable::usb_tunable(const char *path, const char *name) : tunable("", 0.9, _("Good"), _("Bad"), _("Unknown"))
+{
+ ifstream file;
+ char filename[PATH_MAX];
+ char vendor[2048];
+ char product[2048];
+ string str1, str2;
+ snprintf(usb_path, sizeof(usb_path), "%s/power/control", path);
+
+ vendor[0] = 0;
+ product[0] = 0;
+
+ str1 = read_sysfs_string("%s/idVendor", path);
+ str2 = read_sysfs_string("%s/idProduct", path);
+
+ snprintf(desc, sizeof(desc), _("Autosuspend for unknown USB device %s (%s:%s)"), name, str1.c_str(), str2.c_str());
+
+ snprintf(filename, sizeof(filename), "%s/manufacturer", path);
+ file.open(filename, ios::in);
+ if (file) {
+ file.getline(vendor, 2047);
+ if (strstr(vendor, "Linux "))
+ vendor[0] = 0;
+ file.close();
+ };
+ snprintf(filename, sizeof(filename), "%s/product", path);
+ file.open(filename, ios::in);
+ if (file) {
+ file.getline(product, 2040);
+ file.close();
+ };
+ if (strlen(vendor) && strlen(product))
+ snprintf(desc, sizeof(desc), _("Autosuspend for USB device %s [%s]"), product, vendor);
+ else if (strlen(product))
+ snprintf(desc, sizeof(desc), _("Autosuspend for USB device %s [%s]"), product, name);
+ else if (strlen(vendor))
+ snprintf(desc, sizeof(desc), _("Autosuspend for USB device %s [%s]"), vendor, name);
+
+ snprintf(toggle_good, sizeof(toggle_good), "echo 'auto' > '%s';", usb_path);
+ snprintf(toggle_bad, sizeof(toggle_bad), "echo 'on' > '%s';", usb_path);
+}
+
+int usb_tunable::good_bad(void)
+{
+ string content;
+
+ content = read_sysfs_string(usb_path);
+
+ if (strcmp(content.c_str(), "auto") == 0)
+ return TUNE_GOOD;
+
+ return TUNE_BAD;
+}
+
+void usb_tunable::toggle(void)
+{
+ int good;
+ good = good_bad();
+
+ if (good == TUNE_GOOD) {
+ write_sysfs(usb_path, "on");
+ return;
+ }
+
+ write_sysfs(usb_path, "auto");
+}
+
+const char *usb_tunable::toggle_script(void)
+{
+ int good;
+ good = good_bad();
+
+ if (good == TUNE_GOOD) {
+ return toggle_bad;
+ }
+
+ return toggle_good;
+}
+
+static void add_usb_callback(const char *d_name)
+{
+ class usb_tunable *usb;
+ char filename[PATH_MAX];
+ DIR *dir;
+
+ snprintf(filename, sizeof(filename), "/sys/bus/usb/devices/%s/power/control", d_name);
+ if (access(filename, R_OK) != 0)
+ return;
+
+ snprintf(filename, sizeof(filename), "/sys/bus/usb/devices/%s/power/active_duration", d_name);
+ if (access(filename, R_OK)!=0)
+ return;
+
+ /* every interface of this device should support autosuspend */
+ snprintf(filename, sizeof(filename), "/sys/bus/usb/devices/%s", d_name);
+ if ((dir = opendir(filename))) {
+ struct dirent *entry;
+ while ((entry = readdir(dir))) {
+ /* dirname: <busnum>-<devnum>...:<config num>-<interface num> */
+ if (!isdigit(entry->d_name[0]))
+ continue;
+ snprintf(filename, sizeof(filename), "/sys/bus/usb/devices/%s/%s/supports_autosuspend", d_name, entry->d_name);
+ if (access(filename, R_OK) == 0 && read_sysfs(filename) == 0)
+ break;
+ }
+ closedir(dir);
+ if (entry)
+ return;
+ }
+
+ snprintf(filename, sizeof(filename), "/sys/bus/usb/devices/%s", d_name);
+ usb = new class usb_tunable(filename, d_name);
+ all_tunables.push_back(usb);
+}
+
+void add_usb_tunables(void)
+{
+ process_directory("/sys/bus/usb/devices/", add_usb_callback);
+}
diff --git a/src/tuning/tuningusb.h b/src/tuning/tuningusb.h
new file mode 100644
index 0000000..4e27e3a
--- /dev/null
+++ b/src/tuning/tuningusb.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_USB_TUNE_H
+#define _INCLUDE_GUARD_USB_TUNE_H
+
+#include <vector>
+#include <limits.h>
+
+#include "tunable.h"
+
+using namespace std;
+
+class usb_tunable : public tunable {
+ char usb_path[PATH_MAX];
+public:
+ usb_tunable(const char *usb_path, const char *path);
+
+ virtual int good_bad(void);
+
+ virtual void toggle(void);
+
+ virtual const char *toggle_script(void);
+
+};
+
+extern void add_usb_tunables(void);
+
+
+#endif
diff --git a/src/tuning/wifi.cpp b/src/tuning/wifi.cpp
new file mode 100644
index 0000000..f7a91ec
--- /dev/null
+++ b/src/tuning/wifi.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+
+#include "tuning.h"
+#include "tunable.h"
+#include "unistd.h"
+#include "wifi.h"
+#include <string.h>
+#include <utility>
+#include <iostream>
+#include <fstream>
+#include <unistd.h>
+#include <sys/types.h>
+#include <dirent.h>
+
+#include "../lib.h"
+
+extern "C" {
+#include "iw.h"
+}
+
+
+wifi_tunable::wifi_tunable(const char *_iface) : tunable("", 1.5, _("Good"), _("Bad"), _("Unknown"))
+{
+ pt_strcpy(iface, _iface);
+ sprintf(desc, _("Wireless Power Saving for interface %s"), iface);
+
+ snprintf(toggle_good, sizeof(toggle_good), "iw dev %s set power_save on", iface);
+ snprintf(toggle_bad, sizeof(toggle_bad), "iw dev %s set power_save off", iface);
+}
+
+int wifi_tunable::good_bad(void)
+{
+ if (get_wifi_power_saving(iface))
+ return TUNE_GOOD;
+
+ return TUNE_BAD;
+}
+
+void wifi_tunable::toggle(void)
+{
+ int good;
+ good = good_bad();
+
+ if (good == TUNE_GOOD) {
+ set_wifi_power_saving(iface, 0);
+ return;
+ }
+
+ set_wifi_power_saving(iface, 1);
+}
+
+const char *wifi_tunable::toggle_script(void)
+{
+ int good;
+ good = good_bad();
+
+ if (good == TUNE_GOOD) {
+ return toggle_bad;
+ }
+
+ return toggle_good;
+}
+
+void add_wifi_tunables(void)
+{
+ struct dirent *entry;
+ DIR *dir;
+ char* wlan_name;
+ class wifi_tunable *wifi;
+
+
+ dir = opendir("/sys/class/net/");
+ if (!dir)
+ return;
+ while (1) {
+ entry = readdir(dir);
+ if (!entry)
+ break;
+ wlan_name = strstr(entry->d_name, "wlan");
+ if (wlan_name) {
+ wifi = new class wifi_tunable(wlan_name);
+ all_tunables.push_back(wifi);
+ }
+
+ }
+
+ closedir(dir);
+
+}
diff --git a/src/tuning/wifi.h b/src/tuning/wifi.h
new file mode 100644
index 0000000..50ca68c
--- /dev/null
+++ b/src/tuning/wifi.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2010, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Arjan van de Ven <arjan@linux.intel.com>
+ */
+#ifndef _INCLUDE_GUARD_WIFI_TUNE_H
+#define _INCLUDE_GUARD_WIFI_TUNE_H
+
+#include <vector>
+
+#include "tunable.h"
+
+using namespace std;
+
+class wifi_tunable : public tunable {
+ char iface[4096];
+public:
+ wifi_tunable(const char *_iface);
+
+ virtual int good_bad(void);
+
+ virtual void toggle(void);
+
+ virtual const char *toggle_script(void);
+
+};
+
+extern void add_wifi_tunables(void);
+
+
+#endif
diff --git a/src/wakeup/waketab.cpp b/src/wakeup/waketab.cpp
new file mode 100644
index 0000000..77d7567
--- /dev/null
+++ b/src/wakeup/waketab.cpp
@@ -0,0 +1,195 @@
+#include <algorithm>
+#include <stdio.h>
+#include <string.h>
+#include <ncurses.h>
+#include "wakeup.h"
+#include <vector>
+#include "../lib.h"
+#include "../measurement/sysfs.h"
+#include "../display.h"
+#include "../report/report.h"
+#include "../report/report-maker.h"
+#include "../report/report-data-html.h"
+#include "wakeup_ethernet.h"
+#include "wakeup_usb.h"
+
+using namespace std;
+
+static bool should_clear = false;
+
+class wakeup_window *newtab_window;
+
+class wakeup_window: public tab_window {
+public:
+ virtual void repaint(void);
+ virtual void cursor_enter(void);
+ virtual void expose(void);
+ virtual void window_refresh(void);
+};
+
+static void init_wakeup(void)
+{
+ add_ethernet_wakeup();
+ add_usb_wakeup();
+}
+
+void initialize_wakeup(void)
+{
+ class wakeup_window *win;
+
+ win = new wakeup_window();
+
+ create_tab("WakeUp", _("WakeUp"), win, _(" <ESC> Exit | <Enter> Toggle wakeup | <r> Window refresh"));
+
+ init_wakeup();
+
+ win->cursor_max = wakeup_all.size() - 1;
+
+ if (newtab_window)
+ delete newtab_window;
+
+ newtab_window = win;
+}
+
+static void __wakeup_update_display(int cursor_pos)
+{
+ WINDOW *win;
+ unsigned int i;
+
+ win = get_ncurses_win("WakeUp");
+
+ if (!win)
+ return;
+
+ if (should_clear) {
+ should_clear = false;
+ wclear(win);
+ }
+
+ wmove(win, 1,0);
+
+ for (i = 0; i < wakeup_all.size(); i++) {
+ char res[128];
+ char desc[4096];
+ pt_strcpy(res, wakeup_all[i]->wakeup_string());
+ pt_strcpy(desc, wakeup_all[i]->description());
+ while (strlen(res) < 12)
+ strcat(res, " ");
+
+ while (strlen(desc) < 103)
+ strcat(desc, " ");
+
+ if ((int)i != cursor_pos) {
+ wattrset(win, A_NORMAL);
+ wprintw(win, " ");
+ } else {
+ wattrset(win, A_REVERSE);
+ wprintw(win, ">> ");
+ }
+ wprintw(win, "%s %s\n", _(res), _(desc));
+ }
+}
+
+void wakeup_update_display(void)
+{
+ class tab_window *wt;
+
+ wt = tab_windows["WakeUp"];
+ if (!wt)
+ return;
+ wt->repaint();
+}
+
+void wakeup_window::repaint(void)
+{
+ __wakeup_update_display(cursor_pos);
+}
+
+void wakeup_window::cursor_enter(void)
+{
+ class wakeup *wake;
+ const char *wakeup_toggle_script;
+ wake = wakeup_all[cursor_pos];
+ if (!wake)
+ return;
+ wakeup_toggle_script = wake->wakeup_toggle_script();
+ wake->wakeup_toggle();
+ ui_notify_user(">> %s\n", wakeup_toggle_script);
+}
+
+void report_show_wakeup(void)
+{
+ unsigned int i;
+ int idx, rows = 0, cols;
+
+ /* div attr css_class and css_id */
+ tag_attr div_attr;
+ init_div(&div_attr, "clear_block", "wakeup");
+
+ /* Set Title attributes */
+ tag_attr title_attr;
+ init_title_attr(&title_attr);
+
+ /* Set Table attributes, rows, and cols */
+ table_attributes wakeup_table_css;
+ cols=2;
+ idx = cols;
+
+ for (i = 0; i < wakeup_all.size(); i++) {
+ int tgb;
+ tgb = wakeup_all[i]->wakeup_value();
+ if (tgb == WAKEUP_DISABLE)
+ rows+=1;
+ }
+
+ /* add section */
+
+ report.add_div(&div_attr);
+ if (rows > 0){
+ rows= rows + 1;
+ init_wakeup_table_attr(&wakeup_table_css, rows, cols);
+
+ /* Set array of data in row Major order */
+ string *wakeup_data = new string[cols * rows];
+
+ wakeup_data[0]=__("Description");
+ wakeup_data[1]=__("Script");
+
+ for (i = 0; i < wakeup_all.size(); i++) {
+ int gb;
+ gb = wakeup_all[i]->wakeup_value();
+ if (gb != WAKEUP_DISABLE)
+ continue;
+ wakeup_data[idx]=string(wakeup_all[i]->description());
+ idx+=1;
+ wakeup_data[idx]=string(wakeup_all[i]->wakeup_toggle_script());
+ idx+=1;
+ }
+
+ /* Report Output */
+ report.add_title(&title_attr,__("Wake status of the devices"));
+ report.add_table(wakeup_data, &wakeup_table_css);
+ delete [] wakeup_data;
+ }
+}
+
+void wakeup_window::expose(void)
+{
+ cursor_pos = 0;
+ repaint();
+}
+
+void wakeup_window::window_refresh(void)
+{
+ clear_wakeup();
+ should_clear = true;
+ init_wakeup();
+}
+
+void clear_wakeup()
+{
+ for (size_t i = 0; i < wakeup_all.size(); i++) {
+ delete wakeup_all[i];
+ }
+ wakeup_all.clear();
+}
diff --git a/src/wakeup/wakeup.cpp b/src/wakeup/wakeup.cpp
new file mode 100644
index 0000000..9d83a9a
--- /dev/null
+++ b/src/wakeup/wakeup.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2018, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Gayatri Kammela <gayatri.kammela@intel.com>
+ */
+
+#include <string.h>
+#include <ncurses.h>
+#include "wakeup.h"
+#include <vector>
+#include "../lib.h"
+
+using namespace std;
+
+vector<class wakeup *> wakeup_all;
+
+wakeup::wakeup(const char *str, double _score, const char *enable, const char *disable)
+{
+ score = _score;
+ pt_strcpy(desc, str);
+ pt_strcpy(wakeup_enable, enable);
+ pt_strcpy(wakeup_disable, disable);
+}
+
+wakeup::wakeup(void)
+{
+ score = 0;
+ desc[0] = 0;
+ pt_strcpy(wakeup_enable, _("Enabled"));
+ pt_strcpy(wakeup_disable, _("Disabled"));
+ pt_strcpy(wakeup_idle, _("Unknown"));
+}
+
diff --git a/src/wakeup/wakeup.h b/src/wakeup/wakeup.h
new file mode 100644
index 0000000..13f99a3
--- /dev/null
+++ b/src/wakeup/wakeup.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2018, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Gayatri Kammela <gayatri.kammela@intel.com>
+ */
+#ifndef _INCLUDE_GUARD_WAKEUP_H
+#define _INCLUDE_GUARD_WAKEUP_H
+
+#include<vector>
+#include <limits.h>
+
+using namespace std;
+
+#define WAKEUP_ENABLE 1
+#define WAKEUP_DISABLE 0
+
+class wakeup {
+ char wakeup_enable[128];
+ char wakeup_disable[128];
+ char wakeup_idle[128];
+protected:
+ char toggle_enable[4096];
+ char toggle_disable[4096];
+public:
+ char desc[4096];
+ double score;
+
+ wakeup(const char *str, double _score, const char *enable = "", const char *disable = "");
+ wakeup(void);
+
+ virtual ~wakeup () {};
+
+ virtual int wakeup_value(void) { return WAKEUP_DISABLE; }
+
+ virtual char *wakeup_string(void)
+ {
+ switch (wakeup_value()) {
+ case WAKEUP_ENABLE:
+ return wakeup_enable;
+ case WAKEUP_DISABLE:
+ return wakeup_disable;
+ }
+ return wakeup_idle;
+ }
+
+
+ virtual const char *description(void) { return desc; };
+
+ virtual void wakeup_toggle(void) { };
+
+ virtual const char *wakeup_toggle_script(void) { return toggle_enable; }
+
+};
+
+extern vector<class wakeup *> wakeup_all;
+
+extern void initialize_wakeup(void);
+extern void wakeup_update_display(void);
+extern void report_show_wakeup(void);
+extern void clear_wakeup(void);
+
+#endif
diff --git a/src/wakeup/wakeup_ethernet.cpp b/src/wakeup/wakeup_ethernet.cpp
new file mode 100644
index 0000000..6ce1725
--- /dev/null
+++ b/src/wakeup/wakeup_ethernet.cpp
@@ -0,0 +1,111 @@
+;/*
+ * Copyright 2018, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Gayatri Kammela <gayatri.kammela@intel.com>
+ */
+
+#include "wakeup.h"
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <utility>
+#include <iostream>
+#include <fstream>
+#include <sys/socket.h>
+#include <errno.h>
+#include <linux/types.h>
+#include <net/if.h>
+#include <linux/sockios.h>
+#include <sys/ioctl.h>
+
+#include <linux/ethtool.h>
+
+#include "../lib.h"
+#include "wakeup_ethernet.h"
+
+ethernet_wakeup::ethernet_wakeup(const char *path, const char *iface) : wakeup("", 0.5, _("Enabled"), _("Disabled"))
+{
+ memset(interf, 0, sizeof(interf));
+ pt_strcpy(interf, iface);
+ sprintf(desc, _("Wake-on-lan status for device %s"), iface);
+ snprintf(eth_path, sizeof(eth_path), "/sys/class/net/%s/device/power/wakeup", iface);
+ snprintf(toggle_enable, sizeof(toggle_enable), "echo 'enabled' > '%s';", eth_path);
+ snprintf(toggle_disable, sizeof(toggle_disable), "echo 'disabled' > '%s';", eth_path);
+}
+
+int ethernet_wakeup::wakeup_value(void)
+{
+ string content;
+
+ content = read_sysfs_string(eth_path);
+
+ if (strcmp(content.c_str(), "enabled") == 0)
+ return WAKEUP_ENABLE;
+
+ return WAKEUP_DISABLE;
+}
+
+void ethernet_wakeup::wakeup_toggle(void)
+{
+ int enable;
+ enable = wakeup_value();
+
+ if (enable == WAKEUP_ENABLE) {
+ write_sysfs(eth_path, "disabled");
+ return;
+ }
+
+ write_sysfs(eth_path, "enabled");
+}
+
+const char *ethernet_wakeup::wakeup_toggle_script(void)
+{
+ int enable;
+ enable = wakeup_value();
+
+ if (enable == WAKEUP_ENABLE) {
+ return toggle_disable;
+ }
+
+ return toggle_enable;
+}
+
+void wakeup_eth_callback(const char *d_name)
+{
+ class ethernet_wakeup *eth;
+ char filename[PATH_MAX];
+
+ snprintf(filename, sizeof(filename), "/sys/class/net/%s/device/power/wakeup", d_name);
+ if (access(filename, R_OK) != 0)
+ return;
+
+ snprintf(filename, sizeof(filename), "/sys/class/net/%s/device/power/wakeup", d_name);
+ eth = new class ethernet_wakeup(filename, d_name);
+ wakeup_all.push_back(eth);
+}
+
+void add_ethernet_wakeup(void)
+{
+ process_directory("/sys/class/net/", wakeup_eth_callback);
+}
diff --git a/src/wakeup/wakeup_ethernet.h b/src/wakeup/wakeup_ethernet.h
new file mode 100644
index 0000000..682bf95
--- /dev/null
+++ b/src/wakeup/wakeup_ethernet.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2018, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Gayatri Kammela <gayatri.kammela@intel.com>
+ */
+#ifndef _INCLUDE_GUARD_ETHERNET_WAKEUP_H
+#define _INCLUDE_GUARD_ETHERNET_WAKEUP_H
+
+#include <vector>
+
+#include "wakeup.h"
+
+using namespace std;
+
+class ethernet_wakeup : public wakeup {
+ char eth_path[PATH_MAX];
+public:
+ char interf[4096];
+ ethernet_wakeup(const char *eth_path, const char *iface);
+
+ virtual int wakeup_value(void);
+
+ virtual void wakeup_toggle(void);
+
+ virtual const char *wakeup_toggle_script(void);
+
+};
+
+extern void add_ethernet_wakeup(void);
+
+#endif
diff --git a/src/wakeup/wakeup_usb.cpp b/src/wakeup/wakeup_usb.cpp
new file mode 100644
index 0000000..e0e4567
--- /dev/null
+++ b/src/wakeup/wakeup_usb.cpp
@@ -0,0 +1,111 @@
+;/*
+ * Copyright 2018, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Gayatri Kammela <gayatri.kammela@intel.com>
+ */
+
+#include "wakeup.h"
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <utility>
+#include <iostream>
+#include <fstream>
+#include <sys/socket.h>
+#include <errno.h>
+#include <linux/types.h>
+#include <net/if.h>
+#include <linux/sockios.h>
+#include <sys/ioctl.h>
+
+#include <linux/ethtool.h>
+
+#include "../lib.h"
+#include "wakeup_usb.h"
+
+usb_wakeup::usb_wakeup(const char *path, const char *iface) : wakeup("", 0.5, _("Enabled"), _("Disabled"))
+{
+ memset(interf, 0, sizeof(interf));
+ pt_strcpy(interf, iface);
+ sprintf(desc, _("Wake status for USB device %s"), iface);
+ snprintf(usb_path, sizeof(usb_path), "/sys/bus/usb/devices/%s/power/wakeup", iface);
+ snprintf(toggle_enable, sizeof(toggle_enable), "echo 'enabled' > '%s';", usb_path);
+ snprintf(toggle_disable, sizeof(toggle_disable), "echo 'disabled' > '%s';", usb_path);
+}
+
+int usb_wakeup::wakeup_value(void)
+{
+ string content;
+
+ content = read_sysfs_string(usb_path);
+
+ if (strcmp(content.c_str(), "enabled") == 0)
+ return WAKEUP_ENABLE;
+
+ return WAKEUP_DISABLE;
+}
+
+void usb_wakeup::wakeup_toggle(void)
+{
+ int enable;
+ enable = wakeup_value();
+
+ if (enable == WAKEUP_ENABLE) {
+ write_sysfs(usb_path, "disabled");
+ return;
+ }
+
+ write_sysfs(usb_path, "enabled");
+}
+
+const char *usb_wakeup::wakeup_toggle_script(void)
+{
+ int enable;
+ enable = wakeup_value();
+
+ if (enable == WAKEUP_ENABLE) {
+ return toggle_disable;
+ }
+
+ return toggle_enable;
+}
+
+void wakeup_usb_callback(const char *d_name)
+{
+ class usb_wakeup *usb;
+ char filename[PATH_MAX];
+
+ snprintf(filename, sizeof(filename), "/sys/bus/usb/devices/%s/power/wakeup", d_name);
+ if (access(filename, R_OK) != 0)
+ return;
+
+ snprintf(filename, sizeof(filename), "/sys/bus/usb/devices/%s/power/wakeup", d_name);
+ usb = new class usb_wakeup(filename, d_name);
+ wakeup_all.push_back(usb);
+}
+
+void add_usb_wakeup(void)
+{
+ process_directory("/sys/bus/usb/devices/", wakeup_usb_callback);
+}
diff --git a/src/wakeup/wakeup_usb.h b/src/wakeup/wakeup_usb.h
new file mode 100644
index 0000000..f7a1f7e
--- /dev/null
+++ b/src/wakeup/wakeup_usb.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2018, Intel Corporation
+ *
+ * This file is part of PowerTOP
+ *
+ * This program file 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; version 2 of the License.
+ *
+ * This program 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 in a file named COPYING; if not, write to the
+ * Free Software Foundation, Inc,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ * or just google for it.
+ *
+ * Authors:
+ * Gayatri Kammela <gayatri.kammela@intel.com>
+ */
+#ifndef _INCLUDE_GUARD_USB_WAKEUP_H
+#define _INCLUDE_GUARD_USB_WAKEUP_H
+
+#include <vector>
+
+#include "wakeup.h"
+
+using namespace std;
+
+class usb_wakeup : public wakeup {
+ char usb_path[PATH_MAX];
+public:
+ char interf[4096];
+ usb_wakeup(const char *usb_path, const char *iface);
+
+ virtual int wakeup_value(void);
+
+ virtual void wakeup_toggle(void);
+
+ virtual const char *wakeup_toggle_script(void);
+
+};
+
+extern void add_usb_wakeup(void);
+
+#endif
diff --git a/traceevent/Makefile.am b/traceevent/Makefile.am
new file mode 100644
index 0000000..d3ee608
--- /dev/null
+++ b/traceevent/Makefile.am
@@ -0,0 +1,7 @@
+noinst_LTLIBRARIES = libtraceevnet.la
+libtraceevnet_la_SOURCES = event-parse.c \
+ event-parse.h \
+ event-utils.h \
+ parse-filter.c\
+ parse-utils.c \
+ trace-seq.c
diff --git a/traceevent/event-parse.c b/traceevent/event-parse.c
new file mode 100644
index 0000000..1f7eb80
--- /dev/null
+++ b/traceevent/event-parse.c
@@ -0,0 +1,5664 @@
+/*
+ * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License (not later!)
+ *
+ * This program 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * The parts for function graph printing was taken and modified from the
+ * Linux Kernel that were written by
+ * - Copyright (C) 2009 Frederic Weisbecker,
+ * Frederic Weisbecker gave his permission to relicense the code to
+ * the Lesser General Public License.
+ */
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdint.h>
+#include <limits.h>
+
+#include "event-parse.h"
+#include "event-utils.h"
+
+static const char *input_buf;
+static unsigned long long input_buf_ptr;
+static unsigned long long input_buf_siz;
+
+static int is_flag_field;
+static int is_symbolic_field;
+
+static int show_warning = 1;
+
+#define do_warning(fmt, ...) \
+ do { \
+ if (show_warning) \
+ warning(fmt, ##__VA_ARGS__); \
+ } while (0)
+
+static void init_input_buf(const char *buf, unsigned long long size)
+{
+ input_buf = buf;
+ input_buf_siz = size;
+ input_buf_ptr = 0;
+}
+
+const char *pevent_get_input_buf(void)
+{
+ return input_buf;
+}
+
+unsigned long long pevent_get_input_buf_ptr(void)
+{
+ return input_buf_ptr;
+}
+
+struct event_handler {
+ struct event_handler *next;
+ int id;
+ const char *sys_name;
+ const char *event_name;
+ pevent_event_handler_func func;
+ void *context;
+};
+
+struct pevent_func_params {
+ struct pevent_func_params *next;
+ enum pevent_func_arg_type type;
+};
+
+struct pevent_function_handler {
+ struct pevent_function_handler *next;
+ enum pevent_func_arg_type ret_type;
+ char *name;
+ pevent_func_handler func;
+ struct pevent_func_params *params;
+ int nr_args;
+};
+
+static unsigned long long
+process_defined_func(struct trace_seq *s, void *data, int size,
+ struct event_format *event, struct print_arg *arg);
+
+static void free_func_handle(struct pevent_function_handler *func);
+
+/**
+ * pevent_buffer_init - init buffer for parsing
+ * @buf: buffer to parse
+ * @size: the size of the buffer
+ *
+ * For use with pevent_read_token(), this initializes the internal
+ * buffer that pevent_read_token() will parse.
+ */
+void pevent_buffer_init(const char *buf, unsigned long long size)
+{
+ init_input_buf(buf, size);
+}
+
+void breakpoint(void)
+{
+ static int x;
+ x++;
+}
+
+struct print_arg *alloc_arg(void)
+{
+ return calloc(1, sizeof(struct print_arg));
+}
+
+struct cmdline {
+ char *comm;
+ int pid;
+};
+
+static int cmdline_cmp(const void *a, const void *b)
+{
+ const struct cmdline *ca = a;
+ const struct cmdline *cb = b;
+
+ if (ca->pid < cb->pid)
+ return -1;
+ if (ca->pid > cb->pid)
+ return 1;
+
+ return 0;
+}
+
+struct cmdline_list {
+ struct cmdline_list *next;
+ char *comm;
+ int pid;
+};
+
+static int cmdline_init(struct pevent *pevent)
+{
+ struct cmdline_list *cmdlist = pevent->cmdlist;
+ struct cmdline_list *item;
+ struct cmdline *cmdlines;
+ int i;
+
+ cmdlines = malloc(sizeof(*cmdlines) * pevent->cmdline_count);
+ if (!cmdlines)
+ return -1;
+
+ i = 0;
+ while (cmdlist) {
+ cmdlines[i].pid = cmdlist->pid;
+ cmdlines[i].comm = cmdlist->comm;
+ i++;
+ item = cmdlist;
+ cmdlist = cmdlist->next;
+ free(item);
+ }
+
+ qsort(cmdlines, pevent->cmdline_count, sizeof(*cmdlines), cmdline_cmp);
+
+ pevent->cmdlines = cmdlines;
+ pevent->cmdlist = NULL;
+
+ return 0;
+}
+
+static const char *find_cmdline(struct pevent *pevent, int pid)
+{
+ const struct cmdline *comm;
+ struct cmdline key;
+
+ if (!pid)
+ return "<idle>";
+
+ if (!pevent->cmdlines && cmdline_init(pevent))
+ return "<not enough memory for cmdlines!>";
+
+ key.pid = pid;
+
+ comm = bsearch(&key, pevent->cmdlines, pevent->cmdline_count,
+ sizeof(*pevent->cmdlines), cmdline_cmp);
+
+ if (comm)
+ return comm->comm;
+ return "<...>";
+}
+
+/**
+ * pevent_pid_is_registered - return if a pid has a cmdline registered
+ * @pevent: handle for the pevent
+ * @pid: The pid to check if it has a cmdline registered with.
+ *
+ * Returns 1 if the pid has a cmdline mapped to it
+ * 0 otherwise.
+ */
+int pevent_pid_is_registered(struct pevent *pevent, int pid)
+{
+ const struct cmdline *comm;
+ struct cmdline key;
+
+ if (!pid)
+ return 1;
+
+ if (!pevent->cmdlines && cmdline_init(pevent))
+ return 0;
+
+ key.pid = pid;
+
+ comm = bsearch(&key, pevent->cmdlines, pevent->cmdline_count,
+ sizeof(*pevent->cmdlines), cmdline_cmp);
+
+ if (comm)
+ return 1;
+ return 0;
+}
+
+/*
+ * If the command lines have been converted to an array, then
+ * we must add this pid. This is much slower than when cmdlines
+ * are added before the array is initialized.
+ */
+static int add_new_comm(struct pevent *pevent, const char *comm, int pid)
+{
+ struct cmdline *newcmdlines, *cmdlines = pevent->cmdlines;
+ const struct cmdline *cmdline;
+ struct cmdline key;
+
+ if (!pid)
+ return 0;
+
+ /* avoid duplicates */
+ key.pid = pid;
+
+ cmdline = bsearch(&key, pevent->cmdlines, pevent->cmdline_count,
+ sizeof(*pevent->cmdlines), cmdline_cmp);
+ if (cmdline) {
+ errno = EEXIST;
+ return -1;
+ }
+
+ newcmdlines = realloc(cmdlines, sizeof(*cmdlines) * (pevent->cmdline_count + 1));
+ if (!newcmdlines) {
+ free(cmdlines);
+ errno = ENOMEM;
+ return -1;
+ }
+ cmdlines = newcmdlines;
+
+ cmdlines[pevent->cmdline_count].comm = strdup(comm);
+ if (!cmdlines[pevent->cmdline_count].comm) {
+ free(cmdlines);
+ errno = ENOMEM;
+ return -1;
+ }
+
+ cmdlines[pevent->cmdline_count].pid = pid;
+
+ if (cmdlines[pevent->cmdline_count].comm)
+ pevent->cmdline_count++;
+
+ qsort(cmdlines, pevent->cmdline_count, sizeof(*cmdlines), cmdline_cmp);
+ pevent->cmdlines = cmdlines;
+
+ return 0;
+}
+
+/**
+ * pevent_register_comm - register a pid / comm mapping
+ * @pevent: handle for the pevent
+ * @comm: the command line to register
+ * @pid: the pid to map the command line to
+ *
+ * This adds a mapping to search for command line names with
+ * a given pid. The comm is duplicated.
+ */
+int pevent_register_comm(struct pevent *pevent, const char *comm, int pid)
+{
+ struct cmdline_list *item;
+
+ if (pevent->cmdlines)
+ return add_new_comm(pevent, comm, pid);
+
+ item = malloc(sizeof(*item));
+ if (!item)
+ return -1;
+
+ item->comm = strdup(comm);
+ if (!item->comm) {
+ free(item);
+ return -1;
+ }
+ item->pid = pid;
+ item->next = pevent->cmdlist;
+
+ pevent->cmdlist = item;
+ pevent->cmdline_count++;
+
+ return 0;
+}
+
+struct func_map {
+ unsigned long long addr;
+ char *func;
+ char *mod;
+};
+
+struct func_list {
+ struct func_list *next;
+ unsigned long long addr;
+ char *func;
+ char *mod;
+};
+
+static int func_cmp(const void *a, const void *b)
+{
+ const struct func_map *fa = a;
+ const struct func_map *fb = b;
+
+ if (fa->addr < fb->addr)
+ return -1;
+ if (fa->addr > fb->addr)
+ return 1;
+
+ return 0;
+}
+
+/*
+ * We are searching for a record in between, not an exact
+ * match.
+ */
+static int func_bcmp(const void *a, const void *b)
+{
+ const struct func_map *fa = a;
+ const struct func_map *fb = b;
+
+ if ((fa->addr == fb->addr) ||
+
+ (fa->addr > fb->addr &&
+ fa->addr < (fb+1)->addr))
+ return 0;
+
+ if (fa->addr < fb->addr)
+ return -1;
+
+ return 1;
+}
+
+static int func_map_init(struct pevent *pevent)
+{
+ struct func_list *funclist;
+ struct func_list *item;
+ struct func_map *func_map;
+ int i;
+
+ func_map = malloc(sizeof(*func_map) * (pevent->func_count + 1));
+ if (!func_map)
+ return -1;
+
+ funclist = pevent->funclist;
+
+ i = 0;
+ while (funclist) {
+ func_map[i].func = funclist->func;
+ func_map[i].addr = funclist->addr;
+ func_map[i].mod = funclist->mod;
+ i++;
+ item = funclist;
+ funclist = funclist->next;
+ free(item);
+ }
+
+ qsort(func_map, pevent->func_count, sizeof(*func_map), func_cmp);
+
+ /*
+ * Add a special record at the end.
+ */
+ func_map[pevent->func_count].func = NULL;
+ func_map[pevent->func_count].addr = 0;
+ func_map[pevent->func_count].mod = NULL;
+
+ pevent->func_map = func_map;
+ pevent->funclist = NULL;
+
+ return 0;
+}
+
+static struct func_map *
+find_func(struct pevent *pevent, unsigned long long addr)
+{
+ struct func_map *func;
+ struct func_map key;
+
+ if (!pevent->func_map)
+ func_map_init(pevent);
+
+ key.addr = addr;
+
+ func = bsearch(&key, pevent->func_map, pevent->func_count,
+ sizeof(*pevent->func_map), func_bcmp);
+
+ return func;
+}
+
+/**
+ * pevent_find_function - find a function by a given address
+ * @pevent: handle for the pevent
+ * @addr: the address to find the function with
+ *
+ * Returns a pointer to the function stored that has the given
+ * address. Note, the address does not have to be exact, it
+ * will select the function that would contain the address.
+ */
+const char *pevent_find_function(struct pevent *pevent, unsigned long long addr)
+{
+ struct func_map *map;
+
+ map = find_func(pevent, addr);
+ if (!map)
+ return NULL;
+
+ return map->func;
+}
+
+/**
+ * pevent_find_function_address - find a function address by a given address
+ * @pevent: handle for the pevent
+ * @addr: the address to find the function with
+ *
+ * Returns the address the function starts at. This can be used in
+ * conjunction with pevent_find_function to print both the function
+ * name and the function offset.
+ */
+unsigned long long
+pevent_find_function_address(struct pevent *pevent, unsigned long long addr)
+{
+ struct func_map *map;
+
+ map = find_func(pevent, addr);
+ if (!map)
+ return 0;
+
+ return map->addr;
+}
+
+/**
+ * pevent_register_function - register a function with a given address
+ * @pevent: handle for the pevent
+ * @function: the function name to register
+ * @addr: the address the function starts at
+ * @mod: the kernel module the function may be in (NULL for none)
+ *
+ * This registers a function name with an address and module.
+ * The @func passed in is duplicated.
+ */
+int pevent_register_function(struct pevent *pevent, char *func,
+ unsigned long long addr, char *mod)
+{
+ struct func_list *item = malloc(sizeof(*item));
+
+ if (!item)
+ return -1;
+
+ item->next = pevent->funclist;
+ item->func = strdup(func);
+ if (!item->func)
+ goto out_free;
+
+ if (mod) {
+ item->mod = strdup(mod);
+ if (!item->mod)
+ goto out_free_func;
+ } else
+ item->mod = NULL;
+ item->addr = addr;
+
+ pevent->funclist = item;
+ pevent->func_count++;
+
+ return 0;
+
+out_free_func:
+ free(item->func);
+ item->func = NULL;
+out_free:
+ free(item);
+ errno = ENOMEM;
+ return -1;
+}
+
+/**
+ * pevent_print_funcs - print out the stored functions
+ * @pevent: handle for the pevent
+ *
+ * This prints out the stored functions.
+ */
+void pevent_print_funcs(struct pevent *pevent)
+{
+ int i;
+
+ if (!pevent->func_map)
+ func_map_init(pevent);
+
+ for (i = 0; i < (int)pevent->func_count; i++) {
+ printf("%016llx %s",
+ pevent->func_map[i].addr,
+ pevent->func_map[i].func);
+ if (pevent->func_map[i].mod)
+ printf(" [%s]\n", pevent->func_map[i].mod);
+ else
+ printf("\n");
+ }
+}
+
+struct printk_map {
+ unsigned long long addr;
+ char *printk;
+};
+
+struct printk_list {
+ struct printk_list *next;
+ unsigned long long addr;
+ char *printk;
+};
+
+static int printk_cmp(const void *a, const void *b)
+{
+ const struct printk_map *pa = a;
+ const struct printk_map *pb = b;
+
+ if (pa->addr < pb->addr)
+ return -1;
+ if (pa->addr > pb->addr)
+ return 1;
+
+ return 0;
+}
+
+static int printk_map_init(struct pevent *pevent)
+{
+ struct printk_list *printklist;
+ struct printk_list *item;
+ struct printk_map *printk_map;
+ int i;
+
+ printk_map = malloc(sizeof(*printk_map) * (pevent->printk_count + 1));
+ if (!printk_map)
+ return -1;
+
+ printklist = pevent->printklist;
+
+ i = 0;
+ while (printklist) {
+ printk_map[i].printk = printklist->printk;
+ printk_map[i].addr = printklist->addr;
+ i++;
+ item = printklist;
+ printklist = printklist->next;
+ free(item);
+ }
+
+ qsort(printk_map, pevent->printk_count, sizeof(*printk_map), printk_cmp);
+
+ pevent->printk_map = printk_map;
+ pevent->printklist = NULL;
+
+ return 0;
+}
+
+static struct printk_map *
+find_printk(struct pevent *pevent, unsigned long long addr)
+{
+ struct printk_map *printk;
+ struct printk_map key;
+
+ if (!pevent->printk_map && printk_map_init(pevent))
+ return NULL;
+
+ key.addr = addr;
+
+ printk = bsearch(&key, pevent->printk_map, pevent->printk_count,
+ sizeof(*pevent->printk_map), printk_cmp);
+
+ return printk;
+}
+
+/**
+ * pevent_register_print_string - register a string by its address
+ * @pevent: handle for the pevent
+ * @fmt: the string format to register
+ * @addr: the address the string was located at
+ *
+ * This registers a string by the address it was stored in the kernel.
+ * The @fmt passed in is duplicated.
+ */
+int pevent_register_print_string(struct pevent *pevent, char *fmt,
+ unsigned long long addr)
+{
+ struct printk_list *item = malloc(sizeof(*item));
+
+ if (!item)
+ return -1;
+
+ item->next = pevent->printklist;
+ item->addr = addr;
+
+ item->printk = strdup(fmt);
+ if (!item->printk)
+ goto out_free;
+
+ pevent->printklist = item;
+ pevent->printk_count++;
+
+ return 0;
+
+out_free:
+ free(item);
+ errno = ENOMEM;
+ return -1;
+}
+
+/**
+ * pevent_print_printk - print out the stored strings
+ * @pevent: handle for the pevent
+ *
+ * This prints the string formats that were stored.
+ */
+void pevent_print_printk(struct pevent *pevent)
+{
+ int i;
+
+ if (!pevent->printk_map)
+ printk_map_init(pevent);
+
+ for (i = 0; i < (int)pevent->printk_count; i++) {
+ printf("%016llx %s\n",
+ pevent->printk_map[i].addr,
+ pevent->printk_map[i].printk);
+ }
+}
+
+static struct event_format *alloc_event(void)
+{
+ return calloc(1, sizeof(struct event_format));
+}
+
+static int add_event(struct pevent *pevent, struct event_format *event)
+{
+ int i;
+ struct event_format **events = realloc(pevent->events, sizeof(event) *
+ (pevent->nr_events + 1));
+ if (!events)
+ return -1;
+
+ pevent->events = events;
+
+ for (i = 0; i < pevent->nr_events; i++) {
+ if (pevent->events[i]->id > event->id)
+ break;
+ }
+ if (i < pevent->nr_events)
+ memmove(&pevent->events[i + 1],
+ &pevent->events[i],
+ sizeof(event) * (pevent->nr_events - i));
+
+ pevent->events[i] = event;
+ pevent->nr_events++;
+
+ event->pevent = pevent;
+
+ return 0;
+}
+
+static int event_item_type(enum event_type type)
+{
+ switch (type) {
+ case EVENT_ITEM ... EVENT_SQUOTE:
+ return 1;
+ case EVENT_ERROR ... EVENT_DELIM:
+ default:
+ return 0;
+ }
+}
+
+static void free_flag_sym(struct print_flag_sym *fsym)
+{
+ struct print_flag_sym *next;
+
+ while (fsym) {
+ next = fsym->next;
+ free(fsym->value);
+ free(fsym->str);
+ free(fsym);
+ fsym = next;
+ }
+}
+
+static void free_arg(struct print_arg *arg)
+{
+ struct print_arg *farg;
+
+ if (!arg)
+ return;
+
+ switch (arg->type) {
+ case PRINT_ATOM:
+ free(arg->atom.atom);
+ break;
+ case PRINT_FIELD:
+ free(arg->field.name);
+ break;
+ case PRINT_FLAGS:
+ free_arg(arg->flags.field);
+ free(arg->flags.delim);
+ free_flag_sym(arg->flags.flags);
+ break;
+ case PRINT_SYMBOL:
+ free_arg(arg->symbol.field);
+ free_flag_sym(arg->symbol.symbols);
+ break;
+ case PRINT_HEX:
+ free_arg(arg->hex.field);
+ free_arg(arg->hex.size);
+ break;
+ case PRINT_TYPE:
+ free(arg->typecast.type);
+ free_arg(arg->typecast.item);
+ break;
+ case PRINT_STRING:
+ case PRINT_BSTRING:
+ free(arg->string.string);
+ break;
+ case PRINT_DYNAMIC_ARRAY:
+ free(arg->dynarray.index);
+ break;
+ case PRINT_OP:
+ free(arg->op.op);
+ free_arg(arg->op.left);
+ free_arg(arg->op.right);
+ break;
+ case PRINT_FUNC:
+ while (arg->func.args) {
+ farg = arg->func.args;
+ arg->func.args = farg->next;
+ free_arg(farg);
+ }
+ break;
+
+ case PRINT_NULL:
+ default:
+ break;
+ }
+
+ free(arg);
+}
+
+static enum event_type get_type(int ch)
+{
+ if (ch == '\n')
+ return EVENT_NEWLINE;
+ if (isspace(ch))
+ return EVENT_SPACE;
+ if (isalnum(ch) || ch == '_')
+ return EVENT_ITEM;
+ if (ch == '\'')
+ return EVENT_SQUOTE;
+ if (ch == '"')
+ return EVENT_DQUOTE;
+ if (!isprint(ch))
+ return EVENT_NONE;
+ if (ch == '(' || ch == ')' || ch == ',')
+ return EVENT_DELIM;
+
+ return EVENT_OP;
+}
+
+static int __read_char(void)
+{
+ if (input_buf_ptr >= input_buf_siz)
+ return -1;
+
+ return input_buf[input_buf_ptr++];
+}
+
+static int __peek_char(void)
+{
+ if (input_buf_ptr >= input_buf_siz)
+ return -1;
+
+ return input_buf[input_buf_ptr];
+}
+
+/**
+ * pevent_peek_char - peek at the next character that will be read
+ *
+ * Returns the next character read, or -1 if end of buffer.
+ */
+int pevent_peek_char(void)
+{
+ return __peek_char();
+}
+
+static int extend_token(char **tok, char *buf, int size)
+{
+ char *newtok = realloc(*tok, size);
+
+ if (!newtok) {
+ free(*tok);
+ *tok = NULL;
+ return -1;
+ }
+
+ if (!*tok)
+ strcpy(newtok, buf);
+ else
+ strcat(newtok, buf);
+ *tok = newtok;
+
+ return 0;
+}
+
+static enum event_type force_token(const char *str, char **tok);
+
+static enum event_type __read_token(char **tok)
+{
+ char buf[BUFSIZ];
+ int ch, last_ch, quote_ch, next_ch;
+ int i = 0;
+ int tok_size = 0;
+ enum event_type type;
+
+ *tok = NULL;
+
+
+ ch = __read_char();
+ if (ch < 0)
+ return EVENT_NONE;
+
+ type = get_type(ch);
+ if (type == EVENT_NONE)
+ return type;
+
+ buf[i++] = ch;
+
+ switch (type) {
+ case EVENT_NEWLINE:
+ case EVENT_DELIM:
+ if (asprintf(tok, "%c", ch) < 0)
+ return EVENT_ERROR;
+
+ return type;
+
+ case EVENT_OP:
+ switch (ch) {
+ case '-':
+ next_ch = __peek_char();
+ if (next_ch == '>') {
+ buf[i++] = __read_char();
+ break;
+ }
+ /* fall through */
+ case '+':
+ case '|':
+ case '&':
+ case '>':
+ case '<':
+ last_ch = ch;
+ ch = __peek_char();
+ if (ch != last_ch)
+ goto test_equal;
+ buf[i++] = __read_char();
+ switch (last_ch) {
+ case '>':
+ case '<':
+ goto test_equal;
+ default:
+ break;
+ }
+ break;
+ case '!':
+ case '=':
+ goto test_equal;
+ default: /* what should we do instead? */
+ break;
+ }
+ buf[i] = 0;
+ *tok = strdup(buf);
+ return type;
+
+ test_equal:
+ ch = __peek_char();
+ if (ch == '=')
+ buf[i++] = __read_char();
+ goto out;
+
+ case EVENT_DQUOTE:
+ case EVENT_SQUOTE:
+ /* don't keep quotes */
+ i--;
+ quote_ch = ch;
+ last_ch = 0;
+ concat:
+ do {
+ if (i == (BUFSIZ - 1)) {
+ buf[i] = 0;
+ tok_size += BUFSIZ;
+
+ if (extend_token(tok, buf, tok_size) < 0)
+ return EVENT_NONE;
+ i = 0;
+ }
+ last_ch = ch;
+ ch = __read_char();
+ buf[i++] = ch;
+ /* the '\' '\' will cancel itself */
+ if (ch == '\\' && last_ch == '\\')
+ last_ch = 0;
+ } while (ch != quote_ch || last_ch == '\\');
+ /* remove the last quote */
+ i--;
+
+ /*
+ * For strings (double quotes) check the next token.
+ * If it is another string, concatinate the two.
+ */
+ if (type == EVENT_DQUOTE) {
+ unsigned long long save_input_buf_ptr = input_buf_ptr;
+
+ do {
+ ch = __read_char();
+ } while (isspace(ch));
+ if (ch == '"')
+ goto concat;
+ input_buf_ptr = save_input_buf_ptr;
+ }
+
+ goto out;
+
+ case EVENT_ERROR ... EVENT_SPACE:
+ case EVENT_ITEM:
+ default:
+ break;
+ }
+
+ while (get_type(__peek_char()) == type) {
+ if (i == (BUFSIZ - 1)) {
+ buf[i] = 0;
+ tok_size += BUFSIZ;
+
+ if (extend_token(tok, buf, tok_size) < 0)
+ return EVENT_NONE;
+ i = 0;
+ }
+ ch = __read_char();
+ buf[i++] = ch;
+ }
+
+ out:
+ buf[i] = 0;
+ if (extend_token(tok, buf, tok_size + i + 1) < 0)
+ return EVENT_NONE;
+
+ if (type == EVENT_ITEM) {
+ /*
+ * Older versions of the kernel has a bug that
+ * creates invalid symbols and will break the mac80211
+ * parsing. This is a work around to that bug.
+ *
+ * See Linux kernel commit:
+ * 811cb50baf63461ce0bdb234927046131fc7fa8b
+ */
+ if (strcmp(*tok, "LOCAL_PR_FMT") == 0) {
+ free(*tok);
+ *tok = NULL;
+ return force_token("\"\%s\" ", tok);
+ } else if (strcmp(*tok, "STA_PR_FMT") == 0) {
+ free(*tok);
+ *tok = NULL;
+ return force_token("\" sta:%pM\" ", tok);
+ } else if (strcmp(*tok, "VIF_PR_FMT") == 0) {
+ free(*tok);
+ *tok = NULL;
+ return force_token("\" vif:%p(%d)\" ", tok);
+ }
+ }
+
+ return type;
+}
+
+static enum event_type force_token(const char *str, char **tok)
+{
+ const char *save_input_buf;
+ unsigned long long save_input_buf_ptr;
+ unsigned long long save_input_buf_siz;
+ enum event_type type;
+
+ /* save off the current input pointers */
+ save_input_buf = input_buf;
+ save_input_buf_ptr = input_buf_ptr;
+ save_input_buf_siz = input_buf_siz;
+
+ init_input_buf(str, strlen(str));
+
+ type = __read_token(tok);
+
+ /* reset back to original token */
+ input_buf = save_input_buf;
+ input_buf_ptr = save_input_buf_ptr;
+ input_buf_siz = save_input_buf_siz;
+
+ return type;
+}
+
+static void free_token(char *tok)
+{
+ free(tok);
+}
+
+static enum event_type read_token(char **tok)
+{
+ enum event_type type;
+
+ for (;;) {
+ type = __read_token(tok);
+ if (type != EVENT_SPACE)
+ return type;
+
+ free_token(*tok);
+ }
+
+ /* not reached */
+ *tok = NULL;
+ return EVENT_NONE;
+}
+
+/**
+ * pevent_read_token - access to utilites to use the pevent parser
+ * @tok: The token to return
+ *
+ * This will parse tokens from the string given by
+ * pevent_init_data().
+ *
+ * Returns the token type.
+ */
+enum event_type pevent_read_token(char **tok)
+{
+ return read_token(tok);
+}
+
+/**
+ * pevent_free_token - free a token returned by pevent_read_token
+ * @token: the token to free
+ */
+void pevent_free_token(char *token)
+{
+ free_token(token);
+}
+
+/* no newline */
+static enum event_type read_token_item(char **tok)
+{
+ enum event_type type;
+
+ for (;;) {
+ type = __read_token(tok);
+ if (type != EVENT_SPACE && type != EVENT_NEWLINE)
+ return type;
+ free_token(*tok);
+ *tok = NULL;
+ }
+
+ /* not reached */
+ *tok = NULL;
+ return EVENT_NONE;
+}
+
+static int test_type(enum event_type type, enum event_type expect)
+{
+ if (type != expect) {
+ do_warning("Error: expected type %d but read %d",
+ expect, type);
+ return -1;
+ }
+ return 0;
+}
+
+static int test_type_token(enum event_type type, const char *token,
+ enum event_type expect, const char *expect_tok)
+{
+ if (type != expect) {
+ do_warning("Error: expected type %d but read %d",
+ expect, type);
+ return -1;
+ }
+
+ if (strcmp(token, expect_tok) != 0) {
+ do_warning("Error: expected '%s' but read '%s'",
+ expect_tok, token);
+ return -1;
+ }
+ return 0;
+}
+
+static int __read_expect_type(enum event_type expect, char **tok, int newline_ok)
+{
+ enum event_type type;
+
+ if (newline_ok)
+ type = read_token(tok);
+ else
+ type = read_token_item(tok);
+ return test_type(type, expect);
+}
+
+static int read_expect_type(enum event_type expect, char **tok)
+{
+ return __read_expect_type(expect, tok, 1);
+}
+
+static int __read_expected(enum event_type expect, const char *str,
+ int newline_ok)
+{
+ enum event_type type;
+ char *token;
+ int ret;
+
+ if (newline_ok)
+ type = read_token(&token);
+ else
+ type = read_token_item(&token);
+
+ ret = test_type_token(type, token, expect, str);
+
+ free_token(token);
+
+ return ret;
+}
+
+static int read_expected(enum event_type expect, const char *str)
+{
+ return __read_expected(expect, str, 1);
+}
+
+static int read_expected_item(enum event_type expect, const char *str)
+{
+ return __read_expected(expect, str, 0);
+}
+
+static char *event_read_name(void)
+{
+ char *token;
+
+ if (read_expected(EVENT_ITEM, "name") < 0)
+ return NULL;
+
+ if (read_expected(EVENT_OP, ":") < 0)
+ return NULL;
+
+ if (read_expect_type(EVENT_ITEM, &token) < 0)
+ goto fail;
+
+ return token;
+
+ fail:
+ free_token(token);
+ return NULL;
+}
+
+static int event_read_id(void)
+{
+ char *token;
+ int id;
+
+ if (read_expected_item(EVENT_ITEM, "ID") < 0)
+ return -1;
+
+ if (read_expected(EVENT_OP, ":") < 0)
+ return -1;
+
+ if (read_expect_type(EVENT_ITEM, &token) < 0)
+ goto fail;
+
+ id = strtoul(token, NULL, 0);
+ free_token(token);
+ return id;
+
+ fail:
+ free_token(token);
+ return -1;
+}
+
+static int field_is_string(struct format_field *field)
+{
+ if ((field->flags & FIELD_IS_ARRAY) &&
+ (strstr(field->type, "char") || strstr(field->type, "u8") ||
+ strstr(field->type, "s8")))
+ return 1;
+
+ return 0;
+}
+
+static int field_is_dynamic(struct format_field *field)
+{
+ if (strncmp(field->type, "__data_loc", 10) == 0)
+ return 1;
+
+ return 0;
+}
+
+static int field_is_long(struct format_field *field)
+{
+ /* includes long long */
+ if (strstr(field->type, "long"))
+ return 1;
+
+ return 0;
+}
+
+static unsigned int type_size(const char *name)
+{
+ /* This covers all FIELD_IS_STRING types. */
+ static struct {
+ const char *type;
+ unsigned int size;
+ } table[] = {
+ { "u8", 1 },
+ { "u16", 2 },
+ { "u32", 4 },
+ { "u64", 8 },
+ { "s8", 1 },
+ { "s16", 2 },
+ { "s32", 4 },
+ { "s64", 8 },
+ { "char", 1 },
+ { },
+ };
+ int i;
+
+ for (i = 0; table[i].type; i++) {
+ if (!strcmp(table[i].type, name))
+ return table[i].size;
+ }
+
+ return 0;
+}
+
+static int event_read_fields(struct event_format *event, struct format_field **fields)
+{
+ struct format_field *field = NULL;
+ enum event_type type;
+ char *token;
+ char *last_token;
+ int count = 0;
+
+ do {
+ unsigned int size_dynamic = 0;
+
+ type = read_token(&token);
+ if (type == EVENT_NEWLINE) {
+ free_token(token);
+ return count;
+ }
+
+ count++;
+
+ if (test_type_token(type, token, EVENT_ITEM, "field"))
+ goto fail;
+ free_token(token);
+
+ type = read_token(&token);
+ /*
+ * The ftrace fields may still use the "special" name.
+ * Just ignore it.
+ */
+ if (event->flags & EVENT_FL_ISFTRACE &&
+ type == EVENT_ITEM && strcmp(token, "special") == 0) {
+ free_token(token);
+ type = read_token(&token);
+ }
+
+ if (test_type_token(type, token, EVENT_OP, ":") < 0)
+ goto fail;
+
+ free_token(token);
+ if (read_expect_type(EVENT_ITEM, &token) < 0)
+ goto fail;
+
+ last_token = token;
+
+ field = calloc(1, sizeof(*field));
+ if (!field)
+ goto fail;
+
+ field->event = event;
+
+ /* read the rest of the type */
+ for (;;) {
+ type = read_token(&token);
+ if (type == EVENT_ITEM ||
+ (type == EVENT_OP && strcmp(token, "*") == 0) ||
+ /*
+ * Some of the ftrace fields are broken and have
+ * an illegal "." in them.
+ */
+ (event->flags & EVENT_FL_ISFTRACE &&
+ type == EVENT_OP && strcmp(token, ".") == 0)) {
+
+ if (strcmp(token, "*") == 0)
+ field->flags |= FIELD_IS_POINTER;
+
+ if (field->type) {
+ char *new_type;
+ new_type = realloc(field->type,
+ strlen(field->type) +
+ strlen(last_token) + 2);
+ if (!new_type) {
+ free(last_token);
+ goto fail;
+ }
+ field->type = new_type;
+ strcat(field->type, " ");
+ strcat(field->type, last_token);
+ free(last_token);
+ } else
+ field->type = last_token;
+ last_token = token;
+ continue;
+ }
+
+ break;
+ }
+
+ if (!field->type) {
+ do_warning("%s: no type found", __func__);
+ goto fail;
+ }
+ field->name = last_token;
+
+ if (test_type(type, EVENT_OP))
+ goto fail;
+
+ if (strcmp(token, "[") == 0) {
+ enum event_type last_type = type;
+ char *brackets = token;
+ char *new_brackets;
+ int len;
+
+ field->flags |= FIELD_IS_ARRAY;
+
+ type = read_token(&token);
+
+ if (type == EVENT_ITEM)
+ field->arraylen = strtoul(token, NULL, 0);
+ else
+ field->arraylen = 0;
+
+ while (strcmp(token, "]") != 0) {
+ if (last_type == EVENT_ITEM &&
+ type == EVENT_ITEM)
+ len = 2;
+ else
+ len = 1;
+ last_type = type;
+
+ new_brackets = realloc(brackets,
+ strlen(brackets) +
+ strlen(token) + len);
+ if (!new_brackets) {
+ free(brackets);
+ goto fail;
+ }
+ brackets = new_brackets;
+ if (len == 2)
+ strcat(brackets, " ");
+ strcat(brackets, token);
+ /* We only care about the last token */
+ field->arraylen = strtoul(token, NULL, 0);
+ free_token(token);
+ type = read_token(&token);
+ if (type == EVENT_NONE) {
+ do_warning("failed to find token");
+ goto fail;
+ }
+ }
+
+ free_token(token);
+
+ new_brackets = realloc(brackets, strlen(brackets) + 2);
+ if (!new_brackets) {
+ free(brackets);
+ goto fail;
+ }
+ brackets = new_brackets;
+ strcat(brackets, "]");
+
+ /* add brackets to type */
+
+ type = read_token(&token);
+ /*
+ * If the next token is not an OP, then it is of
+ * the format: type [] item;
+ */
+ if (type == EVENT_ITEM) {
+ char *new_type;
+ new_type = realloc(field->type,
+ strlen(field->type) +
+ strlen(field->name) +
+ strlen(brackets) + 2);
+ if (!new_type) {
+ free(brackets);
+ goto fail;
+ }
+ field->type = new_type;
+ strcat(field->type, " ");
+ strcat(field->type, field->name);
+ size_dynamic = type_size(field->name);
+ free_token(field->name);
+ strcat(field->type, brackets);
+ field->name = token;
+ type = read_token(&token);
+ } else {
+ char *new_type;
+ new_type = realloc(field->type,
+ strlen(field->type) +
+ strlen(brackets) + 1);
+ if (!new_type) {
+ free(brackets);
+ goto fail;
+ }
+ field->type = new_type;
+ strcat(field->type, brackets);
+ }
+ free(brackets);
+ }
+
+ if (field_is_string(field))
+ field->flags |= FIELD_IS_STRING;
+ if (field_is_dynamic(field))
+ field->flags |= FIELD_IS_DYNAMIC;
+ if (field_is_long(field))
+ field->flags |= FIELD_IS_LONG;
+
+ if (test_type_token(type, token, EVENT_OP, ";"))
+ goto fail;
+ free_token(token);
+
+ if (read_expected(EVENT_ITEM, "offset") < 0)
+ goto fail_expect;
+
+ if (read_expected(EVENT_OP, ":") < 0)
+ goto fail_expect;
+
+ if (read_expect_type(EVENT_ITEM, &token))
+ goto fail;
+ field->offset = strtoul(token, NULL, 0);
+ free_token(token);
+
+ if (read_expected(EVENT_OP, ";") < 0)
+ goto fail_expect;
+
+ if (read_expected(EVENT_ITEM, "size") < 0)
+ goto fail_expect;
+
+ if (read_expected(EVENT_OP, ":") < 0)
+ goto fail_expect;
+
+ if (read_expect_type(EVENT_ITEM, &token))
+ goto fail;
+ field->size = strtoul(token, NULL, 0);
+ free_token(token);
+
+ if (read_expected(EVENT_OP, ";") < 0)
+ goto fail_expect;
+
+ type = read_token(&token);
+ if (type != EVENT_NEWLINE) {
+ /* newer versions of the kernel have a "signed" type */
+ if (test_type_token(type, token, EVENT_ITEM, "signed"))
+ goto fail;
+
+ free_token(token);
+
+ if (read_expected(EVENT_OP, ":") < 0)
+ goto fail_expect;
+
+ if (read_expect_type(EVENT_ITEM, &token))
+ goto fail;
+
+ if (strtoul(token, NULL, 0))
+ field->flags |= FIELD_IS_SIGNED;
+
+ free_token(token);
+ if (read_expected(EVENT_OP, ";") < 0)
+ goto fail_expect;
+
+ if (read_expect_type(EVENT_NEWLINE, &token))
+ goto fail;
+ }
+
+ free_token(token);
+
+ if (field->flags & FIELD_IS_ARRAY) {
+ if (field->arraylen)
+ field->elementsize = field->size / field->arraylen;
+ else if (field->flags & FIELD_IS_DYNAMIC)
+ field->elementsize = size_dynamic;
+ else if (field->flags & FIELD_IS_STRING)
+ field->elementsize = 1;
+ else if (field->flags & FIELD_IS_LONG)
+ field->elementsize = event->pevent ?
+ event->pevent->long_size :
+ sizeof(long);
+ } else
+ field->elementsize = field->size;
+
+ *fields = field;
+ fields = &field->next;
+
+ } while (1);
+
+ return 0;
+
+fail:
+ free_token(token);
+fail_expect:
+ if (field) {
+ free(field->type);
+ free(field->name);
+ free(field);
+ }
+ return -1;
+}
+
+static int event_read_format(struct event_format *event)
+{
+ char *token;
+ int ret;
+
+ if (read_expected_item(EVENT_ITEM, "format") < 0)
+ return -1;
+
+ if (read_expected(EVENT_OP, ":") < 0)
+ return -1;
+
+ if (read_expect_type(EVENT_NEWLINE, &token))
+ goto fail;
+ free_token(token);
+
+ ret = event_read_fields(event, &event->format.common_fields);
+ if (ret < 0)
+ return ret;
+ event->format.nr_common = ret;
+
+ ret = event_read_fields(event, &event->format.fields);
+ if (ret < 0)
+ return ret;
+ event->format.nr_fields = ret;
+
+ return 0;
+
+ fail:
+ free_token(token);
+ return -1;
+}
+
+static enum event_type
+process_arg_token(struct event_format *event, struct print_arg *arg,
+ char **tok, enum event_type type);
+
+static enum event_type
+process_arg(struct event_format *event, struct print_arg *arg, char **tok)
+{
+ enum event_type type;
+ char *token;
+
+ type = read_token(&token);
+ *tok = token;
+
+ return process_arg_token(event, arg, tok, type);
+}
+
+static enum event_type
+process_op(struct event_format *event, struct print_arg *arg, char **tok);
+
+static enum event_type
+process_cond(struct event_format *event, struct print_arg *top, char **tok)
+{
+ struct print_arg *arg, *left, *right;
+ enum event_type type;
+ char *token = NULL;
+
+ arg = alloc_arg();
+ left = alloc_arg();
+ right = alloc_arg();
+
+ if (!arg || !left || !right) {
+ do_warning("%s: not enough memory!", __func__);
+ /* arg will be freed at out_free */
+ free_arg(left);
+ free_arg(right);
+ goto out_free;
+ }
+
+ arg->type = PRINT_OP;
+ arg->op.left = left;
+ arg->op.right = right;
+
+ *tok = NULL;
+ type = process_arg(event, left, &token);
+
+ again:
+ /* Handle other operations in the arguments */
+ if (type == EVENT_OP && strcmp(token, ":") != 0) {
+ type = process_op(event, left, &token);
+ goto again;
+ }
+
+ if (test_type_token(type, token, EVENT_OP, ":"))
+ goto out_free;
+
+ arg->op.op = token;
+
+ type = process_arg(event, right, &token);
+
+ top->op.right = arg;
+
+ *tok = token;
+ return type;
+
+out_free:
+ /* Top may point to itself */
+ top->op.right = NULL;
+ free_token(token);
+ free_arg(arg);
+ return EVENT_ERROR;
+}
+
+static enum event_type
+process_array(struct event_format *event, struct print_arg *top, char **tok)
+{
+ struct print_arg *arg;
+ enum event_type type;
+ char *token = NULL;
+
+ arg = alloc_arg();
+ if (!arg) {
+ do_warning("%s: not enough memory!", __func__);
+ /* '*tok' is set to top->op.op. No need to free. */
+ *tok = NULL;
+ return EVENT_ERROR;
+ }
+
+ *tok = NULL;
+ type = process_arg(event, arg, &token);
+ if (test_type_token(type, token, EVENT_OP, "]"))
+ goto out_free;
+
+ top->op.right = arg;
+
+ free_token(token);
+ type = read_token_item(&token);
+ *tok = token;
+
+ return type;
+
+out_free:
+ free_token(token);
+ free_arg(arg);
+ return EVENT_ERROR;
+}
+
+static int get_op_prio(char *op)
+{
+ if (!op[1]) {
+ switch (op[0]) {
+ case '~':
+ case '!':
+ return 4;
+ case '*':
+ case '/':
+ case '%':
+ return 6;
+ case '+':
+ case '-':
+ return 7;
+ /* '>>' and '<<' are 8 */
+ case '<':
+ case '>':
+ return 9;
+ /* '==' and '!=' are 10 */
+ case '&':
+ return 11;
+ case '^':
+ return 12;
+ case '|':
+ return 13;
+ case '?':
+ return 16;
+ default:
+ do_warning("unknown op '%c'", op[0]);
+ return -1;
+ }
+ } else {
+ if (strcmp(op, "++") == 0 ||
+ strcmp(op, "--") == 0) {
+ return 3;
+ } else if (strcmp(op, ">>") == 0 ||
+ strcmp(op, "<<") == 0) {
+ return 8;
+ } else if (strcmp(op, ">=") == 0 ||
+ strcmp(op, "<=") == 0) {
+ return 9;
+ } else if (strcmp(op, "==") == 0 ||
+ strcmp(op, "!=") == 0) {
+ return 10;
+ } else if (strcmp(op, "&&") == 0) {
+ return 14;
+ } else if (strcmp(op, "||") == 0) {
+ return 15;
+ } else {
+ do_warning("unknown op '%s'", op);
+ return -1;
+ }
+ }
+}
+
+static int set_op_prio(struct print_arg *arg)
+{
+
+ /* single ops are the greatest */
+ if (!arg->op.left || arg->op.left->type == PRINT_NULL)
+ arg->op.prio = 0;
+ else
+ arg->op.prio = get_op_prio(arg->op.op);
+
+ return arg->op.prio;
+}
+
+/* Note, *tok does not get freed, but will most likely be saved */
+static enum event_type
+process_op(struct event_format *event, struct print_arg *arg, char **tok)
+{
+ struct print_arg *left, *right = NULL;
+ enum event_type type;
+ char *token;
+
+ /* the op is passed in via tok */
+ token = *tok;
+
+ if (arg->type == PRINT_OP && !arg->op.left) {
+ /* handle single op */
+ if (token[1]) {
+ do_warning("bad op token %s", token);
+ goto out_free;
+ }
+ switch (token[0]) {
+ case '~':
+ case '!':
+ case '+':
+ case '-':
+ break;
+ default:
+ do_warning("bad op token %s", token);
+ goto out_free;
+
+ }
+
+ /* make an empty left */
+ left = alloc_arg();
+ if (!left)
+ goto out_warn_free;
+
+ left->type = PRINT_NULL;
+ arg->op.left = left;
+
+ right = alloc_arg();
+ if (!right)
+ goto out_warn_free;
+
+ arg->op.right = right;
+
+ /* do not free the token, it belongs to an op */
+ *tok = NULL;
+ type = process_arg(event, right, tok);
+
+ } else if (strcmp(token, "?") == 0) {
+
+ left = alloc_arg();
+ if (!left)
+ goto out_warn_free;
+
+ /* copy the top arg to the left */
+ *left = *arg;
+
+ arg->type = PRINT_OP;
+ arg->op.op = token;
+ arg->op.left = left;
+ arg->op.prio = 0;
+
+ /* it will set arg->op.right */
+ type = process_cond(event, arg, tok);
+
+ } else if (strcmp(token, ">>") == 0 ||
+ strcmp(token, "<<") == 0 ||
+ strcmp(token, "&") == 0 ||
+ strcmp(token, "|") == 0 ||
+ strcmp(token, "&&") == 0 ||
+ strcmp(token, "||") == 0 ||
+ strcmp(token, "-") == 0 ||
+ strcmp(token, "+") == 0 ||
+ strcmp(token, "*") == 0 ||
+ strcmp(token, "^") == 0 ||
+ strcmp(token, "/") == 0 ||
+ strcmp(token, "<") == 0 ||
+ strcmp(token, ">") == 0 ||
+ strcmp(token, "<=") == 0 ||
+ strcmp(token, ">=") == 0 ||
+ strcmp(token, "==") == 0 ||
+ strcmp(token, "!=") == 0) {
+
+ left = alloc_arg();
+ if (!left)
+ goto out_warn_free;
+
+ /* copy the top arg to the left */
+ *left = *arg;
+
+ arg->type = PRINT_OP;
+ arg->op.op = token;
+ arg->op.left = left;
+ arg->op.right = NULL;
+
+ if (set_op_prio(arg) == -1) {
+ event->flags |= EVENT_FL_FAILED;
+ /* arg->op.op (= token) will be freed at out_free */
+ arg->op.op = NULL;
+ goto out_free;
+ }
+
+ type = read_token_item(&token);
+ *tok = token;
+
+ /* could just be a type pointer */
+ if ((strcmp(arg->op.op, "*") == 0) &&
+ type == EVENT_DELIM && (strcmp(token, ")") == 0)) {
+ char *new_atom;
+
+ if (left->type != PRINT_ATOM) {
+ do_warning("bad pointer type");
+ goto out_free;
+ }
+ new_atom = realloc(left->atom.atom,
+ strlen(left->atom.atom) + 3);
+ if (!new_atom)
+ goto out_warn_free;
+
+ left->atom.atom = new_atom;
+ strcat(left->atom.atom, " *");
+ free(arg->op.op);
+ *arg = *left;
+ free(left);
+
+ return type;
+ }
+
+ right = alloc_arg();
+ if (!right)
+ goto out_warn_free;
+
+ type = process_arg_token(event, right, tok, type);
+ arg->op.right = right;
+
+ } else if (strcmp(token, "[") == 0) {
+
+ left = alloc_arg();
+ if (!left)
+ goto out_warn_free;
+
+ *left = *arg;
+
+ arg->type = PRINT_OP;
+ arg->op.op = token;
+ arg->op.left = left;
+
+ arg->op.prio = 0;
+
+ /* it will set arg->op.right */
+ type = process_array(event, arg, tok);
+
+ } else {
+ do_warning("unknown op '%s'", token);
+ event->flags |= EVENT_FL_FAILED;
+ /* the arg is now the left side */
+ goto out_free;
+ }
+
+ if (type == EVENT_OP && strcmp(*tok, ":") != 0) {
+ int prio;
+
+ /* higher prios need to be closer to the root */
+ prio = get_op_prio(*tok);
+
+ if (prio > arg->op.prio)
+ return process_op(event, arg, tok);
+
+ return process_op(event, right, tok);
+ }
+
+ return type;
+
+out_warn_free:
+ do_warning("%s: not enough memory!", __func__);
+out_free:
+ free_token(token);
+ *tok = NULL;
+ return EVENT_ERROR;
+}
+
+static enum event_type
+process_entry(struct event_format *event __maybe_unused, struct print_arg *arg,
+ char **tok)
+{
+ enum event_type type;
+ char *field;
+ char *token;
+
+ if (read_expected(EVENT_OP, "->") < 0)
+ goto out_err;
+
+ if (read_expect_type(EVENT_ITEM, &token) < 0)
+ goto out_free;
+ field = token;
+
+ arg->type = PRINT_FIELD;
+ arg->field.name = field;
+
+ if (is_flag_field) {
+ arg->field.field = pevent_find_any_field(event, arg->field.name);
+ arg->field.field->flags |= FIELD_IS_FLAG;
+ is_flag_field = 0;
+ } else if (is_symbolic_field) {
+ arg->field.field = pevent_find_any_field(event, arg->field.name);
+ arg->field.field->flags |= FIELD_IS_SYMBOLIC;
+ is_symbolic_field = 0;
+ }
+
+ type = read_token(&token);
+ *tok = token;
+
+ return type;
+
+ out_free:
+ free_token(token);
+ out_err:
+ *tok = NULL;
+ return EVENT_ERROR;
+}
+
+static char *arg_eval (struct print_arg *arg);
+
+static unsigned long long
+eval_type_str(unsigned long long val, const char *type, int pointer)
+{
+ int sign = 0;
+ char *ref;
+ int len;
+
+ len = strlen(type);
+
+ if (pointer) {
+
+ if (type[len-1] != '*') {
+ do_warning("pointer expected with non pointer type");
+ return val;
+ }
+
+ ref = malloc(len);
+ if (!ref) {
+ do_warning("%s: not enough memory!", __func__);
+ return val;
+ }
+ memcpy(ref, type, len);
+
+ /* chop off the " *" */
+ ref[len - 2] = 0;
+
+ val = eval_type_str(val, ref, 0);
+ free(ref);
+ return val;
+ }
+
+ /* check if this is a pointer */
+ if (type[len - 1] == '*')
+ return val;
+
+ /* Try to figure out the arg size*/
+ if (strncmp(type, "struct", 6) == 0)
+ /* all bets off */
+ return val;
+
+ if (strcmp(type, "u8") == 0)
+ return val & 0xff;
+
+ if (strcmp(type, "u16") == 0)
+ return val & 0xffff;
+
+ if (strcmp(type, "u32") == 0)
+ return val & 0xffffffff;
+
+ if (strcmp(type, "u64") == 0 ||
+ strcmp(type, "s64"))
+ return val;
+
+ if (strcmp(type, "s8") == 0)
+ return (unsigned long long)(char)val & 0xff;
+
+ if (strcmp(type, "s16") == 0)
+ return (unsigned long long)(short)val & 0xffff;
+
+ if (strcmp(type, "s32") == 0)
+ return (unsigned long long)(int)val & 0xffffffff;
+
+ if (strncmp(type, "unsigned ", 9) == 0) {
+ sign = 0;
+ type += 9;
+ }
+
+ if (strcmp(type, "char") == 0) {
+ if (sign)
+ return (unsigned long long)(char)val & 0xff;
+ else
+ return val & 0xff;
+ }
+
+ if (strcmp(type, "short") == 0) {
+ if (sign)
+ return (unsigned long long)(short)val & 0xffff;
+ else
+ return val & 0xffff;
+ }
+
+ if (strcmp(type, "int") == 0) {
+ if (sign)
+ return (unsigned long long)(int)val & 0xffffffff;
+ else
+ return val & 0xffffffff;
+ }
+
+ return val;
+}
+
+/*
+ * Try to figure out the type.
+ */
+static unsigned long long
+eval_type(unsigned long long val, struct print_arg *arg, int pointer)
+{
+ if (arg->type != PRINT_TYPE) {
+ do_warning("expected type argument");
+ return 0;
+ }
+
+ return eval_type_str(val, arg->typecast.type, pointer);
+}
+
+static int arg_num_eval(struct print_arg *arg, long long *val)
+{
+ long long left, right;
+ int ret = 1;
+
+ switch (arg->type) {
+ case PRINT_ATOM:
+ *val = strtoll(arg->atom.atom, NULL, 0);
+ break;
+ case PRINT_TYPE:
+ ret = arg_num_eval(arg->typecast.item, val);
+ if (!ret)
+ break;
+ *val = eval_type(*val, arg, 0);
+ break;
+ case PRINT_OP:
+ switch (arg->op.op[0]) {
+ case '|':
+ ret = arg_num_eval(arg->op.left, &left);
+ if (!ret)
+ break;
+ ret = arg_num_eval(arg->op.right, &right);
+ if (!ret)
+ break;
+ if (arg->op.op[1])
+ *val = left || right;
+ else
+ *val = left | right;
+ break;
+ case '&':
+ ret = arg_num_eval(arg->op.left, &left);
+ if (!ret)
+ break;
+ ret = arg_num_eval(arg->op.right, &right);
+ if (!ret)
+ break;
+ if (arg->op.op[1])
+ *val = left && right;
+ else
+ *val = left & right;
+ break;
+ case '<':
+ ret = arg_num_eval(arg->op.left, &left);
+ if (!ret)
+ break;
+ ret = arg_num_eval(arg->op.right, &right);
+ if (!ret)
+ break;
+ switch (arg->op.op[1]) {
+ case 0:
+ *val = left < right;
+ break;
+ case '<':
+ *val = left << right;
+ break;
+ case '=':
+ *val = left <= right;
+ break;
+ default:
+ do_warning("unknown op '%s'", arg->op.op);
+ ret = 0;
+ }
+ break;
+ case '>':
+ ret = arg_num_eval(arg->op.left, &left);
+ if (!ret)
+ break;
+ ret = arg_num_eval(arg->op.right, &right);
+ if (!ret)
+ break;
+ switch (arg->op.op[1]) {
+ case 0:
+ *val = left > right;
+ break;
+ case '>':
+ *val = left >> right;
+ break;
+ case '=':
+ *val = left >= right;
+ break;
+ default:
+ do_warning("unknown op '%s'", arg->op.op);
+ ret = 0;
+ }
+ break;
+ case '=':
+ ret = arg_num_eval(arg->op.left, &left);
+ if (!ret)
+ break;
+ ret = arg_num_eval(arg->op.right, &right);
+ if (!ret)
+ break;
+
+ if (arg->op.op[1] != '=') {
+ do_warning("unknown op '%s'", arg->op.op);
+ ret = 0;
+ } else
+ *val = left == right;
+ break;
+ case '!':
+ ret = arg_num_eval(arg->op.left, &left);
+ if (!ret)
+ break;
+ ret = arg_num_eval(arg->op.right, &right);
+ if (!ret)
+ break;
+
+ switch (arg->op.op[1]) {
+ case '=':
+ *val = left != right;
+ break;
+ default:
+ do_warning("unknown op '%s'", arg->op.op);
+ ret = 0;
+ }
+ break;
+ case '-':
+ /* check for negative */
+ if (arg->op.left->type == PRINT_NULL)
+ left = 0;
+ else
+ ret = arg_num_eval(arg->op.left, &left);
+ if (!ret)
+ break;
+ ret = arg_num_eval(arg->op.right, &right);
+ if (!ret)
+ break;
+ *val = left - right;
+ break;
+ case '+':
+ if (arg->op.left->type == PRINT_NULL)
+ left = 0;
+ else
+ ret = arg_num_eval(arg->op.left, &left);
+ if (!ret)
+ break;
+ ret = arg_num_eval(arg->op.right, &right);
+ if (!ret)
+ break;
+ *val = left + right;
+ break;
+ default:
+ do_warning("unknown op '%s'", arg->op.op);
+ ret = 0;
+ }
+ break;
+
+ case PRINT_NULL:
+ case PRINT_FIELD ... PRINT_SYMBOL:
+ case PRINT_STRING:
+ case PRINT_BSTRING:
+ default:
+ do_warning("invalid eval type %d", arg->type);
+ ret = 0;
+
+ }
+ return ret;
+}
+
+static char *arg_eval (struct print_arg *arg)
+{
+ long long val;
+ static char buf[20];
+
+ switch (arg->type) {
+ case PRINT_ATOM:
+ return arg->atom.atom;
+ case PRINT_TYPE:
+ return arg_eval(arg->typecast.item);
+ case PRINT_OP:
+ if (!arg_num_eval(arg, &val))
+ break;
+ sprintf(buf, "%lld", val);
+ return buf;
+
+ case PRINT_NULL:
+ case PRINT_FIELD ... PRINT_SYMBOL:
+ case PRINT_STRING:
+ case PRINT_BSTRING:
+ default:
+ do_warning("invalid eval type %d", arg->type);
+ break;
+ }
+
+ return NULL;
+}
+
+static enum event_type
+process_fields(struct event_format *event, struct print_flag_sym **list, char **tok)
+{
+ enum event_type type;
+ struct print_arg *arg = NULL;
+ struct print_flag_sym *field;
+ char *token = *tok;
+ char *value;
+
+ do {
+ free_token(token);
+ type = read_token_item(&token);
+ if (test_type_token(type, token, EVENT_OP, "{"))
+ break;
+
+ arg = alloc_arg();
+ if (!arg)
+ goto out_free;
+
+ free_token(token);
+ type = process_arg(event, arg, &token);
+
+ if (type == EVENT_OP)
+ type = process_op(event, arg, &token);
+
+ if (type == EVENT_ERROR)
+ goto out_free;
+
+ if (test_type_token(type, token, EVENT_DELIM, ","))
+ goto out_free;
+
+ field = calloc(1, sizeof(*field));
+ if (!field)
+ goto out_free;
+
+ value = arg_eval(arg);
+ if (value == NULL)
+ goto out_free_field;
+ field->value = strdup(value);
+ if (field->value == NULL)
+ goto out_free_field;
+
+ free_arg(arg);
+ arg = alloc_arg();
+ if (!arg)
+ goto out_free;
+
+ free_token(token);
+ type = process_arg(event, arg, &token);
+ if (test_type_token(type, token, EVENT_OP, "}"))
+ goto out_free_field;
+
+ value = arg_eval(arg);
+ if (value == NULL)
+ goto out_free_field;
+ field->str = strdup(value);
+ if (field->str == NULL)
+ goto out_free_field;
+ free_arg(arg);
+ arg = NULL;
+
+ *list = field;
+ list = &field->next;
+
+ free_token(token);
+ type = read_token_item(&token);
+ } while (type == EVENT_DELIM && strcmp(token, ",") == 0);
+
+ *tok = token;
+ return type;
+
+out_free_field:
+ free_flag_sym(field);
+out_free:
+ free_arg(arg);
+ free_token(token);
+ *tok = NULL;
+
+ return EVENT_ERROR;
+}
+
+static enum event_type
+process_flags(struct event_format *event, struct print_arg *arg, char **tok)
+{
+ struct print_arg *field;
+ enum event_type type;
+ char *token;
+
+ memset(arg, 0, sizeof(*arg));
+ arg->type = PRINT_FLAGS;
+
+ field = alloc_arg();
+ if (!field) {
+ do_warning("%s: not enough memory!", __func__);
+ goto out;
+ }
+
+ type = process_arg(event, field, &token);
+
+ /* Handle operations in the first argument */
+ while (type == EVENT_OP)
+ type = process_op(event, field, &token);
+
+ if (test_type_token(type, token, EVENT_DELIM, ","))
+ goto out_free_field;
+ free_token(token);
+
+ arg->flags.field = field;
+
+ type = read_token_item(&token);
+ if (event_item_type(type)) {
+ arg->flags.delim = token;
+ type = read_token_item(&token);
+ }
+
+ if (test_type_token(type, token, EVENT_DELIM, ","))
+ goto out_free;
+
+ type = process_fields(event, &arg->flags.flags, &token);
+ if (test_type_token(type, token, EVENT_DELIM, ")"))
+ goto out_free;
+
+ free_token(token);
+ type = read_token_item(tok);
+ return type;
+
+out_free_field:
+ free_arg(field);
+out_free:
+ free_token(token);
+out:
+ *tok = NULL;
+ return EVENT_ERROR;
+}
+
+static enum event_type
+process_symbols(struct event_format *event, struct print_arg *arg, char **tok)
+{
+ struct print_arg *field;
+ enum event_type type;
+ char *token;
+
+ memset(arg, 0, sizeof(*arg));
+ arg->type = PRINT_SYMBOL;
+
+ field = alloc_arg();
+ if (!field) {
+ do_warning("%s: not enough memory!", __func__);
+ goto out;
+ }
+
+ type = process_arg(event, field, &token);
+ if (test_type_token(type, token, EVENT_DELIM, ","))
+ goto out_free_field;
+
+ arg->symbol.field = field;
+
+ type = process_fields(event, &arg->symbol.symbols, &token);
+ if (test_type_token(type, token, EVENT_DELIM, ")"))
+ goto out_free;
+
+ free_token(token);
+ type = read_token_item(tok);
+ return type;
+
+out_free_field:
+ free_arg(field);
+out_free:
+ free_token(token);
+out:
+ *tok = NULL;
+ return EVENT_ERROR;
+}
+
+static enum event_type
+process_hex(struct event_format *event, struct print_arg *arg, char **tok)
+{
+ struct print_arg *field;
+ enum event_type type;
+ char *token;
+
+ memset(arg, 0, sizeof(*arg));
+ arg->type = PRINT_HEX;
+
+ field = alloc_arg();
+ if (!field) {
+ do_warning("%s: not enough memory!", __func__);
+ goto out;
+ }
+
+ type = process_arg(event, field, &token);
+
+ if (test_type_token(type, token, EVENT_DELIM, ","))
+ goto out_free;
+
+ arg->hex.field = field;
+
+ free_token(token);
+
+ field = alloc_arg();
+ if (!field) {
+ do_warning("%s: not enough memory!", __func__);
+ *tok = NULL;
+ return EVENT_ERROR;
+ }
+
+ type = process_arg(event, field, &token);
+
+ if (test_type_token(type, token, EVENT_DELIM, ")"))
+ goto out_free;
+
+ arg->hex.size = field;
+
+ free_token(token);
+ type = read_token_item(tok);
+ return type;
+
+ out_free:
+ free_arg(field);
+ free_token(token);
+out:
+ *tok = NULL;
+ return EVENT_ERROR;
+}
+
+static enum event_type
+process_dynamic_array(struct event_format *event, struct print_arg *arg, char **tok)
+{
+ struct format_field *field;
+ enum event_type type;
+ char *token;
+
+ memset(arg, 0, sizeof(*arg));
+ arg->type = PRINT_DYNAMIC_ARRAY;
+
+ /*
+ * The item within the parenthesis is another field that holds
+ * the index into where the array starts.
+ */
+ type = read_token(&token);
+ *tok = token;
+ if (type != EVENT_ITEM)
+ goto out_free;
+
+ /* Find the field */
+
+ field = pevent_find_field(event, token);
+ if (!field)
+ goto out_free;
+
+ arg->dynarray.field = field;
+ arg->dynarray.index = 0;
+
+ if (read_expected(EVENT_DELIM, ")") < 0)
+ goto out_free;
+
+ free_token(token);
+ type = read_token_item(&token);
+ *tok = token;
+ if (type != EVENT_OP || strcmp(token, "[") != 0)
+ return type;
+
+ free_token(token);
+ arg = alloc_arg();
+ if (!arg) {
+ do_warning("%s: not enough memory!", __func__);
+ *tok = NULL;
+ return EVENT_ERROR;
+ }
+
+ type = process_arg(event, arg, &token);
+ if (type == EVENT_ERROR)
+ goto out_free_arg;
+
+ if (!test_type_token(type, token, EVENT_OP, "]"))
+ goto out_free_arg;
+
+ free_token(token);
+ type = read_token_item(tok);
+ return type;
+
+ out_free_arg:
+ free_arg(arg);
+ out_free:
+ free_token(token);
+ *tok = NULL;
+ return EVENT_ERROR;
+}
+
+static enum event_type
+process_paren(struct event_format *event, struct print_arg *arg, char **tok)
+{
+ struct print_arg *item_arg;
+ enum event_type type;
+ char *token;
+
+ type = process_arg(event, arg, &token);
+
+ if (type == EVENT_ERROR)
+ goto out_free;
+
+ if (type == EVENT_OP)
+ type = process_op(event, arg, &token);
+
+ if (type == EVENT_ERROR)
+ goto out_free;
+
+ if (test_type_token(type, token, EVENT_DELIM, ")"))
+ goto out_free;
+
+ free_token(token);
+ type = read_token_item(&token);
+
+ /*
+ * If the next token is an item or another open paren, then
+ * this was a typecast.
+ */
+ if (event_item_type(type) ||
+ (type == EVENT_DELIM && strcmp(token, "(") == 0)) {
+
+ /* make this a typecast and contine */
+
+ /* prevous must be an atom */
+ if (arg->type != PRINT_ATOM) {
+ do_warning("previous needed to be PRINT_ATOM");
+ goto out_free;
+ }
+
+ item_arg = alloc_arg();
+ if (!item_arg) {
+ do_warning("%s: not enough memory!", __func__);
+ goto out_free;
+ }
+
+ arg->type = PRINT_TYPE;
+ arg->typecast.type = arg->atom.atom;
+ arg->typecast.item = item_arg;
+ type = process_arg_token(event, item_arg, &token, type);
+
+ }
+
+ *tok = token;
+ return type;
+
+ out_free:
+ free_token(token);
+ *tok = NULL;
+ return EVENT_ERROR;
+}
+
+
+static enum event_type
+process_str(struct event_format *event __maybe_unused, struct print_arg *arg,
+ char **tok)
+{
+ enum event_type type;
+ char *token;
+
+ if (read_expect_type(EVENT_ITEM, &token) < 0)
+ goto out_free;
+
+ arg->type = PRINT_STRING;
+ arg->string.string = token;
+ arg->string.offset = -1;
+
+ if (read_expected(EVENT_DELIM, ")") < 0)
+ goto out_err;
+
+ type = read_token(&token);
+ *tok = token;
+
+ return type;
+
+ out_free:
+ free_token(token);
+ out_err:
+ *tok = NULL;
+ return EVENT_ERROR;
+}
+
+static struct pevent_function_handler *
+find_func_handler(struct pevent *pevent, char *func_name)
+{
+ struct pevent_function_handler *func;
+
+ if (!pevent)
+ return NULL;
+
+ for (func = pevent->func_handlers; func; func = func->next) {
+ if (strcmp(func->name, func_name) == 0)
+ break;
+ }
+
+ return func;
+}
+
+static void remove_func_handler(struct pevent *pevent, char *func_name)
+{
+ struct pevent_function_handler *func;
+ struct pevent_function_handler **next;
+
+ next = &pevent->func_handlers;
+ while ((func = *next)) {
+ if (strcmp(func->name, func_name) == 0) {
+ *next = func->next;
+ free_func_handle(func);
+ break;
+ }
+ next = &func->next;
+ }
+}
+
+static enum event_type
+process_func_handler(struct event_format *event, struct pevent_function_handler *func,
+ struct print_arg *arg, char **tok)
+{
+ struct print_arg **next_arg;
+ struct print_arg *farg;
+ enum event_type type;
+ char *token;
+ const char *test;
+ int i;
+
+ arg->type = PRINT_FUNC;
+ arg->func.func = func;
+
+ *tok = NULL;
+
+ next_arg = &(arg->func.args);
+ for (i = 0; i < func->nr_args; i++) {
+ farg = alloc_arg();
+ if (!farg) {
+ do_warning("%s: not enough memory!", __func__);
+ return EVENT_ERROR;
+ }
+
+ type = process_arg(event, farg, &token);
+ if (i < (func->nr_args - 1))
+ test = ",";
+ else
+ test = ")";
+
+ if (test_type_token(type, token, EVENT_DELIM, test)) {
+ free_arg(farg);
+ free_token(token);
+ return EVENT_ERROR;
+ }
+
+ *next_arg = farg;
+ next_arg = &(farg->next);
+ free_token(token);
+ }
+
+ type = read_token(&token);
+ *tok = token;
+
+ return type;
+}
+
+static enum event_type
+process_function(struct event_format *event, struct print_arg *arg,
+ char *token, char **tok)
+{
+ struct pevent_function_handler *func;
+
+ if (strcmp(token, "__print_flags") == 0) {
+ free_token(token);
+ is_flag_field = 1;
+ return process_flags(event, arg, tok);
+ }
+ if (strcmp(token, "__print_symbolic") == 0) {
+ free_token(token);
+ is_symbolic_field = 1;
+ return process_symbols(event, arg, tok);
+ }
+ if (strcmp(token, "__print_hex") == 0) {
+ free_token(token);
+ return process_hex(event, arg, tok);
+ }
+ if (strcmp(token, "__get_str") == 0) {
+ free_token(token);
+ return process_str(event, arg, tok);
+ }
+ if (strcmp(token, "__get_dynamic_array") == 0) {
+ free_token(token);
+ return process_dynamic_array(event, arg, tok);
+ }
+
+ func = find_func_handler(event->pevent, token);
+ if (func) {
+ free_token(token);
+ return process_func_handler(event, func, arg, tok);
+ }
+
+ do_warning("function %s not defined", token);
+ free_token(token);
+ return EVENT_ERROR;
+}
+
+static enum event_type
+process_arg_token(struct event_format *event, struct print_arg *arg,
+ char **tok, enum event_type type)
+{
+ char *token;
+ char *atom;
+
+ token = *tok;
+
+ switch (type) {
+ case EVENT_ITEM:
+ if (strcmp(token, "REC") == 0) {
+ free_token(token);
+ type = process_entry(event, arg, &token);
+ break;
+ }
+ atom = token;
+ /* test the next token */
+ type = read_token_item(&token);
+
+ /*
+ * If the next token is a parenthesis, then this
+ * is a function.
+ */
+ if (type == EVENT_DELIM && strcmp(token, "(") == 0) {
+ free_token(token);
+ token = NULL;
+ /* this will free atom. */
+ type = process_function(event, arg, atom, &token);
+ break;
+ }
+ /* atoms can be more than one token long */
+ while (type == EVENT_ITEM) {
+ char *new_atom;
+ new_atom = realloc(atom,
+ strlen(atom) + strlen(token) + 2);
+ if (!new_atom) {
+ free(atom);
+ *tok = NULL;
+ free_token(token);
+ return EVENT_ERROR;
+ }
+ atom = new_atom;
+ strcat(atom, " ");
+ strcat(atom, token);
+ free_token(token);
+ type = read_token_item(&token);
+ }
+
+ arg->type = PRINT_ATOM;
+ arg->atom.atom = atom;
+ break;
+
+ case EVENT_DQUOTE:
+ case EVENT_SQUOTE:
+ arg->type = PRINT_ATOM;
+ arg->atom.atom = token;
+ type = read_token_item(&token);
+ break;
+ case EVENT_DELIM:
+ if (strcmp(token, "(") == 0) {
+ free_token(token);
+ type = process_paren(event, arg, &token);
+ break;
+ }
+ case EVENT_OP:
+ /* handle single ops */
+ arg->type = PRINT_OP;
+ arg->op.op = token;
+ arg->op.left = NULL;
+ type = process_op(event, arg, &token);
+
+ /* On error, the op is freed */
+ if (type == EVENT_ERROR)
+ arg->op.op = NULL;
+
+ /* return error type if errored */
+ break;
+
+ case EVENT_ERROR ... EVENT_NEWLINE:
+ default:
+ do_warning("unexpected type %d", type);
+ return EVENT_ERROR;
+ }
+ *tok = token;
+
+ return type;
+}
+
+static int event_read_print_args(struct event_format *event, struct print_arg **list)
+{
+ enum event_type type = EVENT_ERROR;
+ struct print_arg *arg;
+ char *token;
+ int args = 0;
+
+ do {
+ if (type == EVENT_NEWLINE) {
+ type = read_token_item(&token);
+ continue;
+ }
+
+ arg = alloc_arg();
+ if (!arg) {
+ do_warning("%s: not enough memory!", __func__);
+ return -1;
+ }
+
+ type = process_arg(event, arg, &token);
+
+ if (type == EVENT_ERROR) {
+ free_token(token);
+ free_arg(arg);
+ return -1;
+ }
+
+ *list = arg;
+ args++;
+
+ if (type == EVENT_OP) {
+ type = process_op(event, arg, &token);
+ free_token(token);
+ if (type == EVENT_ERROR) {
+ *list = NULL;
+ free_arg(arg);
+ return -1;
+ }
+ list = &arg->next;
+ continue;
+ }
+
+ if (type == EVENT_DELIM && strcmp(token, ",") == 0) {
+ free_token(token);
+ *list = arg;
+ list = &arg->next;
+ continue;
+ }
+ break;
+ } while (type != EVENT_NONE);
+
+ if (type != EVENT_NONE && type != EVENT_ERROR)
+ free_token(token);
+
+ return args;
+}
+
+static int event_read_print(struct event_format *event)
+{
+ enum event_type type;
+ char *token;
+ int ret;
+
+ if (read_expected_item(EVENT_ITEM, "print") < 0)
+ return -1;
+
+ if (read_expected(EVENT_ITEM, "fmt") < 0)
+ return -1;
+
+ if (read_expected(EVENT_OP, ":") < 0)
+ return -1;
+
+ if (read_expect_type(EVENT_DQUOTE, &token) < 0)
+ goto fail;
+
+ concat:
+ event->print_fmt.format = token;
+ event->print_fmt.args = NULL;
+
+ /* ok to have no arg */
+ type = read_token_item(&token);
+
+ if (type == EVENT_NONE)
+ return 0;
+
+ /* Handle concatenation of print lines */
+ if (type == EVENT_DQUOTE) {
+ char *cat;
+
+ if (asprintf(&cat, "%s%s", event->print_fmt.format, token) < 0)
+ goto fail;
+ free_token(token);
+ free_token(event->print_fmt.format);
+ event->print_fmt.format = NULL;
+ token = cat;
+ goto concat;
+ }
+
+ if (test_type_token(type, token, EVENT_DELIM, ","))
+ goto fail;
+
+ free_token(token);
+
+ ret = event_read_print_args(event, &event->print_fmt.args);
+ if (ret < 0)
+ return -1;
+
+ return ret;
+
+ fail:
+ free_token(token);
+ return -1;
+}
+
+/**
+ * pevent_find_common_field - return a common field by event
+ * @event: handle for the event
+ * @name: the name of the common field to return
+ *
+ * Returns a common field from the event by the given @name.
+ * This only searchs the common fields and not all field.
+ */
+struct format_field *
+pevent_find_common_field(struct event_format *event, const char *name)
+{
+ struct format_field *format;
+
+ for (format = event->format.common_fields;
+ format; format = format->next) {
+ if (strcmp(format->name, name) == 0)
+ break;
+ }
+
+ return format;
+}
+
+/**
+ * pevent_find_field - find a non-common field
+ * @event: handle for the event
+ * @name: the name of the non-common field
+ *
+ * Returns a non-common field by the given @name.
+ * This does not search common fields.
+ */
+struct format_field *
+pevent_find_field(struct event_format *event, const char *name)
+{
+ struct format_field *format;
+
+ for (format = event->format.fields;
+ format; format = format->next) {
+ if (strcmp(format->name, name) == 0)
+ break;
+ }
+
+ return format;
+}
+
+/**
+ * pevent_find_any_field - find any field by name
+ * @event: handle for the event
+ * @name: the name of the field
+ *
+ * Returns a field by the given @name.
+ * This searchs the common field names first, then
+ * the non-common ones if a common one was not found.
+ */
+struct format_field *
+pevent_find_any_field(struct event_format *event, const char *name)
+{
+ struct format_field *format;
+
+ format = pevent_find_common_field(event, name);
+ if (format)
+ return format;
+ return pevent_find_field(event, name);
+}
+
+/**
+ * pevent_read_number - read a number from data
+ * @pevent: handle for the pevent
+ * @ptr: the raw data
+ * @size: the size of the data that holds the number
+ *
+ * Returns the number (converted to host) from the
+ * raw data.
+ */
+unsigned long long pevent_read_number(struct pevent *pevent,
+ const void *ptr, int size)
+{
+ switch (size) {
+ case 1:
+ return *(unsigned char *)ptr;
+ case 2:
+ return data2host2(pevent, ptr);
+ case 4:
+ return data2host4(pevent, ptr);
+ case 8:
+ return data2host8(pevent, ptr);
+ default:
+ /* BUG! */
+ return 0;
+ }
+}
+
+/**
+ * pevent_read_number_field - read a number from data
+ * @field: a handle to the field
+ * @data: the raw data to read
+ * @value: the value to place the number in
+ *
+ * Reads raw data according to a field offset and size,
+ * and translates it into @value.
+ *
+ * Returns 0 on success, -1 otherwise.
+ */
+int pevent_read_number_field(struct format_field *field, const void *data,
+ unsigned long long *value)
+{
+ if (!field)
+ return -1;
+ switch (field->size) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ *value = pevent_read_number(field->event->pevent,
+ data + field->offset, field->size);
+ return 0;
+ default:
+ return -1;
+ }
+}
+
+static int get_common_info(struct pevent *pevent,
+ const char *type, int *offset, int *size)
+{
+ struct event_format *event;
+ struct format_field *field;
+
+ /*
+ * All events should have the same common elements.
+ * Pick any event to find where the type is;
+ */
+ if (!pevent->events) {
+ do_warning("no event_list!");
+ return -1;
+ }
+
+ event = pevent->events[0];
+ field = pevent_find_common_field(event, type);
+ if (!field)
+ return -1;
+
+ *offset = field->offset;
+ *size = field->size;
+
+ return 0;
+}
+
+static int __parse_common(struct pevent *pevent, void *data,
+ int *size, int *offset, const char *name)
+{
+ int ret;
+
+ if (!*size) {
+ ret = get_common_info(pevent, name, offset, size);
+ if (ret < 0)
+ return ret;
+ }
+ return pevent_read_number(pevent, data + *offset, *size);
+}
+
+static int trace_parse_common_type(struct pevent *pevent, void *data)
+{
+ return __parse_common(pevent, data,
+ &pevent->type_size, &pevent->type_offset,
+ "common_type");
+}
+
+static int parse_common_pid(struct pevent *pevent, void *data)
+{
+ return __parse_common(pevent, data,
+ &pevent->pid_size, &pevent->pid_offset,
+ "common_pid");
+}
+
+static int parse_common_pc(struct pevent *pevent, void *data)
+{
+ return __parse_common(pevent, data,
+ &pevent->pc_size, &pevent->pc_offset,
+ "common_preempt_count");
+}
+
+static int parse_common_flags(struct pevent *pevent, void *data)
+{
+ return __parse_common(pevent, data,
+ &pevent->flags_size, &pevent->flags_offset,
+ "common_flags");
+}
+
+static int parse_common_lock_depth(struct pevent *pevent, void *data)
+{
+ return __parse_common(pevent, data,
+ &pevent->ld_size, &pevent->ld_offset,
+ "common_lock_depth");
+}
+
+static int parse_common_migrate_disable(struct pevent *pevent, void *data)
+{
+ return __parse_common(pevent, data,
+ &pevent->ld_size, &pevent->ld_offset,
+ "common_migrate_disable");
+}
+
+static int events_id_cmp(const void *a, const void *b);
+
+/**
+ * pevent_find_event - find an event by given id
+ * @pevent: a handle to the pevent
+ * @id: the id of the event
+ *
+ * Returns an event that has a given @id.
+ */
+struct event_format *pevent_find_event(struct pevent *pevent, int id)
+{
+ struct event_format **eventptr;
+ struct event_format key;
+ struct event_format *pkey = &key;
+
+ /* Check cache first */
+ if (pevent->last_event && pevent->last_event->id == id)
+ return pevent->last_event;
+
+ key.id = id;
+
+ eventptr = bsearch(&pkey, pevent->events, pevent->nr_events,
+ sizeof(*pevent->events), events_id_cmp);
+
+ if (eventptr) {
+ pevent->last_event = *eventptr;
+ return *eventptr;
+ }
+
+ return NULL;
+}
+
+/**
+ * pevent_find_event_by_name - find an event by given name
+ * @pevent: a handle to the pevent
+ * @sys: the system name to search for
+ * @name: the name of the event to search for
+ *
+ * This returns an event with a given @name and under the system
+ * @sys. If @sys is NULL the first event with @name is returned.
+ */
+struct event_format *
+pevent_find_event_by_name(struct pevent *pevent,
+ const char *sys, const char *name)
+{
+ struct event_format *event;
+ int i;
+
+ if (pevent->last_event &&
+ strcmp(pevent->last_event->name, name) == 0 &&
+ (!sys || strcmp(pevent->last_event->system, sys) == 0))
+ return pevent->last_event;
+
+ for (i = 0; i < pevent->nr_events; i++) {
+ event = pevent->events[i];
+ if (strcmp(event->name, name) == 0) {
+ if (!sys)
+ break;
+ if (strcmp(event->system, sys) == 0)
+ break;
+ }
+ }
+ if (i == pevent->nr_events)
+ event = NULL;
+
+ pevent->last_event = event;
+ return event;
+}
+
+static unsigned long long
+eval_num_arg(void *data, int size, struct event_format *event, struct print_arg *arg)
+{
+ struct pevent *pevent = event->pevent;
+ unsigned long long val = 0;
+ unsigned long long left, right;
+ struct print_arg *typearg = NULL;
+ struct print_arg *larg;
+ unsigned long offset;
+ unsigned int field_size;
+
+ switch (arg->type) {
+ case PRINT_NULL:
+ /* ?? */
+ return 0;
+ case PRINT_ATOM:
+ return strtoull(arg->atom.atom, NULL, 0);
+ case PRINT_FIELD:
+ if (!arg->field.field) {
+ arg->field.field = pevent_find_any_field(event, arg->field.name);
+ if (!arg->field.field)
+ goto out_warning_field;
+
+ }
+ /* must be a number */
+ val = pevent_read_number(pevent, data + arg->field.field->offset,
+ arg->field.field->size);
+ break;
+ case PRINT_FLAGS:
+ case PRINT_SYMBOL:
+ case PRINT_HEX:
+ break;
+ case PRINT_TYPE:
+ val = eval_num_arg(data, size, event, arg->typecast.item);
+ return eval_type(val, arg, 0);
+ case PRINT_STRING:
+ case PRINT_BSTRING:
+ return 0;
+ case PRINT_FUNC: {
+ struct trace_seq s;
+ trace_seq_init(&s);
+ val = process_defined_func(&s, data, size, event, arg);
+ trace_seq_destroy(&s);
+ return val;
+ }
+ case PRINT_OP:
+ if (strcmp(arg->op.op, "[") == 0) {
+ /*
+ * Arrays are special, since we don't want
+ * to read the arg as is.
+ */
+ right = eval_num_arg(data, size, event, arg->op.right);
+
+ /* handle typecasts */
+ larg = arg->op.left;
+ while (larg->type == PRINT_TYPE) {
+ if (!typearg)
+ typearg = larg;
+ larg = larg->typecast.item;
+ }
+
+ /* Default to long size */
+ field_size = pevent->long_size;
+
+ switch (larg->type) {
+ case PRINT_DYNAMIC_ARRAY:
+ offset = pevent_read_number(pevent,
+ data + larg->dynarray.field->offset,
+ larg->dynarray.field->size);
+ if (larg->dynarray.field->elementsize)
+ field_size = larg->dynarray.field->elementsize;
+ /*
+ * The actual length of the dynamic array is stored
+ * in the top half of the field, and the offset
+ * is in the bottom half of the 32 bit field.
+ */
+ offset &= 0xffff;
+ offset += right;
+ break;
+ case PRINT_FIELD:
+ if (!larg->field.field) {
+ larg->field.field =
+ pevent_find_any_field(event, larg->field.name);
+ if (!larg->field.field) {
+ arg = larg;
+ goto out_warning_field;
+ }
+ }
+ field_size = larg->field.field->elementsize;
+ offset = larg->field.field->offset +
+ right * larg->field.field->elementsize;
+ break;
+ default:
+ goto default_op; /* oops, all bets off */
+ }
+ val = pevent_read_number(pevent,
+ data + offset, field_size);
+ if (typearg)
+ val = eval_type(val, typearg, 1);
+ break;
+ } else if (strcmp(arg->op.op, "?") == 0) {
+ left = eval_num_arg(data, size, event, arg->op.left);
+ arg = arg->op.right;
+ if (left)
+ val = eval_num_arg(data, size, event, arg->op.left);
+ else
+ val = eval_num_arg(data, size, event, arg->op.right);
+ break;
+ }
+ default_op:
+ left = eval_num_arg(data, size, event, arg->op.left);
+ right = eval_num_arg(data, size, event, arg->op.right);
+ switch (arg->op.op[0]) {
+ case '!':
+ switch (arg->op.op[1]) {
+ case 0:
+ val = !right;
+ break;
+ case '=':
+ val = left != right;
+ break;
+ default:
+ goto out_warning_op;
+ }
+ break;
+ case '~':
+ val = ~right;
+ break;
+ case '|':
+ if (arg->op.op[1])
+ val = left || right;
+ else
+ val = left | right;
+ break;
+ case '&':
+ if (arg->op.op[1])
+ val = left && right;
+ else
+ val = left & right;
+ break;
+ case '<':
+ switch (arg->op.op[1]) {
+ case 0:
+ val = left < right;
+ break;
+ case '<':
+ val = left << right;
+ break;
+ case '=':
+ val = left <= right;
+ break;
+ default:
+ goto out_warning_op;
+ }
+ break;
+ case '>':
+ switch (arg->op.op[1]) {
+ case 0:
+ val = left > right;
+ break;
+ case '>':
+ val = left >> right;
+ break;
+ case '=':
+ val = left >= right;
+ break;
+ default:
+ goto out_warning_op;
+ }
+ break;
+ case '=':
+ if (arg->op.op[1] != '=')
+ goto out_warning_op;
+
+ val = left == right;
+ break;
+ case '-':
+ val = left - right;
+ break;
+ case '+':
+ val = left + right;
+ break;
+ case '/':
+ val = left / right;
+ break;
+ case '*':
+ val = left * right;
+ break;
+ default:
+ goto out_warning_op;
+ }
+ break;
+ default: /* not sure what to do there */
+ return 0;
+ }
+ return val;
+
+out_warning_op:
+ do_warning("%s: unknown op '%s'", __func__, arg->op.op);
+ return 0;
+
+out_warning_field:
+ do_warning("%s: field %s not found", __func__, arg->field.name);
+ return 0;
+}
+
+struct flag {
+ const char *name;
+ unsigned long long value;
+};
+
+static const struct flag flags[] = {
+ { "HI_SOFTIRQ", 0 },
+ { "TIMER_SOFTIRQ", 1 },
+ { "NET_TX_SOFTIRQ", 2 },
+ { "NET_RX_SOFTIRQ", 3 },
+ { "BLOCK_SOFTIRQ", 4 },
+ { "BLOCK_IOPOLL_SOFTIRQ", 5 },
+ { "TASKLET_SOFTIRQ", 6 },
+ { "SCHED_SOFTIRQ", 7 },
+ { "HRTIMER_SOFTIRQ", 8 },
+ { "RCU_SOFTIRQ", 9 },
+
+ { "HRTIMER_NORESTART", 0 },
+ { "HRTIMER_RESTART", 1 },
+};
+
+static unsigned long long eval_flag(const char *flag)
+{
+ int i;
+
+ /*
+ * Some flags in the format files do not get converted.
+ * If the flag is not numeric, see if it is something that
+ * we already know about.
+ */
+ if (isdigit(flag[0]))
+ return strtoull(flag, NULL, 0);
+
+ for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); i++)
+ if (strcmp(flags[i].name, flag) == 0)
+ return flags[i].value;
+
+ return 0;
+}
+
+static void print_str_to_seq(struct trace_seq *s, const char *format,
+ int len_arg, const char *str)
+{
+ if (len_arg >= 0)
+ trace_seq_printf(s, format, len_arg, str);
+ else
+ trace_seq_printf(s, format, str);
+}
+
+static void print_str_arg(struct trace_seq *s, void *data, int size,
+ struct event_format *event, const char *format,
+ int len_arg, struct print_arg *arg)
+{
+ struct pevent *pevent = event->pevent;
+ struct print_flag_sym *flag;
+ struct format_field *field;
+ unsigned long long val, fval;
+ unsigned long addr;
+ char *str;
+ unsigned char *hex;
+ int print;
+ int i, len;
+
+ switch (arg->type) {
+ case PRINT_NULL:
+ /* ?? */
+ return;
+ case PRINT_ATOM:
+ print_str_to_seq(s, format, len_arg, arg->atom.atom);
+ return;
+ case PRINT_FIELD:
+ field = arg->field.field;
+ if (!field) {
+ field = pevent_find_any_field(event, arg->field.name);
+ if (!field) {
+ str = arg->field.name;
+ goto out_warning_field;
+ }
+ arg->field.field = field;
+ }
+ /* Zero sized fields, mean the rest of the data */
+ len = field->size ? : size - field->offset;
+
+ /*
+ * Some events pass in pointers. If this is not an array
+ * and the size is the same as long_size, assume that it
+ * is a pointer.
+ */
+ if (!(field->flags & FIELD_IS_ARRAY) &&
+ field->size == pevent->long_size) {
+ addr = *(unsigned long *)(data + field->offset);
+ trace_seq_printf(s, "%lx", addr);
+ break;
+ }
+ str = malloc(len + 1);
+ if (!str) {
+ do_warning("%s: not enough memory!", __func__);
+ return;
+ }
+ memcpy(str, data + field->offset, len);
+ str[len] = 0;
+ print_str_to_seq(s, format, len_arg, str);
+ free(str);
+ break;
+ case PRINT_FLAGS:
+ val = eval_num_arg(data, size, event, arg->flags.field);
+ print = 0;
+ for (flag = arg->flags.flags; flag; flag = flag->next) {
+ fval = eval_flag(flag->value);
+ if (!val && !fval) {
+ print_str_to_seq(s, format, len_arg, flag->str);
+ break;
+ }
+ if (fval && (val & fval) == fval) {
+ if (print && arg->flags.delim)
+ trace_seq_puts(s, arg->flags.delim);
+ print_str_to_seq(s, format, len_arg, flag->str);
+ print = 1;
+ val &= ~fval;
+ }
+ }
+ break;
+ case PRINT_SYMBOL:
+ val = eval_num_arg(data, size, event, arg->symbol.field);
+ for (flag = arg->symbol.symbols; flag; flag = flag->next) {
+ fval = eval_flag(flag->value);
+ if (val == fval) {
+ print_str_to_seq(s, format, len_arg, flag->str);
+ break;
+ }
+ }
+ break;
+ case PRINT_HEX:
+ field = arg->hex.field->field.field;
+ if (!field) {
+ str = arg->hex.field->field.name;
+ field = pevent_find_any_field(event, str);
+ if (!field)
+ goto out_warning_field;
+ arg->hex.field->field.field = field;
+ }
+ hex = data + field->offset;
+ len = eval_num_arg(data, size, event, arg->hex.size);
+ for (i = 0; i < len; i++) {
+ if (i)
+ trace_seq_putc(s, ' ');
+ trace_seq_printf(s, "%02x", hex[i]);
+ }
+ break;
+
+ case PRINT_TYPE:
+ break;
+ case PRINT_STRING: {
+ int str_offset;
+
+ if (arg->string.offset == -1) {
+ struct format_field *f;
+
+ f = pevent_find_any_field(event, arg->string.string);
+ arg->string.offset = f->offset;
+ }
+ str_offset = data2host4(pevent, data + arg->string.offset);
+ str_offset &= 0xffff;
+ print_str_to_seq(s, format, len_arg, ((char *)data) + str_offset);
+ break;
+ }
+ case PRINT_BSTRING:
+ print_str_to_seq(s, format, len_arg, arg->string.string);
+ break;
+ case PRINT_OP:
+ /*
+ * The only op for string should be ? :
+ */
+ if (arg->op.op[0] != '?')
+ return;
+ val = eval_num_arg(data, size, event, arg->op.left);
+ if (val)
+ print_str_arg(s, data, size, event,
+ format, len_arg, arg->op.right->op.left);
+ else
+ print_str_arg(s, data, size, event,
+ format, len_arg, arg->op.right->op.right);
+ break;
+ case PRINT_FUNC:
+ process_defined_func(s, data, size, event, arg);
+ break;
+ default:
+ /* well... */
+ break;
+ }
+
+ return;
+
+out_warning_field:
+ do_warning("%s: field %s not found", __func__, arg->field.name);
+}
+
+static unsigned long long
+process_defined_func(struct trace_seq *s, void *data, int size,
+ struct event_format *event, struct print_arg *arg)
+{
+ struct pevent_function_handler *func_handle = arg->func.func;
+ struct pevent_func_params *param;
+ unsigned long long *args;
+ unsigned long long ret;
+ struct print_arg *farg;
+ struct trace_seq str;
+ struct save_str {
+ struct save_str *next;
+ char *str;
+ } *strings = NULL, *string;
+ int i;
+
+ if (!func_handle->nr_args) {
+ ret = (*func_handle->func)(s, NULL);
+ goto out;
+ }
+
+ farg = arg->func.args;
+ param = func_handle->params;
+
+ ret = ULLONG_MAX;
+ args = malloc(sizeof(*args) * func_handle->nr_args);
+ if (!args)
+ goto out;
+
+ for (i = 0; i < func_handle->nr_args; i++) {
+ switch (param->type) {
+ case PEVENT_FUNC_ARG_INT:
+ case PEVENT_FUNC_ARG_LONG:
+ case PEVENT_FUNC_ARG_PTR:
+ args[i] = eval_num_arg(data, size, event, farg);
+ break;
+ case PEVENT_FUNC_ARG_STRING:
+ trace_seq_init(&str);
+ print_str_arg(&str, data, size, event, "%s", -1, farg);
+ trace_seq_terminate(&str);
+ string = malloc(sizeof(*string));
+ if (!string) {
+ do_warning("%s(%d): malloc str", __func__, __LINE__);
+ goto out_free;
+ }
+ string->next = strings;
+ string->str = strdup(str.buffer);
+ if (!string->str) {
+ free(string);
+ do_warning("%s(%d): malloc str", __func__, __LINE__);
+ goto out_free;
+ }
+ args[i] = (uintptr_t)string->str;
+ strings = string;
+ trace_seq_destroy(&str);
+ break;
+ default:
+ /*
+ * Something went totally wrong, this is not
+ * an input error, something in this code broke.
+ */
+ do_warning("Unexpected end of arguments\n");
+ goto out_free;
+ }
+ farg = farg->next;
+ param = param->next;
+ }
+
+ ret = (*func_handle->func)(s, args);
+out_free:
+ free(args);
+ while (strings) {
+ string = strings;
+ strings = string->next;
+ free(string->str);
+ free(string);
+ }
+
+ out:
+ /* TBD : handle return type here */
+ return ret;
+}
+
+static void free_args(struct print_arg *args)
+{
+ struct print_arg *next;
+
+ while (args) {
+ next = args->next;
+
+ free_arg(args);
+ args = next;
+ }
+}
+
+static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struct event_format *event)
+{
+ struct pevent *pevent = event->pevent;
+ struct format_field *field, *ip_field;
+ struct print_arg *args, *arg, **next;
+ unsigned long long ip, val;
+ char *ptr;
+ void *bptr;
+ int vsize;
+
+ field = pevent->bprint_buf_field;
+ ip_field = pevent->bprint_ip_field;
+
+ if (!field) {
+ field = pevent_find_field(event, "buf");
+ if (!field) {
+ do_warning("can't find buffer field for binary printk");
+ return NULL;
+ }
+ ip_field = pevent_find_field(event, "ip");
+ if (!ip_field) {
+ do_warning("can't find ip field for binary printk");
+ return NULL;
+ }
+ pevent->bprint_buf_field = field;
+ pevent->bprint_ip_field = ip_field;
+ }
+
+ ip = pevent_read_number(pevent, data + ip_field->offset, ip_field->size);
+
+ /*
+ * The first arg is the IP pointer.
+ */
+ args = alloc_arg();
+ if (!args) {
+ do_warning("%s(%d): not enough memory!", __func__, __LINE__);
+ return NULL;
+ }
+ arg = args;
+ arg->next = NULL;
+ next = &arg->next;
+
+ arg->type = PRINT_ATOM;
+
+ if (asprintf(&arg->atom.atom, "%lld", ip) < 0)
+ goto out_free;
+
+ /* skip the first "%pf : " */
+ for (ptr = fmt + 6, bptr = data + field->offset;
+ bptr < data + size && *ptr; ptr++) {
+ int ls = 0;
+
+ if (*ptr == '%') {
+ process_again:
+ ptr++;
+ switch (*ptr) {
+ case '%':
+ break;
+ case 'l':
+ ls++;
+ goto process_again;
+ case 'L':
+ ls = 2;
+ goto process_again;
+ case '0' ... '9':
+ goto process_again;
+ case '.':
+ goto process_again;
+ case 'p':
+ ls = 1;
+ /* fall through */
+ case 'd':
+ case 'u':
+ case 'x':
+ case 'i':
+ switch (ls) {
+ case 0:
+ vsize = 4;
+ break;
+ case 1:
+ vsize = pevent->long_size;
+ break;
+ case 2:
+ vsize = 8;
+ break;
+ default:
+ vsize = ls; /* ? */
+ break;
+ }
+ /* fall through */
+ case '*':
+ if (*ptr == '*')
+ vsize = 4;
+
+ /* the pointers are always 4 bytes aligned */
+ bptr = (void *)(((unsigned long)bptr + 3) &
+ ~3);
+ val = pevent_read_number(pevent, bptr, vsize);
+ bptr += vsize;
+ arg = alloc_arg();
+ if (!arg) {
+ do_warning("%s(%d): not enough memory!",
+ __func__, __LINE__);
+ goto out_free;
+ }
+ arg->next = NULL;
+ arg->type = PRINT_ATOM;
+ if (asprintf(&arg->atom.atom, "%lld", val) < 0) {
+ free(arg);
+ goto out_free;
+ }
+ *next = arg;
+ next = &arg->next;
+ /*
+ * The '*' case means that an arg is used as the length.
+ * We need to continue to figure out for what.
+ */
+ if (*ptr == '*')
+ goto process_again;
+
+ break;
+ case 's':
+ arg = alloc_arg();
+ if (!arg) {
+ do_warning("%s(%d): not enough memory!",
+ __func__, __LINE__);
+ goto out_free;
+ }
+ arg->next = NULL;
+ arg->type = PRINT_BSTRING;
+ arg->string.string = strdup(bptr);
+ if (!arg->string.string)
+ goto out_free;
+ bptr += strlen(bptr) + 1;
+ *next = arg;
+ next = &arg->next;
+ default:
+ break;
+ }
+ }
+ }
+
+ return args;
+
+out_free:
+ free_args(args);
+ return NULL;
+}
+
+static char *
+get_bprint_format(void *data, int size __maybe_unused,
+ struct event_format *event)
+{
+ struct pevent *pevent = event->pevent;
+ unsigned long long addr;
+ struct format_field *field;
+ struct printk_map *printk;
+ char *format;
+ char *p;
+
+ field = pevent->bprint_fmt_field;
+
+ if (!field) {
+ field = pevent_find_field(event, "fmt");
+ if (!field) {
+ do_warning("can't find format field for binary printk");
+ return NULL;
+ }
+ pevent->bprint_fmt_field = field;
+ }
+
+ addr = pevent_read_number(pevent, data + field->offset, field->size);
+
+ printk = find_printk(pevent, addr);
+ if (!printk) {
+ if (asprintf(&format, "%%pf : (NO FORMAT FOUND at %llx)\n", addr) < 0)
+ return NULL;
+ return format;
+ }
+
+ p = printk->printk;
+ /* Remove any quotes. */
+ if (*p == '"')
+ p++;
+ if (asprintf(&format, "%s : %s", "%pf", p) < 0)
+ return NULL;
+ /* remove ending quotes and new line since we will add one too */
+ p = format + strlen(format) - 1;
+ if (*p == '"')
+ *p = 0;
+
+ p -= 2;
+ if (strcmp(p, "\\n") == 0)
+ *p = 0;
+
+ return format;
+}
+
+static void print_mac_arg(struct trace_seq *s, int mac, void *data, int size,
+ struct event_format *event, struct print_arg *arg)
+{
+ unsigned char *buf;
+ const char *fmt = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x";
+
+ if (arg->type == PRINT_FUNC) {
+ process_defined_func(s, data, size, event, arg);
+ return;
+ }
+
+ if (arg->type != PRINT_FIELD) {
+ trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d",
+ arg->type);
+ return;
+ }
+
+ if (mac == 'm')
+ fmt = "%.2x%.2x%.2x%.2x%.2x%.2x";
+ if (!arg->field.field) {
+ arg->field.field =
+ pevent_find_any_field(event, arg->field.name);
+ if (!arg->field.field) {
+ do_warning("%s: field %s not found",
+ __func__, arg->field.name);
+ return;
+ }
+ }
+ if (arg->field.field->size != 6) {
+ trace_seq_printf(s, "INVALIDMAC");
+ return;
+ }
+ buf = data + arg->field.field->offset;
+ trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
+}
+
+static int is_printable_array(char *p, unsigned int len)
+{
+ unsigned int i;
+
+ for (i = 0; i < len && p[i]; i++)
+ if (!isprint(p[i]))
+ return 0;
+ return 1;
+}
+
+static void print_event_fields(struct trace_seq *s, void *data,
+ int size __maybe_unused,
+ struct event_format *event)
+{
+ struct format_field *field;
+ unsigned long long val;
+ unsigned int offset, len, i;
+
+ field = event->format.fields;
+ while (field) {
+ trace_seq_printf(s, " %s=", field->name);
+ if (field->flags & FIELD_IS_ARRAY) {
+ offset = field->offset;
+ len = field->size;
+ if (field->flags & FIELD_IS_DYNAMIC) {
+ val = pevent_read_number(event->pevent, data + offset, len);
+ offset = val;
+ len = offset >> 16;
+ offset &= 0xffff;
+ }
+ if (field->flags & FIELD_IS_STRING &&
+ is_printable_array(data + offset, len)) {
+ trace_seq_printf(s, "%s", (char *)data + offset);
+ } else {
+ trace_seq_puts(s, "ARRAY[");
+ for (i = 0; i < len; i++) {
+ if (i)
+ trace_seq_puts(s, ", ");
+ trace_seq_printf(s, "%02x",
+ *((unsigned char *)data + offset + i));
+ }
+ trace_seq_putc(s, ']');
+ field->flags &= ~FIELD_IS_STRING;
+ }
+ } else {
+ val = pevent_read_number(event->pevent, data + field->offset,
+ field->size);
+ if (field->flags & FIELD_IS_POINTER) {
+ trace_seq_printf(s, "0x%llx", val);
+ } else if (field->flags & FIELD_IS_SIGNED) {
+ switch (field->size) {
+ case 4:
+ /*
+ * If field is long then print it in hex.
+ * A long usually stores pointers.
+ */
+ if (field->flags & FIELD_IS_LONG)
+ trace_seq_printf(s, "0x%x", (int)val);
+ else
+ trace_seq_printf(s, "%d", (int)val);
+ break;
+ case 2:
+ trace_seq_printf(s, "%2d", (short)val);
+ break;
+ case 1:
+ trace_seq_printf(s, "%1d", (char)val);
+ break;
+ default:
+ trace_seq_printf(s, "%lld", val);
+ }
+ } else {
+ if (field->flags & FIELD_IS_LONG)
+ trace_seq_printf(s, "0x%llx", val);
+ else
+ trace_seq_printf(s, "%llu", val);
+ }
+ }
+ field = field->next;
+ }
+}
+
+static void pretty_print(struct trace_seq *s, void *data, int size, struct event_format *event)
+{
+ struct pevent *pevent = event->pevent;
+ struct print_fmt *print_fmt = &event->print_fmt;
+ struct print_arg *arg = print_fmt->args;
+ struct print_arg *args = NULL;
+ const char *ptr = print_fmt->format;
+ unsigned long long val;
+ struct func_map *func;
+ const char *saveptr;
+ char *bprint_fmt = NULL;
+ char format[32];
+ int show_func;
+ int len_as_arg;
+ int len_arg;
+ int len;
+ int ls;
+
+ if (event->flags & EVENT_FL_FAILED) {
+ trace_seq_printf(s, "[FAILED TO PARSE]");
+ print_event_fields(s, data, size, event);
+ return;
+ }
+
+ if (event->flags & EVENT_FL_ISBPRINT) {
+ bprint_fmt = get_bprint_format(data, size, event);
+ args = make_bprint_args(bprint_fmt, data, size, event);
+ arg = args;
+ ptr = bprint_fmt;
+ }
+
+ for (; *ptr; ptr++) {
+ ls = 0;
+ if (*ptr == '\\') {
+ ptr++;
+ switch (*ptr) {
+ case 'n':
+ trace_seq_putc(s, '\n');
+ break;
+ case 't':
+ trace_seq_putc(s, '\t');
+ break;
+ case 'r':
+ trace_seq_putc(s, '\r');
+ break;
+ case '\\':
+ trace_seq_putc(s, '\\');
+ break;
+ default:
+ trace_seq_putc(s, *ptr);
+ break;
+ }
+
+ } else if (*ptr == '%') {
+ saveptr = ptr;
+ show_func = 0;
+ len_as_arg = 0;
+ cont_process:
+ ptr++;
+ switch (*ptr) {
+ case '%':
+ trace_seq_putc(s, '%');
+ break;
+ case '#':
+ /* FIXME: need to handle properly */
+ goto cont_process;
+ case 'h':
+ ls--;
+ goto cont_process;
+ case 'l':
+ ls++;
+ goto cont_process;
+ case 'L':
+ ls = 2;
+ goto cont_process;
+ case '*':
+ /* The argument is the length. */
+ if (!arg) {
+ do_warning("no argument match");
+ event->flags |= EVENT_FL_FAILED;
+ goto out_failed;
+ }
+ len_arg = eval_num_arg(data, size, event, arg);
+ len_as_arg = 1;
+ arg = arg->next;
+ goto cont_process;
+ case '.':
+ case 'z':
+ case 'Z':
+ case '0' ... '9':
+ goto cont_process;
+ case 'p':
+ if (pevent->long_size == 4)
+ ls = 1;
+ else
+ ls = 2;
+
+ if (*(ptr+1) == 'F' ||
+ *(ptr+1) == 'f') {
+ ptr++;
+ show_func = *ptr;
+ } else if (*(ptr+1) == 'M' || *(ptr+1) == 'm') {
+ print_mac_arg(s, *(ptr+1), data, size, event, arg);
+ ptr++;
+ arg = arg->next;
+ break;
+ }
+
+ /* fall through */
+ case 'd':
+ case 'i':
+ case 'x':
+ case 'X':
+ case 'u':
+ if (!arg) {
+ do_warning("no argument match");
+ event->flags |= EVENT_FL_FAILED;
+ goto out_failed;
+ }
+
+ len = ((unsigned long)ptr + 1) -
+ (unsigned long)saveptr;
+
+ /* should never happen */
+ if (len > 31) {
+ do_warning("bad format!");
+ event->flags |= EVENT_FL_FAILED;
+ len = 31;
+ }
+
+ memcpy(format, saveptr, len);
+ format[len] = 0;
+
+ val = eval_num_arg(data, size, event, arg);
+ arg = arg->next;
+
+ if (show_func) {
+ func = find_func(pevent, val);
+ if (func) {
+ trace_seq_puts(s, func->func);
+ if (show_func == 'F')
+ trace_seq_printf(s,
+ "+0x%llx",
+ val - func->addr);
+ break;
+ }
+ }
+ if (pevent->long_size == 8 && ls &&
+ sizeof(long) != 8) {
+ char *p;
+
+ ls = 2;
+ /* make %l into %ll */
+ p = strchr(format, 'l');
+ if (p)
+ memmove(p+1, p, strlen(p)+1);
+ else if (strcmp(format, "%p") == 0)
+ strcpy(format, "0x%llx");
+ }
+ switch (ls) {
+ case -2:
+ if (len_as_arg)
+ trace_seq_printf(s, format, len_arg, (char)val);
+ else
+ trace_seq_printf(s, format, (char)val);
+ break;
+ case -1:
+ if (len_as_arg)
+ trace_seq_printf(s, format, len_arg, (short)val);
+ else
+ trace_seq_printf(s, format, (short)val);
+ break;
+ case 0:
+ if (len_as_arg)
+ trace_seq_printf(s, format, len_arg, (int)val);
+ else
+ trace_seq_printf(s, format, (int)val);
+ break;
+ case 1:
+ if (len_as_arg)
+ trace_seq_printf(s, format, len_arg, (long)val);
+ else
+ trace_seq_printf(s, format, (long)val);
+ break;
+ case 2:
+ if (len_as_arg)
+ trace_seq_printf(s, format, len_arg,
+ (long long)val);
+ else
+ trace_seq_printf(s, format, (long long)val);
+ break;
+ default:
+ do_warning("bad count (%d)", ls);
+ event->flags |= EVENT_FL_FAILED;
+ }
+ break;
+ case 's':
+ if (!arg) {
+ do_warning("no matching argument");
+ event->flags |= EVENT_FL_FAILED;
+ goto out_failed;
+ }
+
+ len = ((unsigned long)ptr + 1) -
+ (unsigned long)saveptr;
+
+ /* should never happen */
+ if (len > 31) {
+ do_warning("bad format!");
+ event->flags |= EVENT_FL_FAILED;
+ len = 31;
+ }
+
+ memcpy(format, saveptr, len);
+ format[len] = 0;
+ if (!len_as_arg)
+ len_arg = -1;
+ print_str_arg(s, data, size, event,
+ format, len_arg, arg);
+ arg = arg->next;
+ break;
+ default:
+ trace_seq_printf(s, ">%c<", *ptr);
+
+ }
+ } else
+ trace_seq_putc(s, *ptr);
+ }
+
+ if (event->flags & EVENT_FL_FAILED) {
+out_failed:
+ trace_seq_printf(s, "[FAILED TO PARSE]");
+ }
+
+ if (args) {
+ free_args(args);
+ free(bprint_fmt);
+ }
+}
+
+/**
+ * pevent_data_lat_fmt - parse the data for the latency format
+ * @pevent: a handle to the pevent
+ * @s: the trace_seq to write to
+ * @record: the record to read from
+ *
+ * This parses out the Latency format (interrupts disabled,
+ * need rescheduling, in hard/soft interrupt, preempt count
+ * and lock depth) and places it into the trace_seq.
+ */
+void pevent_data_lat_fmt(struct pevent *pevent,
+ struct trace_seq *s, struct pevent_record *record)
+{
+ static int check_lock_depth = 1;
+ static int check_migrate_disable = 1;
+ static int lock_depth_exists;
+ static int migrate_disable_exists;
+ unsigned int lat_flags;
+ unsigned int pc;
+ int lock_depth;
+ int migrate_disable;
+ int hardirq;
+ int softirq;
+ void *data = record->data;
+
+ lat_flags = parse_common_flags(pevent, data);
+ pc = parse_common_pc(pevent, data);
+ /* lock_depth may not always exist */
+ if (lock_depth_exists)
+ lock_depth = parse_common_lock_depth(pevent, data);
+ else if (check_lock_depth) {
+ lock_depth = parse_common_lock_depth(pevent, data);
+ if (lock_depth < 0)
+ check_lock_depth = 0;
+ else
+ lock_depth_exists = 1;
+ }
+
+ /* migrate_disable may not always exist */
+ if (migrate_disable_exists)
+ migrate_disable = parse_common_migrate_disable(pevent, data);
+ else if (check_migrate_disable) {
+ migrate_disable = parse_common_migrate_disable(pevent, data);
+ if (migrate_disable < 0)
+ check_migrate_disable = 0;
+ else
+ migrate_disable_exists = 1;
+ }
+
+ hardirq = lat_flags & TRACE_FLAG_HARDIRQ;
+ softirq = lat_flags & TRACE_FLAG_SOFTIRQ;
+
+ trace_seq_printf(s, "%c%c%c",
+ (lat_flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
+ (lat_flags & TRACE_FLAG_IRQS_NOSUPPORT) ?
+ 'X' : '.',
+ (lat_flags & TRACE_FLAG_NEED_RESCHED) ?
+ 'N' : '.',
+ (hardirq && softirq) ? 'H' :
+ hardirq ? 'h' : softirq ? 's' : '.');
+
+ if (pc)
+ trace_seq_printf(s, "%x", pc);
+ else
+ trace_seq_putc(s, '.');
+
+ if (migrate_disable_exists) {
+ if (migrate_disable < 0)
+ trace_seq_putc(s, '.');
+ else
+ trace_seq_printf(s, "%d", migrate_disable);
+ }
+
+ if (lock_depth_exists) {
+ if (lock_depth < 0)
+ trace_seq_putc(s, '.');
+ else
+ trace_seq_printf(s, "%d", lock_depth);
+ }
+
+ trace_seq_terminate(s);
+}
+
+/**
+ * pevent_data_type - parse out the given event type
+ * @pevent: a handle to the pevent
+ * @rec: the record to read from
+ *
+ * This returns the event id from the @rec.
+ */
+int pevent_data_type(struct pevent *pevent, struct pevent_record *rec)
+{
+ return trace_parse_common_type(pevent, rec->data);
+}
+
+/**
+ * pevent_data_event_from_type - find the event by a given type
+ * @pevent: a handle to the pevent
+ * @type: the type of the event.
+ *
+ * This returns the event form a given @type;
+ */
+struct event_format *pevent_data_event_from_type(struct pevent *pevent, int type)
+{
+ return pevent_find_event(pevent, type);
+}
+
+/**
+ * pevent_data_pid - parse the PID from raw data
+ * @pevent: a handle to the pevent
+ * @rec: the record to parse
+ *
+ * This returns the PID from a raw data.
+ */
+int pevent_data_pid(struct pevent *pevent, struct pevent_record *rec)
+{
+ return parse_common_pid(pevent, rec->data);
+}
+
+/**
+ * pevent_data_comm_from_pid - return the command line from PID
+ * @pevent: a handle to the pevent
+ * @pid: the PID of the task to search for
+ *
+ * This returns a pointer to the command line that has the given
+ * @pid.
+ */
+const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid)
+{
+ const char *comm;
+
+ comm = find_cmdline(pevent, pid);
+ return comm;
+}
+
+/**
+ * pevent_data_comm_from_pid - parse the data into the print format
+ * @s: the trace_seq to write to
+ * @event: the handle to the event
+ * @record: the record to read from
+ *
+ * This parses the raw @data using the given @event information and
+ * writes the print format into the trace_seq.
+ */
+void pevent_event_info(struct trace_seq *s, struct event_format *event,
+ struct pevent_record *record)
+{
+ int print_pretty = 1;
+
+ if (event->pevent->print_raw)
+ print_event_fields(s, record->data, record->size, event);
+ else {
+
+ if (event->handler)
+ print_pretty = event->handler(s, record, event,
+ event->context);
+
+ if (print_pretty)
+ pretty_print(s, record->data, record->size, event);
+ }
+
+ trace_seq_terminate(s);
+}
+
+void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
+ struct pevent_record *record)
+{
+ static const char *spaces = " "; /* 20 spaces */
+ struct event_format *event;
+ unsigned long secs;
+ unsigned long usecs;
+ unsigned long nsecs;
+ const char *comm;
+ void *data = record->data;
+ int type;
+ int pid;
+ int len;
+ int p;
+
+ secs = record->ts / NSECS_PER_SEC;
+ nsecs = record->ts - secs * NSECS_PER_SEC;
+
+ if (record->size < 0) {
+ do_warning("ug! negative record size %d", record->size);
+ return;
+ }
+
+ type = trace_parse_common_type(pevent, data);
+
+ event = pevent_find_event(pevent, type);
+ if (!event) {
+ do_warning("ug! no event found for type %d", type);
+ return;
+ }
+
+ pid = parse_common_pid(pevent, data);
+ comm = find_cmdline(pevent, pid);
+
+ if (pevent->latency_format) {
+ trace_seq_printf(s, "%8.8s-%-5d %3d",
+ comm, pid, record->cpu);
+ pevent_data_lat_fmt(pevent, s, record);
+ } else
+ trace_seq_printf(s, "%16s-%-5d [%03d]", comm, pid, record->cpu);
+
+ if (pevent->flags & PEVENT_NSEC_OUTPUT) {
+ usecs = nsecs;
+ p = 9;
+ } else {
+ usecs = (nsecs + 500) / NSECS_PER_USEC;
+ p = 6;
+ }
+
+ trace_seq_printf(s, " %5lu.%0*lu: %s: ", secs, p, usecs, event->name);
+
+ /* Space out the event names evenly. */
+ len = strlen(event->name);
+ if (len < 20)
+ trace_seq_printf(s, "%.*s", 20 - len, spaces);
+
+ pevent_event_info(s, event, record);
+}
+
+static int events_id_cmp(const void *a, const void *b)
+{
+ struct event_format * const * ea = a;
+ struct event_format * const * eb = b;
+
+ if ((*ea)->id < (*eb)->id)
+ return -1;
+
+ if ((*ea)->id > (*eb)->id)
+ return 1;
+
+ return 0;
+}
+
+static int events_name_cmp(const void *a, const void *b)
+{
+ struct event_format * const * ea = a;
+ struct event_format * const * eb = b;
+ int res;
+
+ res = strcmp((*ea)->name, (*eb)->name);
+ if (res)
+ return res;
+
+ res = strcmp((*ea)->system, (*eb)->system);
+ if (res)
+ return res;
+
+ return events_id_cmp(a, b);
+}
+
+static int events_system_cmp(const void *a, const void *b)
+{
+ struct event_format * const * ea = a;
+ struct event_format * const * eb = b;
+ int res;
+
+ res = strcmp((*ea)->system, (*eb)->system);
+ if (res)
+ return res;
+
+ res = strcmp((*ea)->name, (*eb)->name);
+ if (res)
+ return res;
+
+ return events_id_cmp(a, b);
+}
+
+struct event_format **pevent_list_events(struct pevent *pevent, enum event_sort_type sort_type)
+{
+ struct event_format **events;
+ int (*sort)(const void *a, const void *b);
+
+ events = pevent->sort_events;
+
+ if (events && pevent->last_type == sort_type)
+ return events;
+
+ if (!events) {
+ events = malloc(sizeof(*events) * (pevent->nr_events + 1));
+ if (!events)
+ return NULL;
+
+ memcpy(events, pevent->events, sizeof(*events) * pevent->nr_events);
+ events[pevent->nr_events] = NULL;
+
+ pevent->sort_events = events;
+
+ /* the internal events are sorted by id */
+ if (sort_type == EVENT_SORT_ID) {
+ pevent->last_type = sort_type;
+ return events;
+ }
+ }
+
+ switch (sort_type) {
+ case EVENT_SORT_ID:
+ sort = events_id_cmp;
+ break;
+ case EVENT_SORT_NAME:
+ sort = events_name_cmp;
+ break;
+ case EVENT_SORT_SYSTEM:
+ sort = events_system_cmp;
+ break;
+ default:
+ return events;
+ }
+
+ qsort(events, pevent->nr_events, sizeof(*events), sort);
+ pevent->last_type = sort_type;
+
+ return events;
+}
+
+static struct format_field **
+get_event_fields(const char *type, const char *name,
+ int count, struct format_field *list)
+{
+ struct format_field **fields;
+ struct format_field *field;
+ int i = 0;
+
+ fields = malloc(sizeof(*fields) * (count + 1));
+ if (!fields)
+ return NULL;
+
+ for (field = list; field; field = field->next) {
+ fields[i++] = field;
+ if (i == count + 1) {
+ do_warning("event %s has more %s fields than specified",
+ name, type);
+ i--;
+ break;
+ }
+ }
+
+ if (i != count)
+ do_warning("event %s has less %s fields than specified",
+ name, type);
+
+ fields[i] = NULL;
+
+ return fields;
+}
+
+/**
+ * pevent_event_common_fields - return a list of common fields for an event
+ * @event: the event to return the common fields of.
+ *
+ * Returns an allocated array of fields. The last item in the array is NULL.
+ * The array must be freed with free().
+ */
+struct format_field **pevent_event_common_fields(struct event_format *event)
+{
+ return get_event_fields("common", event->name,
+ event->format.nr_common,
+ event->format.common_fields);
+}
+
+/**
+ * pevent_event_fields - return a list of event specific fields for an event
+ * @event: the event to return the fields of.
+ *
+ * Returns an allocated array of fields. The last item in the array is NULL.
+ * The array must be freed with free().
+ */
+struct format_field **pevent_event_fields(struct event_format *event)
+{
+ return get_event_fields("event", event->name,
+ event->format.nr_fields,
+ event->format.fields);
+}
+
+static void print_fields(struct trace_seq *s, struct print_flag_sym *field)
+{
+ trace_seq_printf(s, "{ %s, %s }", field->value, field->str);
+ if (field->next) {
+ trace_seq_puts(s, ", ");
+ print_fields(s, field->next);
+ }
+}
+
+/* for debugging */
+static void print_args(struct print_arg *args)
+{
+ int print_paren = 1;
+ struct trace_seq s;
+
+ switch (args->type) {
+ case PRINT_NULL:
+ printf("null");
+ break;
+ case PRINT_ATOM:
+ printf("%s", args->atom.atom);
+ break;
+ case PRINT_FIELD:
+ printf("REC->%s", args->field.name);
+ break;
+ case PRINT_FLAGS:
+ printf("__print_flags(");
+ print_args(args->flags.field);
+ printf(", %s, ", args->flags.delim);
+ trace_seq_init(&s);
+ print_fields(&s, args->flags.flags);
+ trace_seq_do_printf(&s);
+ trace_seq_destroy(&s);
+ printf(")");
+ break;
+ case PRINT_SYMBOL:
+ printf("__print_symbolic(");
+ print_args(args->symbol.field);
+ printf(", ");
+ trace_seq_init(&s);
+ print_fields(&s, args->symbol.symbols);
+ trace_seq_do_printf(&s);
+ trace_seq_destroy(&s);
+ printf(")");
+ break;
+ case PRINT_HEX:
+ printf("__print_hex(");
+ print_args(args->hex.field);
+ printf(", ");
+ print_args(args->hex.size);
+ printf(")");
+ break;
+ case PRINT_STRING:
+ case PRINT_BSTRING:
+ printf("__get_str(%s)", args->string.string);
+ break;
+ case PRINT_TYPE:
+ printf("(%s)", args->typecast.type);
+ print_args(args->typecast.item);
+ break;
+ case PRINT_OP:
+ if (strcmp(args->op.op, ":") == 0)
+ print_paren = 0;
+ if (print_paren)
+ printf("(");
+ print_args(args->op.left);
+ printf(" %s ", args->op.op);
+ print_args(args->op.right);
+ if (print_paren)
+ printf(")");
+ break;
+ default:
+ /* we should warn... */
+ return;
+ }
+ if (args->next) {
+ printf("\n");
+ print_args(args->next);
+ }
+}
+
+static void parse_header_field(const char *field,
+ int *offset, int *size, int mandatory)
+{
+ unsigned long long save_input_buf_ptr;
+ unsigned long long save_input_buf_siz;
+ char *token;
+ int type;
+
+ save_input_buf_ptr = input_buf_ptr;
+ save_input_buf_siz = input_buf_siz;
+
+ if (read_expected(EVENT_ITEM, "field") < 0)
+ return;
+ if (read_expected(EVENT_OP, ":") < 0)
+ return;
+
+ /* type */
+ if (read_expect_type(EVENT_ITEM, &token) < 0)
+ goto fail;
+ free_token(token);
+
+ /*
+ * If this is not a mandatory field, then test it first.
+ */
+ if (mandatory) {
+ if (read_expected(EVENT_ITEM, field) < 0)
+ return;
+ } else {
+ if (read_expect_type(EVENT_ITEM, &token) < 0)
+ goto fail;
+ if (strcmp(token, field) != 0)
+ goto discard;
+ free_token(token);
+ }
+
+ if (read_expected(EVENT_OP, ";") < 0)
+ return;
+ if (read_expected(EVENT_ITEM, "offset") < 0)
+ return;
+ if (read_expected(EVENT_OP, ":") < 0)
+ return;
+ if (read_expect_type(EVENT_ITEM, &token) < 0)
+ goto fail;
+ *offset = atoi(token);
+ free_token(token);
+ if (read_expected(EVENT_OP, ";") < 0)
+ return;
+ if (read_expected(EVENT_ITEM, "size") < 0)
+ return;
+ if (read_expected(EVENT_OP, ":") < 0)
+ return;
+ if (read_expect_type(EVENT_ITEM, &token) < 0)
+ goto fail;
+ *size = atoi(token);
+ free_token(token);
+ if (read_expected(EVENT_OP, ";") < 0)
+ return;
+ type = read_token(&token);
+ if (type != EVENT_NEWLINE) {
+ /* newer versions of the kernel have a "signed" type */
+ if (type != EVENT_ITEM)
+ goto fail;
+
+ if (strcmp(token, "signed") != 0)
+ goto fail;
+
+ free_token(token);
+
+ if (read_expected(EVENT_OP, ":") < 0)
+ return;
+
+ if (read_expect_type(EVENT_ITEM, &token))
+ goto fail;
+
+ free_token(token);
+ if (read_expected(EVENT_OP, ";") < 0)
+ return;
+
+ if (read_expect_type(EVENT_NEWLINE, &token))
+ goto fail;
+ }
+ fail:
+ free_token(token);
+ return;
+
+ discard:
+ input_buf_ptr = save_input_buf_ptr;
+ input_buf_siz = save_input_buf_siz;
+ *offset = 0;
+ *size = 0;
+ free_token(token);
+}
+
+/**
+ * pevent_parse_header_page - parse the data stored in the header page
+ * @pevent: the handle to the pevent
+ * @buf: the buffer storing the header page format string
+ * @size: the size of @buf
+ * @long_size: the long size to use if there is no header
+ *
+ * This parses the header page format for information on the
+ * ring buffer used. The @buf should be copied from
+ *
+ * /sys/kernel/debug/tracing/events/header_page
+ */
+int pevent_parse_header_page(struct pevent *pevent, char *buf, unsigned long size,
+ int long_size)
+{
+ int ignore;
+
+ if (!size) {
+ /*
+ * Old kernels did not have header page info.
+ * Sorry but we just use what we find here in user space.
+ */
+ pevent->header_page_ts_size = sizeof(long long);
+ pevent->header_page_size_size = long_size;
+ pevent->header_page_data_offset = sizeof(long long) + long_size;
+ pevent->old_format = 1;
+ return -1;
+ }
+ init_input_buf(buf, size);
+
+ parse_header_field("timestamp", &pevent->header_page_ts_offset,
+ &pevent->header_page_ts_size, 1);
+ parse_header_field("commit", &pevent->header_page_size_offset,
+ &pevent->header_page_size_size, 1);
+ parse_header_field("overwrite", &pevent->header_page_overwrite,
+ &ignore, 0);
+ parse_header_field("data", &pevent->header_page_data_offset,
+ &pevent->header_page_data_size, 1);
+
+ return 0;
+}
+
+static int event_matches(struct event_format *event,
+ int id, const char *sys_name,
+ const char *event_name)
+{
+ if (id >= 0 && id != event->id)
+ return 0;
+
+ if (event_name && (strcmp(event_name, event->name) != 0))
+ return 0;
+
+ if (sys_name && (strcmp(sys_name, event->system) != 0))
+ return 0;
+
+ return 1;
+}
+
+static void free_handler(struct event_handler *handle)
+{
+ free((void *)handle->sys_name);
+ free((void *)handle->event_name);
+ free(handle);
+}
+
+static int find_event_handle(struct pevent *pevent, struct event_format *event)
+{
+ struct event_handler *handle, **next;
+
+ for (next = &pevent->handlers; *next;
+ next = &(*next)->next) {
+ handle = *next;
+ if (event_matches(event, handle->id,
+ handle->sys_name,
+ handle->event_name))
+ break;
+ }
+
+ if (!(*next))
+ return 0;
+
+ pr_stat("overriding event (%d) %s:%s with new print handler",
+ event->id, event->system, event->name);
+
+ event->handler = handle->func;
+ event->context = handle->context;
+
+ *next = handle->next;
+ free_handler(handle);
+
+ return 1;
+}
+
+/**
+ * __pevent_parse_format - parse the event format
+ * @buf: the buffer storing the event format string
+ * @size: the size of @buf
+ * @sys: the system the event belongs to
+ *
+ * This parses the event format and creates an event structure
+ * to quickly parse raw data for a given event.
+ *
+ * These files currently come from:
+ *
+ * /sys/kernel/debug/tracing/events/.../.../format
+ */
+enum pevent_errno __pevent_parse_format(struct event_format **eventp,
+ struct pevent *pevent, const char *buf,
+ unsigned long size, const char *sys)
+{
+ struct event_format *event;
+ int ret;
+
+ init_input_buf(buf, size);
+
+ *eventp = event = alloc_event();
+ if (!event)
+ return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+
+ event->name = event_read_name();
+ if (!event->name) {
+ /* Bad event? */
+ ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
+ goto event_alloc_failed;
+ }
+
+ if (strcmp(sys, "ftrace") == 0) {
+ event->flags |= EVENT_FL_ISFTRACE;
+
+ if (strcmp(event->name, "bprint") == 0)
+ event->flags |= EVENT_FL_ISBPRINT;
+ }
+
+ event->id = event_read_id();
+ if (event->id < 0) {
+ ret = PEVENT_ERRNO__READ_ID_FAILED;
+ /*
+ * This isn't an allocation error actually.
+ * But as the ID is critical, just bail out.
+ */
+ goto event_alloc_failed;
+ }
+
+ event->system = strdup(sys);
+ if (!event->system) {
+ ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
+ goto event_alloc_failed;
+ }
+
+ /* Add pevent to event so that it can be referenced */
+ event->pevent = pevent;
+
+ ret = event_read_format(event);
+ if (ret < 0) {
+ ret = PEVENT_ERRNO__READ_FORMAT_FAILED;
+ goto event_parse_failed;
+ }
+
+ /*
+ * If the event has an override, don't print warnings if the event
+ * print format fails to parse.
+ */
+ if (pevent && find_event_handle(pevent, event))
+ show_warning = 0;
+
+ ret = event_read_print(event);
+ show_warning = 1;
+
+ if (ret < 0) {
+ ret = PEVENT_ERRNO__READ_PRINT_FAILED;
+ goto event_parse_failed;
+ }
+
+ if (!ret && (event->flags & EVENT_FL_ISFTRACE)) {
+ struct format_field *field;
+ struct print_arg *arg, **list;
+
+ /* old ftrace had no args */
+ list = &event->print_fmt.args;
+ for (field = event->format.fields; field; field = field->next) {
+ arg = alloc_arg();
+ if (!arg) {
+ event->flags |= EVENT_FL_FAILED;
+ return PEVENT_ERRNO__OLD_FTRACE_ARG_FAILED;
+ }
+ arg->type = PRINT_FIELD;
+ arg->field.name = strdup(field->name);
+ if (!arg->field.name) {
+ event->flags |= EVENT_FL_FAILED;
+ free_arg(arg);
+ return PEVENT_ERRNO__OLD_FTRACE_ARG_FAILED;
+ }
+ arg->field.field = field;
+ *list = arg;
+ list = &arg->next;
+ }
+ return 0;
+ }
+
+ return 0;
+
+ event_parse_failed:
+ event->flags |= EVENT_FL_FAILED;
+ return ret;
+
+ event_alloc_failed:
+ free(event->system);
+ free(event->name);
+ free(event);
+ *eventp = NULL;
+ return ret;
+}
+
+/**
+ * pevent_parse_format - parse the event format
+ * @buf: the buffer storing the event format string
+ * @size: the size of @buf
+ * @sys: the system the event belongs to
+ *
+ * This parses the event format and creates an event structure
+ * to quickly parse raw data for a given event.
+ *
+ * These files currently come from:
+ *
+ * /sys/kernel/debug/tracing/events/.../.../format
+ */
+enum pevent_errno pevent_parse_format(struct event_format **eventp, const char *buf,
+ unsigned long size, const char *sys)
+{
+ return __pevent_parse_format(eventp, NULL, buf, size, sys);
+}
+
+/**
+ * pevent_parse_event - parse the event format
+ * @pevent: the handle to the pevent
+ * @buf: the buffer storing the event format string
+ * @size: the size of @buf
+ * @sys: the system the event belongs to
+ *
+ * This parses the event format and creates an event structure
+ * to quickly parse raw data for a given event.
+ *
+ * These files currently come from:
+ *
+ * /sys/kernel/debug/tracing/events/.../.../format
+ */
+enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf,
+ unsigned long size, const char *sys)
+{
+ struct event_format *event = NULL;
+ int ret = __pevent_parse_format(&event, pevent, buf, size, sys);
+
+ if (event == NULL)
+ return ret;
+
+ if (add_event(pevent, event)) {
+ ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
+ goto event_add_failed;
+ }
+
+#define PRINT_ARGS 0
+ if (PRINT_ARGS && event->print_fmt.args)
+ print_args(event->print_fmt.args);
+
+ return 0;
+
+event_add_failed:
+ pevent_free_format(event);
+ return ret;
+}
+
+#undef _PE
+#define _PE(code, str) str
+static const char * const pevent_error_str[] = {
+ PEVENT_ERRORS
+};
+#undef _PE
+
+int pevent_strerror(struct pevent *pevent __maybe_unused,
+ enum pevent_errno errnum, char *buf, size_t buflen)
+{
+ int idx;
+ const char *msg;
+
+ if (errnum >= 0) {
+#if defined(__GLIBC__)
+ msg = strerror_r(errnum, buf, buflen);
+ if (msg != buf) {
+ size_t len = strlen(msg);
+ memcpy(buf, msg, min(buflen - 1, len));
+ *(buf + min(buflen - 1, len)) = '\0';
+ }
+#else
+ if (strerror_r(errnum, buf, buflen))
+ snprintf(buf, buflen, "errnum %i", errnum);
+#endif
+ return 0;
+ }
+
+ if (errnum <= __PEVENT_ERRNO__START ||
+ errnum >= __PEVENT_ERRNO__END)
+ return -1;
+
+ idx = errnum - __PEVENT_ERRNO__START - 1;
+ msg = pevent_error_str[idx];
+
+ switch (errnum) {
+ case PEVENT_ERRNO__MEM_ALLOC_FAILED:
+ case PEVENT_ERRNO__PARSE_EVENT_FAILED:
+ case PEVENT_ERRNO__READ_ID_FAILED:
+ case PEVENT_ERRNO__READ_FORMAT_FAILED:
+ case PEVENT_ERRNO__READ_PRINT_FAILED:
+ case PEVENT_ERRNO__OLD_FTRACE_ARG_FAILED:
+ case PEVENT_ERRNO__INVALID_ARG_TYPE:
+ snprintf(buf, buflen, "%s", msg);
+ break;
+
+ default:
+ /* cannot reach here */
+ break;
+ }
+
+ return 0;
+}
+
+int get_field_val(struct trace_seq *s, struct format_field *field,
+ const char *name, struct pevent_record *record,
+ unsigned long long *val, int err)
+{
+ if (!field) {
+ if (err)
+ trace_seq_printf(s, "<CAN'T FIND FIELD %s>", name);
+ return -1;
+ }
+
+ if (pevent_read_number_field(field, record->data, val)) {
+ if (err)
+ trace_seq_printf(s, " %s=INVALID", name);
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * pevent_get_field_raw - return the raw pointer into the data field
+ * @s: The seq to print to on error
+ * @event: the event that the field is for
+ * @name: The name of the field
+ * @record: The record with the field name.
+ * @len: place to store the field length.
+ * @err: print default error if failed.
+ *
+ * Returns a pointer into record->data of the field and places
+ * the length of the field in @len.
+ *
+ * On failure, it returns NULL.
+ */
+void *pevent_get_field_raw(struct trace_seq *s, struct event_format *event,
+ const char *name, struct pevent_record *record,
+ int *len, int err)
+{
+ struct format_field *field;
+ void *data = record->data;
+ unsigned offset;
+ int dummy;
+
+ if (!event)
+ return NULL;
+
+ field = pevent_find_field(event, name);
+
+ if (!field) {
+ if (err)
+ trace_seq_printf(s, "<CAN'T FIND FIELD %s>", name);
+ return NULL;
+ }
+
+ /* Allow @len to be NULL */
+ if (!len)
+ len = &dummy;
+
+ offset = field->offset;
+ if (field->flags & FIELD_IS_DYNAMIC) {
+ offset = pevent_read_number(event->pevent,
+ data + offset, field->size);
+ *len = offset >> 16;
+ offset &= 0xffff;
+ } else
+ *len = field->size;
+
+ return data + offset;
+}
+
+/**
+ * pevent_get_field_val - find a field and return its value
+ * @s: The seq to print to on error
+ * @event: the event that the field is for
+ * @name: The name of the field
+ * @record: The record with the field name.
+ * @val: place to store the value of the field.
+ * @err: print default error if failed.
+ *
+ * Returns 0 on success -1 on field not found.
+ */
+int pevent_get_field_val(struct trace_seq *s, struct event_format *event,
+ const char *name, struct pevent_record *record,
+ unsigned long long *val, int err)
+{
+ struct format_field *field;
+
+ if (!event)
+ return -1;
+
+ field = pevent_find_field(event, name);
+
+ return get_field_val(s, field, name, record, val, err);
+}
+
+/**
+ * pevent_get_common_field_val - find a common field and return its value
+ * @s: The seq to print to on error
+ * @event: the event that the field is for
+ * @name: The name of the field
+ * @record: The record with the field name.
+ * @val: place to store the value of the field.
+ * @err: print default error if failed.
+ *
+ * Returns 0 on success -1 on field not found.
+ */
+int pevent_get_common_field_val(struct trace_seq *s, struct event_format *event,
+ const char *name, struct pevent_record *record,
+ unsigned long long *val, int err)
+{
+ struct format_field *field;
+
+ if (!event)
+ return -1;
+
+ field = pevent_find_common_field(event, name);
+
+ return get_field_val(s, field, name, record, val, err);
+}
+
+/**
+ * pevent_get_any_field_val - find a any field and return its value
+ * @s: The seq to print to on error
+ * @event: the event that the field is for
+ * @name: The name of the field
+ * @record: The record with the field name.
+ * @val: place to store the value of the field.
+ * @err: print default error if failed.
+ *
+ * Returns 0 on success -1 on field not found.
+ */
+int pevent_get_any_field_val(struct trace_seq *s, struct event_format *event,
+ const char *name, struct pevent_record *record,
+ unsigned long long *val, int err)
+{
+ struct format_field *field;
+
+ if (!event)
+ return -1;
+
+ field = pevent_find_any_field(event, name);
+
+ return get_field_val(s, field, name, record, val, err);
+}
+
+/**
+ * pevent_print_num_field - print a field and a format
+ * @s: The seq to print to
+ * @fmt: The printf format to print the field with.
+ * @event: the event that the field is for
+ * @name: The name of the field
+ * @record: The record with the field name.
+ * @err: print default error if failed.
+ *
+ * Returns: 0 on success, -1 field not found, or 1 if buffer is full.
+ */
+int pevent_print_num_field(struct trace_seq *s, const char *fmt,
+ struct event_format *event, const char *name,
+ struct pevent_record *record, int err)
+{
+ struct format_field *field = pevent_find_field(event, name);
+ unsigned long long val;
+
+ if (!field)
+ goto failed;
+
+ if (pevent_read_number_field(field, record->data, &val))
+ goto failed;
+
+ return trace_seq_printf(s, fmt, val);
+
+ failed:
+ if (err)
+ trace_seq_printf(s, "CAN'T FIND FIELD \"%s\"", name);
+ return -1;
+}
+
+static void free_func_handle(struct pevent_function_handler *func)
+{
+ struct pevent_func_params *params;
+
+ free(func->name);
+
+ while (func->params) {
+ params = func->params;
+ func->params = params->next;
+ free(params);
+ }
+
+ free(func);
+}
+
+/**
+ * pevent_register_print_function - register a helper function
+ * @pevent: the handle to the pevent
+ * @func: the function to process the helper function
+ * @ret_type: the return type of the helper function
+ * @name: the name of the helper function
+ * @parameters: A list of enum pevent_func_arg_type
+ *
+ * Some events may have helper functions in the print format arguments.
+ * This allows a plugin to dynamically create a way to process one
+ * of these functions.
+ *
+ * The @parameters is a variable list of pevent_func_arg_type enums that
+ * must end with PEVENT_FUNC_ARG_VOID.
+ */
+int pevent_register_print_function(struct pevent *pevent,
+ pevent_func_handler func,
+ enum pevent_func_arg_type ret_type,
+ char *name, ...)
+{
+ struct pevent_function_handler *func_handle;
+ struct pevent_func_params **next_param;
+ struct pevent_func_params *param;
+ enum pevent_func_arg_type type;
+ va_list ap;
+ int ret;
+
+ func_handle = find_func_handler(pevent, name);
+ if (func_handle) {
+ /*
+ * This is most like caused by the users own
+ * plugins updating the function. This overrides the
+ * system defaults.
+ */
+ pr_stat("override of function helper '%s'", name);
+ remove_func_handler(pevent, name);
+ }
+
+ func_handle = calloc(1, sizeof(*func_handle));
+ if (!func_handle) {
+ do_warning("Failed to allocate function handler");
+ return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+ }
+
+ func_handle->ret_type = ret_type;
+ func_handle->name = strdup(name);
+ func_handle->func = func;
+ if (!func_handle->name) {
+ do_warning("Failed to allocate function name");
+ free(func_handle);
+ return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+ }
+
+ next_param = &(func_handle->params);
+ va_start(ap, name);
+ for (;;) {
+ type = va_arg(ap, enum pevent_func_arg_type);
+ if (type == PEVENT_FUNC_ARG_VOID)
+ break;
+
+ if (type >= PEVENT_FUNC_ARG_MAX_TYPES) {
+ do_warning("Invalid argument type %d", type);
+ ret = PEVENT_ERRNO__INVALID_ARG_TYPE;
+ goto out_free;
+ }
+
+ param = malloc(sizeof(*param));
+ if (!param) {
+ do_warning("Failed to allocate function param");
+ ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
+ goto out_free;
+ }
+ param->type = type;
+ param->next = NULL;
+
+ *next_param = param;
+ next_param = &(param->next);
+
+ func_handle->nr_args++;
+ }
+ va_end(ap);
+
+ func_handle->next = pevent->func_handlers;
+ pevent->func_handlers = func_handle;
+
+ return 0;
+ out_free:
+ va_end(ap);
+ free_func_handle(func_handle);
+ return ret;
+}
+
+/**
+ * pevent_register_event_handler - register a way to parse an event
+ * @pevent: the handle to the pevent
+ * @id: the id of the event to register
+ * @sys_name: the system name the event belongs to
+ * @event_name: the name of the event
+ * @func: the function to call to parse the event information
+ * @context: the data to be passed to @func
+ *
+ * This function allows a developer to override the parsing of
+ * a given event. If for some reason the default print format
+ * is not sufficient, this function will register a function
+ * for an event to be used to parse the data instead.
+ *
+ * If @id is >= 0, then it is used to find the event.
+ * else @sys_name and @event_name are used.
+ */
+int pevent_register_event_handler(struct pevent *pevent, int id,
+ const char *sys_name, const char *event_name,
+ pevent_event_handler_func func, void *context)
+{
+ struct event_format *event;
+ struct event_handler *handle;
+
+ if (id >= 0) {
+ /* search by id */
+ event = pevent_find_event(pevent, id);
+ if (!event)
+ goto not_found;
+ if (event_name && (strcmp(event_name, event->name) != 0))
+ goto not_found;
+ if (sys_name && (strcmp(sys_name, event->system) != 0))
+ goto not_found;
+ } else {
+ event = pevent_find_event_by_name(pevent, sys_name, event_name);
+ if (!event)
+ goto not_found;
+ }
+
+ pr_stat("overriding event (%d) %s:%s with new print handler",
+ event->id, event->system, event->name);
+
+ event->handler = func;
+ event->context = context;
+ return 0;
+
+ not_found:
+ /* Save for later use. */
+ handle = calloc(1, sizeof(*handle));
+ if (!handle) {
+ do_warning("Failed to allocate event handler");
+ return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+ }
+
+ handle->id = id;
+ if (event_name)
+ handle->event_name = strdup(event_name);
+ if (sys_name)
+ handle->sys_name = strdup(sys_name);
+
+ if ((event_name && !handle->event_name) ||
+ (sys_name && !handle->sys_name)) {
+ do_warning("Failed to allocate event/sys name");
+ free((void *)handle->event_name);
+ free((void *)handle->sys_name);
+ free(handle);
+ return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+ }
+
+ handle->func = func;
+ handle->next = pevent->handlers;
+ pevent->handlers = handle;
+ handle->context = context;
+
+ return -1;
+}
+
+/**
+ * pevent_alloc - create a pevent handle
+ */
+struct pevent *pevent_alloc(void)
+{
+ struct pevent *pevent = calloc(1, sizeof(*pevent));
+
+ if (pevent)
+ pevent->ref_count = 1;
+
+ return pevent;
+}
+
+void pevent_ref(struct pevent *pevent)
+{
+ pevent->ref_count++;
+}
+
+static void free_format_fields(struct format_field *field)
+{
+ struct format_field *next;
+
+ while (field) {
+ next = field->next;
+ free(field->type);
+ free(field->name);
+ free(field);
+ field = next;
+ }
+}
+
+static void free_formats(struct format *format)
+{
+ free_format_fields(format->common_fields);
+ free_format_fields(format->fields);
+}
+
+void pevent_free_format(struct event_format *event)
+{
+ free(event->name);
+ free(event->system);
+
+ free_formats(&event->format);
+
+ free(event->print_fmt.format);
+ free_args(event->print_fmt.args);
+
+ free(event);
+}
+
+/**
+ * pevent_free - free a pevent handle
+ * @pevent: the pevent handle to free
+ */
+void pevent_free(struct pevent *pevent)
+{
+ struct cmdline_list *cmdlist, *cmdnext;
+ struct func_list *funclist, *funcnext;
+ struct printk_list *printklist, *printknext;
+ struct pevent_function_handler *func_handler;
+ struct event_handler *handle;
+ int i;
+
+ if (!pevent)
+ return;
+
+ cmdlist = pevent->cmdlist;
+ funclist = pevent->funclist;
+ printklist = pevent->printklist;
+
+ pevent->ref_count--;
+ if (pevent->ref_count)
+ return;
+
+ if (pevent->cmdlines) {
+ for (i = 0; i < pevent->cmdline_count; i++)
+ free(pevent->cmdlines[i].comm);
+ free(pevent->cmdlines);
+ }
+
+ while (cmdlist) {
+ cmdnext = cmdlist->next;
+ free(cmdlist->comm);
+ free(cmdlist);
+ cmdlist = cmdnext;
+ }
+
+ if (pevent->func_map) {
+ for (i = 0; i < (int)pevent->func_count; i++) {
+ free(pevent->func_map[i].func);
+ free(pevent->func_map[i].mod);
+ }
+ free(pevent->func_map);
+ }
+
+ while (funclist) {
+ funcnext = funclist->next;
+ free(funclist->func);
+ free(funclist->mod);
+ free(funclist);
+ funclist = funcnext;
+ }
+
+ while (pevent->func_handlers) {
+ func_handler = pevent->func_handlers;
+ pevent->func_handlers = func_handler->next;
+ free_func_handle(func_handler);
+ }
+
+ if (pevent->printk_map) {
+ for (i = 0; i < (int)pevent->printk_count; i++)
+ free(pevent->printk_map[i].printk);
+ free(pevent->printk_map);
+ }
+
+ while (printklist) {
+ printknext = printklist->next;
+ free(printklist->printk);
+ free(printklist);
+ printklist = printknext;
+ }
+
+ for (i = 0; i < pevent->nr_events; i++)
+ pevent_free_format(pevent->events[i]);
+
+ while (pevent->handlers) {
+ handle = pevent->handlers;
+ pevent->handlers = handle->next;
+ free_handler(handle);
+ }
+
+ free(pevent->events);
+ free(pevent->sort_events);
+
+ free(pevent);
+}
+
+void pevent_unref(struct pevent *pevent)
+{
+ pevent_free(pevent);
+}
diff --git a/traceevent/event-parse.h b/traceevent/event-parse.h
new file mode 100644
index 0000000..c37b202
--- /dev/null
+++ b/traceevent/event-parse.h
@@ -0,0 +1,857 @@
+/*
+ * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License (not later!)
+ *
+ * This program 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#ifndef _PARSE_EVENTS_H
+#define _PARSE_EVENTS_H
+
+#include <stdarg.h>
+#include <regex.h>
+
+#ifndef __maybe_unused
+#define __maybe_unused __attribute__((unused))
+#endif
+
+/* ----------------------- trace_seq ----------------------- */
+
+
+#ifndef TRACE_SEQ_BUF_SIZE
+#define TRACE_SEQ_BUF_SIZE 4096
+#endif
+
+#ifndef DEBUG_RECORD
+#define DEBUG_RECORD 0
+#endif
+
+struct pevent_record {
+ unsigned long long ts;
+ unsigned long long offset;
+ long long missed_events; /* buffer dropped events before */
+ int record_size; /* size of binary record */
+ int size; /* size of data */
+ void *data;
+ int cpu;
+ int ref_count;
+ int locked; /* Do not free, even if ref_count is zero */
+ void *priv;
+#if DEBUG_RECORD
+ struct pevent_record *prev;
+ struct pevent_record *next;
+ long alloc_addr;
+#endif
+};
+
+/*
+ * Trace sequences are used to allow a function to call several other functions
+ * to create a string of data to use (up to a max of PAGE_SIZE).
+ */
+
+struct trace_seq {
+ char *buffer;
+ unsigned int buffer_size;
+ unsigned int len;
+ unsigned int readpos;
+};
+
+void trace_seq_init(struct trace_seq *s);
+void trace_seq_reset(struct trace_seq *s);
+void trace_seq_destroy(struct trace_seq *s);
+
+extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
+ __attribute__ ((format (printf, 2, 3)));
+extern int trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args)
+ __attribute__ ((format (printf, 2, 0)));
+
+extern int trace_seq_puts(struct trace_seq *s, const char *str);
+extern int trace_seq_putc(struct trace_seq *s, unsigned char c);
+
+extern void trace_seq_terminate(struct trace_seq *s);
+
+extern int trace_seq_do_printf(struct trace_seq *s);
+
+
+/* ----------------------- pevent ----------------------- */
+
+struct pevent;
+struct event_format;
+
+typedef int (*pevent_event_handler_func)(struct trace_seq *s,
+ struct pevent_record *record,
+ struct event_format *event,
+ void *context);
+
+typedef int (*pevent_plugin_load_func)(struct pevent *pevent);
+typedef int (*pevent_plugin_unload_func)(void);
+
+struct plugin_option {
+ struct plugin_option *next;
+ void *handle;
+ char *file;
+ char *name;
+ char *plugin_alias;
+ char *description;
+ char *value;
+ void *priv;
+ int set;
+};
+
+/*
+ * Plugin hooks that can be called:
+ *
+ * PEVENT_PLUGIN_LOADER: (required)
+ * The function name to initialized the plugin.
+ *
+ * int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
+ *
+ * PEVENT_PLUGIN_UNLOADER: (optional)
+ * The function called just before unloading
+ *
+ * int PEVENT_PLUGIN_UNLOADER(void)
+ *
+ * PEVENT_PLUGIN_OPTIONS: (optional)
+ * Plugin options that can be set before loading
+ *
+ * struct plugin_option PEVENT_PLUGIN_OPTIONS[] = {
+ * {
+ * .name = "option-name",
+ * .plugin_alias = "overide-file-name", (optional)
+ * .description = "description of option to show users",
+ * },
+ * {
+ * .name = NULL,
+ * },
+ * };
+ *
+ * Array must end with .name = NULL;
+ *
+ *
+ * .plugin_alias is used to give a shorter name to access
+ * the vairable. Useful if a plugin handles more than one event.
+ *
+ * PEVENT_PLUGIN_ALIAS: (optional)
+ * The name to use for finding options (uses filename if not defined)
+ */
+#define PEVENT_PLUGIN_LOADER pevent_plugin_loader
+#define PEVENT_PLUGIN_UNLOADER pevent_plugin_unloader
+#define PEVENT_PLUGIN_OPTIONS pevent_plugin_options
+#define PEVENT_PLUGIN_ALIAS pevent_plugin_alias
+#define _MAKE_STR(x) #x
+#define MAKE_STR(x) _MAKE_STR(x)
+#define PEVENT_PLUGIN_LOADER_NAME MAKE_STR(PEVENT_PLUGIN_LOADER)
+#define PEVENT_PLUGIN_UNLOADER_NAME MAKE_STR(PEVENT_PLUGIN_UNLOADER)
+#define PEVENT_PLUGIN_OPTIONS_NAME MAKE_STR(PEVENT_PLUGIN_OPTIONS)
+#define PEVENT_PLUGIN_ALIAS_NAME MAKE_STR(PEVENT_PLUGIN_ALIAS)
+
+#define NSECS_PER_SEC 1000000000ULL
+#define NSECS_PER_USEC 1000ULL
+
+enum format_flags {
+ FIELD_IS_ARRAY = 1,
+ FIELD_IS_POINTER = 2,
+ FIELD_IS_SIGNED = 4,
+ FIELD_IS_STRING = 8,
+ FIELD_IS_DYNAMIC = 16,
+ FIELD_IS_LONG = 32,
+ FIELD_IS_FLAG = 64,
+ FIELD_IS_SYMBOLIC = 128,
+};
+
+struct format_field {
+ struct format_field *next;
+ struct event_format *event;
+ char *type;
+ char *name;
+ int offset;
+ int size;
+ unsigned int arraylen;
+ unsigned int elementsize;
+ unsigned long flags;
+};
+
+struct format {
+ int nr_common;
+ int nr_fields;
+ struct format_field *common_fields;
+ struct format_field *fields;
+};
+
+struct print_arg_atom {
+ char *atom;
+};
+
+struct print_arg_string {
+ char *string;
+ int offset;
+};
+
+struct print_arg_field {
+ char *name;
+ struct format_field *field;
+};
+
+struct print_flag_sym {
+ struct print_flag_sym *next;
+ char *value;
+ char *str;
+};
+
+struct print_arg_typecast {
+ char *type;
+ struct print_arg *item;
+};
+
+struct print_arg_flags {
+ struct print_arg *field;
+ char *delim;
+ struct print_flag_sym *flags;
+};
+
+struct print_arg_symbol {
+ struct print_arg *field;
+ struct print_flag_sym *symbols;
+};
+
+struct print_arg_hex {
+ struct print_arg *field;
+ struct print_arg *size;
+};
+
+struct print_arg_dynarray {
+ struct format_field *field;
+ struct print_arg *index;
+};
+
+struct print_arg;
+
+struct print_arg_op {
+ char *op;
+ int prio;
+ struct print_arg *left;
+ struct print_arg *right;
+};
+
+struct pevent_function_handler;
+
+struct print_arg_func {
+ struct pevent_function_handler *func;
+ struct print_arg *args;
+};
+
+enum print_arg_type {
+ PRINT_NULL,
+ PRINT_ATOM,
+ PRINT_FIELD,
+ PRINT_FLAGS,
+ PRINT_SYMBOL,
+ PRINT_HEX,
+ PRINT_TYPE,
+ PRINT_STRING,
+ PRINT_BSTRING,
+ PRINT_DYNAMIC_ARRAY,
+ PRINT_OP,
+ PRINT_FUNC,
+};
+
+struct print_arg {
+ struct print_arg *next;
+ enum print_arg_type type;
+ union {
+ struct print_arg_atom atom;
+ struct print_arg_field field;
+ struct print_arg_typecast typecast;
+ struct print_arg_flags flags;
+ struct print_arg_symbol symbol;
+ struct print_arg_hex hex;
+ struct print_arg_func func;
+ struct print_arg_string string;
+ struct print_arg_op op;
+ struct print_arg_dynarray dynarray;
+ };
+};
+
+struct print_fmt {
+ char *format;
+ struct print_arg *args;
+};
+
+struct event_format {
+ struct pevent *pevent;
+ char *name;
+ int id;
+ int flags;
+ struct format format;
+ struct print_fmt print_fmt;
+ char *system;
+ pevent_event_handler_func handler;
+ void *context;
+};
+
+enum {
+ EVENT_FL_ISFTRACE = 0x01,
+ EVENT_FL_ISPRINT = 0x02,
+ EVENT_FL_ISBPRINT = 0x04,
+ EVENT_FL_ISFUNCENT = 0x10,
+ EVENT_FL_ISFUNCRET = 0x20,
+
+ EVENT_FL_FAILED = 0x80000000
+};
+
+enum event_sort_type {
+ EVENT_SORT_ID,
+ EVENT_SORT_NAME,
+ EVENT_SORT_SYSTEM,
+};
+
+enum event_type {
+ EVENT_ERROR,
+ EVENT_NONE,
+ EVENT_SPACE,
+ EVENT_NEWLINE,
+ EVENT_OP,
+ EVENT_DELIM,
+ EVENT_ITEM,
+ EVENT_DQUOTE,
+ EVENT_SQUOTE,
+};
+
+typedef unsigned long long (*pevent_func_handler)(struct trace_seq *s,
+ unsigned long long *args);
+
+enum pevent_func_arg_type {
+ PEVENT_FUNC_ARG_VOID,
+ PEVENT_FUNC_ARG_INT,
+ PEVENT_FUNC_ARG_LONG,
+ PEVENT_FUNC_ARG_STRING,
+ PEVENT_FUNC_ARG_PTR,
+ PEVENT_FUNC_ARG_MAX_TYPES
+};
+
+enum pevent_flag {
+ PEVENT_NSEC_OUTPUT = 1, /* output in NSECS */
+};
+
+#define PEVENT_ERRORS \
+ _PE(MEM_ALLOC_FAILED, "failed to allocate memory"), \
+ _PE(PARSE_EVENT_FAILED, "failed to parse event"), \
+ _PE(READ_ID_FAILED, "failed to read event id"), \
+ _PE(READ_FORMAT_FAILED, "failed to read event format"), \
+ _PE(READ_PRINT_FAILED, "failed to read event print fmt"), \
+ _PE(OLD_FTRACE_ARG_FAILED,"failed to allocate field name for ftrace"),\
+ _PE(INVALID_ARG_TYPE, "invalid argument type")
+
+#undef _PE
+#define _PE(__code, __str) PEVENT_ERRNO__ ## __code
+enum pevent_errno {
+ PEVENT_ERRNO__SUCCESS = 0,
+
+ /*
+ * Choose an arbitrary negative big number not to clash with standard
+ * errno since SUS requires the errno has distinct positive values.
+ * See 'Issue 6' in the link below.
+ *
+ * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html
+ */
+ __PEVENT_ERRNO__START = -100000,
+
+ PEVENT_ERRORS,
+
+ __PEVENT_ERRNO__END,
+};
+#undef _PE
+
+struct cmdline;
+struct cmdline_list;
+struct func_map;
+struct func_list;
+struct event_handler;
+
+struct pevent {
+ int ref_count;
+
+ int header_page_ts_offset;
+ int header_page_ts_size;
+ int header_page_size_offset;
+ int header_page_size_size;
+ int header_page_data_offset;
+ int header_page_data_size;
+ int header_page_overwrite;
+
+ int file_bigendian;
+ int host_bigendian;
+
+ int latency_format;
+
+ int old_format;
+
+ int cpus;
+ int long_size;
+ int page_size;
+
+ struct cmdline *cmdlines;
+ struct cmdline_list *cmdlist;
+ int cmdline_count;
+
+ struct func_map *func_map;
+ struct func_list *funclist;
+ unsigned int func_count;
+
+ struct printk_map *printk_map;
+ struct printk_list *printklist;
+ unsigned int printk_count;
+
+
+ struct event_format **events;
+ int nr_events;
+ struct event_format **sort_events;
+ enum event_sort_type last_type;
+
+ int type_offset;
+ int type_size;
+
+ int pid_offset;
+ int pid_size;
+
+ int pc_offset;
+ int pc_size;
+
+ int flags_offset;
+ int flags_size;
+
+ int ld_offset;
+ int ld_size;
+
+ int print_raw;
+
+ int test_filters;
+
+ int flags;
+
+ struct format_field *bprint_ip_field;
+ struct format_field *bprint_fmt_field;
+ struct format_field *bprint_buf_field;
+
+ struct event_handler *handlers;
+ struct pevent_function_handler *func_handlers;
+
+ /* cache */
+ struct event_format *last_event;
+};
+
+static inline void pevent_set_flag(struct pevent *pevent, int flag)
+{
+ pevent->flags |= flag;
+}
+
+static inline unsigned short
+__data2host2(struct pevent *pevent, unsigned short data)
+{
+ unsigned short swap;
+
+ if (pevent->host_bigendian == pevent->file_bigendian)
+ return data;
+
+ swap = ((data & 0xffULL) << 8) |
+ ((data & (0xffULL << 8)) >> 8);
+
+ return swap;
+}
+
+static inline unsigned int
+__data2host4(struct pevent *pevent, unsigned int data)
+{
+ unsigned int swap;
+
+ if (pevent->host_bigendian == pevent->file_bigendian)
+ return data;
+
+ swap = ((data & 0xffULL) << 24) |
+ ((data & (0xffULL << 8)) << 8) |
+ ((data & (0xffULL << 16)) >> 8) |
+ ((data & (0xffULL << 24)) >> 24);
+
+ return swap;
+}
+
+static inline unsigned long long
+__data2host8(struct pevent *pevent, unsigned long long data)
+{
+ unsigned long long swap;
+
+ if (pevent->host_bigendian == pevent->file_bigendian)
+ return data;
+
+ swap = ((data & 0xffULL) << 56) |
+ ((data & (0xffULL << 8)) << 40) |
+ ((data & (0xffULL << 16)) << 24) |
+ ((data & (0xffULL << 24)) << 8) |
+ ((data & (0xffULL << 32)) >> 8) |
+ ((data & (0xffULL << 40)) >> 24) |
+ ((data & (0xffULL << 48)) >> 40) |
+ ((data & (0xffULL << 56)) >> 56);
+
+ return swap;
+}
+
+#define data2host2(pevent, ptr) __data2host2(pevent, *(unsigned short *)(ptr))
+#define data2host4(pevent, ptr) __data2host4(pevent, *(unsigned int *)(ptr))
+#define data2host8(pevent, ptr) \
+({ \
+ unsigned long long __val; \
+ \
+ memcpy(&__val, (ptr), sizeof(unsigned long long)); \
+ __data2host8(pevent, __val); \
+})
+
+/* taken from kernel/trace/trace.h */
+enum trace_flag_type {
+ TRACE_FLAG_IRQS_OFF = 0x01,
+ TRACE_FLAG_IRQS_NOSUPPORT = 0x02,
+ TRACE_FLAG_NEED_RESCHED = 0x04,
+ TRACE_FLAG_HARDIRQ = 0x08,
+ TRACE_FLAG_SOFTIRQ = 0x10,
+};
+
+int pevent_register_comm(struct pevent *pevent, const char *comm, int pid);
+int pevent_register_function(struct pevent *pevent, char *name,
+ unsigned long long addr, char *mod);
+int pevent_register_print_string(struct pevent *pevent, char *fmt,
+ unsigned long long addr);
+int pevent_pid_is_registered(struct pevent *pevent, int pid);
+
+void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
+ struct pevent_record *record);
+
+int pevent_parse_header_page(struct pevent *pevent, char *buf, unsigned long size,
+ int long_size);
+
+enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf,
+ unsigned long size, const char *sys);
+enum pevent_errno pevent_parse_format(struct event_format **eventp, const char *buf,
+ unsigned long size, const char *sys);
+void pevent_free_format(struct event_format *event);
+
+void *pevent_get_field_raw(struct trace_seq *s, struct event_format *event,
+ const char *name, struct pevent_record *record,
+ int *len, int err);
+
+int pevent_get_field_val(struct trace_seq *s, struct event_format *event,
+ const char *name, struct pevent_record *record,
+ unsigned long long *val, int err);
+int pevent_get_common_field_val(struct trace_seq *s, struct event_format *event,
+ const char *name, struct pevent_record *record,
+ unsigned long long *val, int err);
+int pevent_get_any_field_val(struct trace_seq *s, struct event_format *event,
+ const char *name, struct pevent_record *record,
+ unsigned long long *val, int err);
+
+int pevent_print_num_field(struct trace_seq *s, const char *fmt,
+ struct event_format *event, const char *name,
+ struct pevent_record *record, int err);
+
+int pevent_register_event_handler(struct pevent *pevent, int id,
+ const char *sys_name, const char *event_name,
+ pevent_event_handler_func func, void *context);
+int pevent_register_print_function(struct pevent *pevent,
+ pevent_func_handler func,
+ enum pevent_func_arg_type ret_type,
+ char *name, ...);
+
+struct format_field *pevent_find_common_field(struct event_format *event, const char *name);
+struct format_field *pevent_find_field(struct event_format *event, const char *name);
+struct format_field *pevent_find_any_field(struct event_format *event, const char *name);
+
+const char *pevent_find_function(struct pevent *pevent, unsigned long long addr);
+unsigned long long
+pevent_find_function_address(struct pevent *pevent, unsigned long long addr);
+unsigned long long pevent_read_number(struct pevent *pevent, const void *ptr, int size);
+int pevent_read_number_field(struct format_field *field, const void *data,
+ unsigned long long *value);
+
+struct event_format *pevent_find_event(struct pevent *pevent, int id);
+
+struct event_format *
+pevent_find_event_by_name(struct pevent *pevent, const char *sys, const char *name);
+
+void pevent_data_lat_fmt(struct pevent *pevent,
+ struct trace_seq *s, struct pevent_record *record);
+int pevent_data_type(struct pevent *pevent, struct pevent_record *rec);
+struct event_format *pevent_data_event_from_type(struct pevent *pevent, int type);
+int pevent_data_pid(struct pevent *pevent, struct pevent_record *rec);
+const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid);
+void pevent_event_info(struct trace_seq *s, struct event_format *event,
+ struct pevent_record *record);
+int pevent_strerror(struct pevent *pevent, enum pevent_errno errnum,
+ char *buf, size_t buflen);
+
+struct event_format **pevent_list_events(struct pevent *pevent, enum event_sort_type);
+struct format_field **pevent_event_common_fields(struct event_format *event);
+struct format_field **pevent_event_fields(struct event_format *event);
+
+static inline int pevent_get_cpus(struct pevent *pevent)
+{
+ return pevent->cpus;
+}
+
+static inline void pevent_set_cpus(struct pevent *pevent, int cpus)
+{
+ pevent->cpus = cpus;
+}
+
+static inline int pevent_get_long_size(struct pevent *pevent)
+{
+ return pevent->long_size;
+}
+
+static inline void pevent_set_long_size(struct pevent *pevent, int long_size)
+{
+ pevent->long_size = long_size;
+}
+
+static inline int pevent_get_page_size(struct pevent *pevent)
+{
+ return pevent->page_size;
+}
+
+static inline void pevent_set_page_size(struct pevent *pevent, int _page_size)
+{
+ pevent->page_size = _page_size;
+}
+
+static inline int pevent_is_file_bigendian(struct pevent *pevent)
+{
+ return pevent->file_bigendian;
+}
+
+static inline void pevent_set_file_bigendian(struct pevent *pevent, int endian)
+{
+ pevent->file_bigendian = endian;
+}
+
+static inline int pevent_is_host_bigendian(struct pevent *pevent)
+{
+ return pevent->host_bigendian;
+}
+
+static inline void pevent_set_host_bigendian(struct pevent *pevent, int endian)
+{
+ pevent->host_bigendian = endian;
+}
+
+static inline int pevent_is_latency_format(struct pevent *pevent)
+{
+ return pevent->latency_format;
+}
+
+static inline void pevent_set_latency_format(struct pevent *pevent, int lat)
+{
+ pevent->latency_format = lat;
+}
+
+struct pevent *pevent_alloc(void);
+void pevent_free(struct pevent *pevent);
+void pevent_ref(struct pevent *pevent);
+void pevent_unref(struct pevent *pevent);
+
+/* access to the internal parser */
+void pevent_buffer_init(const char *buf, unsigned long long size);
+enum event_type pevent_read_token(char **tok);
+void pevent_free_token(char *token);
+int pevent_peek_char(void);
+const char *pevent_get_input_buf(void);
+unsigned long long pevent_get_input_buf_ptr(void);
+
+/* for debugging */
+void pevent_print_funcs(struct pevent *pevent);
+void pevent_print_printk(struct pevent *pevent);
+
+/* ----------------------- filtering ----------------------- */
+
+enum filter_boolean_type {
+ FILTER_FALSE,
+ FILTER_TRUE,
+};
+
+enum filter_op_type {
+ FILTER_OP_AND = 1,
+ FILTER_OP_OR,
+ FILTER_OP_NOT,
+};
+
+enum filter_cmp_type {
+ FILTER_CMP_NONE,
+ FILTER_CMP_EQ,
+ FILTER_CMP_NE,
+ FILTER_CMP_GT,
+ FILTER_CMP_LT,
+ FILTER_CMP_GE,
+ FILTER_CMP_LE,
+ FILTER_CMP_MATCH,
+ FILTER_CMP_NOT_MATCH,
+ FILTER_CMP_REGEX,
+ FILTER_CMP_NOT_REGEX,
+};
+
+enum filter_exp_type {
+ FILTER_EXP_NONE,
+ FILTER_EXP_ADD,
+ FILTER_EXP_SUB,
+ FILTER_EXP_MUL,
+ FILTER_EXP_DIV,
+ FILTER_EXP_MOD,
+ FILTER_EXP_RSHIFT,
+ FILTER_EXP_LSHIFT,
+ FILTER_EXP_AND,
+ FILTER_EXP_OR,
+ FILTER_EXP_XOR,
+ FILTER_EXP_NOT,
+};
+
+enum filter_arg_type {
+ FILTER_ARG_NONE,
+ FILTER_ARG_BOOLEAN,
+ FILTER_ARG_VALUE,
+ FILTER_ARG_FIELD,
+ FILTER_ARG_EXP,
+ FILTER_ARG_OP,
+ FILTER_ARG_NUM,
+ FILTER_ARG_STR,
+};
+
+enum filter_value_type {
+ FILTER_NUMBER,
+ FILTER_STRING,
+ FILTER_CHAR
+};
+
+struct fliter_arg;
+
+struct filter_arg_boolean {
+ enum filter_boolean_type value;
+};
+
+struct filter_arg_field {
+ struct format_field *field;
+};
+
+struct filter_arg_value {
+ enum filter_value_type type;
+ union {
+ char *str;
+ unsigned long long val;
+ };
+};
+
+struct filter_arg_op {
+ enum filter_op_type type;
+ struct filter_arg *left;
+ struct filter_arg *right;
+};
+
+struct filter_arg_exp {
+ enum filter_exp_type type;
+ struct filter_arg *left;
+ struct filter_arg *right;
+};
+
+struct filter_arg_num {
+ enum filter_cmp_type type;
+ struct filter_arg *left;
+ struct filter_arg *right;
+};
+
+struct filter_arg_str {
+ enum filter_cmp_type type;
+ struct format_field *field;
+ char *val;
+ char *buffer;
+ regex_t reg;
+};
+
+struct filter_arg {
+ enum filter_arg_type type;
+ union {
+ struct filter_arg_boolean boolean;
+ struct filter_arg_field field;
+ struct filter_arg_value value;
+ struct filter_arg_op op;
+ struct filter_arg_exp exp;
+ struct filter_arg_num num;
+ struct filter_arg_str str;
+ };
+};
+
+struct filter_type {
+ int event_id;
+ struct event_format *event;
+ struct filter_arg *filter;
+};
+
+struct event_filter {
+ struct pevent *pevent;
+ int filters;
+ struct filter_type *event_filters;
+};
+
+struct event_filter *pevent_filter_alloc(struct pevent *pevent);
+
+#define FILTER_NONE -2
+#define FILTER_NOEXIST -1
+#define FILTER_MISS 0
+#define FILTER_MATCH 1
+
+enum filter_trivial_type {
+ FILTER_TRIVIAL_FALSE,
+ FILTER_TRIVIAL_TRUE,
+ FILTER_TRIVIAL_BOTH,
+};
+
+int pevent_filter_add_filter_str(struct event_filter *filter,
+ const char *filter_str,
+ char **error_str);
+
+
+int pevent_filter_match(struct event_filter *filter,
+ struct pevent_record *record);
+
+int pevent_event_filtered(struct event_filter *filter,
+ int event_id);
+
+void pevent_filter_reset(struct event_filter *filter);
+
+void pevent_filter_clear_trivial(struct event_filter *filter,
+ enum filter_trivial_type type);
+
+void pevent_filter_free(struct event_filter *filter);
+
+char *pevent_filter_make_string(struct event_filter *filter, int event_id);
+
+int pevent_filter_remove_event(struct event_filter *filter,
+ int event_id);
+
+int pevent_filter_event_has_trivial(struct event_filter *filter,
+ int event_id,
+ enum filter_trivial_type type);
+
+int pevent_filter_copy(struct event_filter *dest, struct event_filter *source);
+
+int pevent_update_trivial(struct event_filter *dest, struct event_filter *source,
+ enum filter_trivial_type type);
+
+int pevent_filter_compare(struct event_filter *filter1, struct event_filter *filter2);
+
+#endif /* _PARSE_EVENTS_H */
diff --git a/traceevent/event-utils.h b/traceevent/event-utils.h
new file mode 100644
index 0000000..e76c9ac
--- /dev/null
+++ b/traceevent/event-utils.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License (not later!)
+ *
+ * This program 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#ifndef __UTIL_H
+#define __UTIL_H
+
+#include <ctype.h>
+
+/* Can be overridden */
+void die(const char *fmt, ...);
+void *malloc_or_die(unsigned int size);
+void warning(const char *fmt, ...);
+void pr_stat(const char *fmt, ...);
+void vpr_stat(const char *fmt, va_list ap);
+
+/* Always available */
+void __die(const char *fmt, ...);
+void __warning(const char *fmt, ...);
+void __pr_stat(const char *fmt, ...);
+
+void __vdie(const char *fmt, ...);
+void __vwarning(const char *fmt, ...);
+void __vpr_stat(const char *fmt, ...);
+
+#define min(x, y) ({ \
+ typeof(x) _min1 = (x); \
+ typeof(y) _min2 = (y); \
+ (void) (&_min1 == &_min2); \
+ _min1 < _min2 ? _min1 : _min2; })
+
+static inline char *strim(char *string)
+{
+ char *ret;
+
+ if (!string)
+ return NULL;
+ while (*string) {
+ if (!isspace(*string))
+ break;
+ string++;
+ }
+ ret = string;
+
+ string = ret + strlen(ret) - 1;
+ while (string > ret) {
+ if (!isspace(*string))
+ break;
+ string--;
+ }
+ string[1] = 0;
+
+ return ret;
+}
+
+static inline int has_text(const char *text)
+{
+ if (!text)
+ return 0;
+
+ while (*text) {
+ if (!isspace(*text))
+ return 1;
+ text++;
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/traceevent/kbuffer-parse.c b/traceevent/kbuffer-parse.c
new file mode 100644
index 0000000..8deddc9
--- /dev/null
+++ b/traceevent/kbuffer-parse.c
@@ -0,0 +1,732 @@
+/*
+ * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License (not later!)
+ *
+ * This program 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "kbuffer.h"
+
+#define MISSING_EVENTS (1 << 31)
+#define MISSING_STORED (1 << 30)
+
+#define COMMIT_MASK ((1 << 27) - 1)
+
+enum {
+ KBUFFER_FL_HOST_BIG_ENDIAN = (1<<0),
+ KBUFFER_FL_BIG_ENDIAN = (1<<1),
+ KBUFFER_FL_LONG_8 = (1<<2),
+ KBUFFER_FL_OLD_FORMAT = (1<<3),
+};
+
+#define ENDIAN_MASK (KBUFFER_FL_HOST_BIG_ENDIAN | KBUFFER_FL_BIG_ENDIAN)
+
+/** kbuffer
+ * @timestamp - timestamp of current event
+ * @lost_events - # of lost events between this subbuffer and previous
+ * @flags - special flags of the kbuffer
+ * @subbuffer - pointer to the sub-buffer page
+ * @data - pointer to the start of data on the sub-buffer page
+ * @index - index from @data to the @curr event data
+ * @curr - offset from @data to the start of current event
+ * (includes metadata)
+ * @next - offset from @data to the start of next event
+ * @size - The size of data on @data
+ * @start - The offset from @subbuffer where @data lives
+ *
+ * @read_4 - Function to read 4 raw bytes (may swap)
+ * @read_8 - Function to read 8 raw bytes (may swap)
+ * @read_long - Function to read a long word (4 or 8 bytes with needed swap)
+ */
+struct kbuffer {
+ unsigned long long timestamp;
+ long long lost_events;
+ unsigned long flags;
+ void *subbuffer;
+ void *data;
+ unsigned int index;
+ unsigned int curr;
+ unsigned int next;
+ unsigned int size;
+ unsigned int start;
+
+ unsigned int (*read_4)(void *ptr);
+ unsigned long long (*read_8)(void *ptr);
+ unsigned long long (*read_long)(struct kbuffer *kbuf, void *ptr);
+ int (*next_event)(struct kbuffer *kbuf);
+};
+
+static void *zmalloc(size_t size)
+{
+ return calloc(1, size);
+}
+
+static int host_is_bigendian(void)
+{
+ unsigned char str[] = { 0x1, 0x2, 0x3, 0x4 };
+ unsigned int *ptr;
+
+ ptr = (unsigned int *)str;
+ return *ptr == 0x01020304;
+}
+
+static int do_swap(struct kbuffer *kbuf)
+{
+ return ((kbuf->flags & KBUFFER_FL_HOST_BIG_ENDIAN) + kbuf->flags) &
+ ENDIAN_MASK;
+}
+
+static unsigned long long __read_8(void *ptr)
+{
+ unsigned long long data = *(unsigned long long *)ptr;
+
+ return data;
+}
+
+static unsigned long long __read_8_sw(void *ptr)
+{
+ unsigned long long data = *(unsigned long long *)ptr;
+ unsigned long long swap;
+
+ swap = ((data & 0xffULL) << 56) |
+ ((data & (0xffULL << 8)) << 40) |
+ ((data & (0xffULL << 16)) << 24) |
+ ((data & (0xffULL << 24)) << 8) |
+ ((data & (0xffULL << 32)) >> 8) |
+ ((data & (0xffULL << 40)) >> 24) |
+ ((data & (0xffULL << 48)) >> 40) |
+ ((data & (0xffULL << 56)) >> 56);
+
+ return swap;
+}
+
+static unsigned int __read_4(void *ptr)
+{
+ unsigned int data = *(unsigned int *)ptr;
+
+ return data;
+}
+
+static unsigned int __read_4_sw(void *ptr)
+{
+ unsigned int data = *(unsigned int *)ptr;
+ unsigned int swap;
+
+ swap = ((data & 0xffULL) << 24) |
+ ((data & (0xffULL << 8)) << 8) |
+ ((data & (0xffULL << 16)) >> 8) |
+ ((data & (0xffULL << 24)) >> 24);
+
+ return swap;
+}
+
+static unsigned long long read_8(struct kbuffer *kbuf, void *ptr)
+{
+ return kbuf->read_8(ptr);
+}
+
+static unsigned int read_4(struct kbuffer *kbuf, void *ptr)
+{
+ return kbuf->read_4(ptr);
+}
+
+static unsigned long long __read_long_8(struct kbuffer *kbuf, void *ptr)
+{
+ return kbuf->read_8(ptr);
+}
+
+static unsigned long long __read_long_4(struct kbuffer *kbuf, void *ptr)
+{
+ return kbuf->read_4(ptr);
+}
+
+static unsigned long long read_long(struct kbuffer *kbuf, void *ptr)
+{
+ return kbuf->read_long(kbuf, ptr);
+}
+
+static int calc_index(struct kbuffer *kbuf, void *ptr)
+{
+ return (unsigned long)ptr - (unsigned long)kbuf->data;
+}
+
+static int __next_event(struct kbuffer *kbuf);
+
+/**
+ * kbuffer_alloc - allocat a new kbuffer
+ * @size; enum to denote size of word
+ * @endian: enum to denote endianness
+ *
+ * Allocates and returns a new kbuffer.
+ */
+struct kbuffer *
+kbuffer_alloc(enum kbuffer_long_size size, enum kbuffer_endian endian)
+{
+ struct kbuffer *kbuf;
+ int flags = 0;
+
+ switch (size) {
+ case KBUFFER_LSIZE_4:
+ break;
+ case KBUFFER_LSIZE_8:
+ flags |= KBUFFER_FL_LONG_8;
+ break;
+ default:
+ return NULL;
+ }
+
+ switch (endian) {
+ case KBUFFER_ENDIAN_LITTLE:
+ break;
+ case KBUFFER_ENDIAN_BIG:
+ flags |= KBUFFER_FL_BIG_ENDIAN;
+ break;
+ default:
+ return NULL;
+ }
+
+ kbuf = zmalloc(sizeof(*kbuf));
+ if (!kbuf)
+ return NULL;
+
+ kbuf->flags = flags;
+
+ if (host_is_bigendian())
+ kbuf->flags |= KBUFFER_FL_HOST_BIG_ENDIAN;
+
+ if (do_swap(kbuf)) {
+ kbuf->read_8 = __read_8_sw;
+ kbuf->read_4 = __read_4_sw;
+ } else {
+ kbuf->read_8 = __read_8;
+ kbuf->read_4 = __read_4;
+ }
+
+ if (kbuf->flags & KBUFFER_FL_LONG_8)
+ kbuf->read_long = __read_long_8;
+ else
+ kbuf->read_long = __read_long_4;
+
+ /* May be changed by kbuffer_set_old_format() */
+ kbuf->next_event = __next_event;
+
+ return kbuf;
+}
+
+/** kbuffer_free - free an allocated kbuffer
+ * @kbuf: The kbuffer to free
+ *
+ * Can take NULL as a parameter.
+ */
+void kbuffer_free(struct kbuffer *kbuf)
+{
+ free(kbuf);
+}
+
+static unsigned int type4host(struct kbuffer *kbuf,
+ unsigned int type_len_ts)
+{
+ if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN)
+ return (type_len_ts >> 29) & 3;
+ else
+ return type_len_ts & 3;
+}
+
+static unsigned int len4host(struct kbuffer *kbuf,
+ unsigned int type_len_ts)
+{
+ if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN)
+ return (type_len_ts >> 27) & 7;
+ else
+ return (type_len_ts >> 2) & 7;
+}
+
+static unsigned int type_len4host(struct kbuffer *kbuf,
+ unsigned int type_len_ts)
+{
+ if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN)
+ return (type_len_ts >> 27) & ((1 << 5) - 1);
+ else
+ return type_len_ts & ((1 << 5) - 1);
+}
+
+static unsigned int ts4host(struct kbuffer *kbuf,
+ unsigned int type_len_ts)
+{
+ if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN)
+ return type_len_ts & ((1 << 27) - 1);
+ else
+ return type_len_ts >> 5;
+}
+
+/*
+ * Linux 2.6.30 and earlier (not much earlier) had a different
+ * ring buffer format. It should be obsolete, but we handle it anyway.
+ */
+enum old_ring_buffer_type {
+ OLD_RINGBUF_TYPE_PADDING,
+ OLD_RINGBUF_TYPE_TIME_EXTEND,
+ OLD_RINGBUF_TYPE_TIME_STAMP,
+ OLD_RINGBUF_TYPE_DATA,
+};
+
+static unsigned int old_update_pointers(struct kbuffer *kbuf)
+{
+ unsigned long long extend;
+ unsigned int type_len_ts;
+ unsigned int type;
+ unsigned int len;
+ unsigned int delta;
+ unsigned int length;
+ void *ptr = kbuf->data + kbuf->curr;
+
+ type_len_ts = read_4(kbuf, ptr);
+ ptr += 4;
+
+ type = type4host(kbuf, type_len_ts);
+ len = len4host(kbuf, type_len_ts);
+ delta = ts4host(kbuf, type_len_ts);
+
+ switch (type) {
+ case OLD_RINGBUF_TYPE_PADDING:
+ kbuf->next = kbuf->size;
+ return 0;
+
+ case OLD_RINGBUF_TYPE_TIME_EXTEND:
+ extend = read_4(kbuf, ptr);
+ extend <<= TS_SHIFT;
+ extend += delta;
+ delta = extend;
+ ptr += 4;
+ break;
+
+ case OLD_RINGBUF_TYPE_TIME_STAMP:
+ /* should never happen! */
+ kbuf->curr = kbuf->size;
+ kbuf->next = kbuf->size;
+ kbuf->index = kbuf->size;
+ return -1;
+ default:
+ if (len)
+ length = len * 4;
+ else {
+ length = read_4(kbuf, ptr);
+ length -= 4;
+ ptr += 4;
+ }
+ break;
+ }
+
+ kbuf->timestamp += delta;
+ kbuf->index = calc_index(kbuf, ptr);
+ kbuf->next = kbuf->index + length;
+
+ return type;
+}
+
+static int __old_next_event(struct kbuffer *kbuf)
+{
+ int type;
+
+ do {
+ kbuf->curr = kbuf->next;
+ if (kbuf->next >= kbuf->size)
+ return -1;
+ type = old_update_pointers(kbuf);
+ } while (type == OLD_RINGBUF_TYPE_TIME_EXTEND || type == OLD_RINGBUF_TYPE_PADDING);
+
+ return 0;
+}
+
+static unsigned int
+translate_data(struct kbuffer *kbuf, void *data, void **rptr,
+ unsigned long long *delta, int *length)
+{
+ unsigned long long extend;
+ unsigned int type_len_ts;
+ unsigned int type_len;
+
+ type_len_ts = read_4(kbuf, data);
+ data += 4;
+
+ type_len = type_len4host(kbuf, type_len_ts);
+ *delta = ts4host(kbuf, type_len_ts);
+
+ switch (type_len) {
+ case KBUFFER_TYPE_PADDING:
+ *length = read_4(kbuf, data);
+ data += *length;
+ break;
+
+ case KBUFFER_TYPE_TIME_EXTEND:
+ extend = read_4(kbuf, data);
+ data += 4;
+ extend <<= TS_SHIFT;
+ extend += *delta;
+ *delta = extend;
+ *length = 0;
+ break;
+
+ case KBUFFER_TYPE_TIME_STAMP:
+ data += 12;
+ *length = 0;
+ break;
+ case 0:
+ *length = read_4(kbuf, data) - 4;
+ *length = (*length + 3) & ~3;
+ data += 4;
+ break;
+ default:
+ *length = type_len * 4;
+ break;
+ }
+
+ *rptr = data;
+
+ return type_len;
+}
+
+static unsigned int update_pointers(struct kbuffer *kbuf)
+{
+ unsigned long long delta;
+ unsigned int type_len;
+ int length;
+ void *ptr = kbuf->data + kbuf->curr;
+
+ type_len = translate_data(kbuf, ptr, &ptr, &delta, &length);
+
+ kbuf->timestamp += delta;
+ kbuf->index = calc_index(kbuf, ptr);
+ kbuf->next = kbuf->index + length;
+
+ return type_len;
+}
+
+/**
+ * kbuffer_translate_data - read raw data to get a record
+ * @swap: Set to 1 if bytes in words need to be swapped when read
+ * @data: The raw data to read
+ * @size: Address to store the size of the event data.
+ *
+ * Returns a pointer to the event data. To determine the entire
+ * record size (record metadata + data) just add the difference between
+ * @data and the returned value to @size.
+ */
+void *kbuffer_translate_data(int swap, void *data, unsigned int *size)
+{
+ unsigned long long delta;
+ struct kbuffer kbuf;
+ int type_len;
+ int length;
+ void *ptr;
+
+ if (swap) {
+ kbuf.read_8 = __read_8_sw;
+ kbuf.read_4 = __read_4_sw;
+ kbuf.flags = host_is_bigendian() ? 0 : KBUFFER_FL_BIG_ENDIAN;
+ } else {
+ kbuf.read_8 = __read_8;
+ kbuf.read_4 = __read_4;
+ kbuf.flags = host_is_bigendian() ? KBUFFER_FL_BIG_ENDIAN: 0;
+ }
+
+ type_len = translate_data(&kbuf, data, &ptr, &delta, &length);
+ switch (type_len) {
+ case KBUFFER_TYPE_PADDING:
+ case KBUFFER_TYPE_TIME_EXTEND:
+ case KBUFFER_TYPE_TIME_STAMP:
+ return NULL;
+ };
+
+ *size = length;
+
+ return ptr;
+}
+
+static int __next_event(struct kbuffer *kbuf)
+{
+ int type;
+
+ do {
+ kbuf->curr = kbuf->next;
+ if (kbuf->next >= kbuf->size)
+ return -1;
+ type = update_pointers(kbuf);
+ } while (type == KBUFFER_TYPE_TIME_EXTEND || type == KBUFFER_TYPE_PADDING);
+
+ return 0;
+}
+
+static int next_event(struct kbuffer *kbuf)
+{
+ return kbuf->next_event(kbuf);
+}
+
+/**
+ * kbuffer_next_event - increment the current pointer
+ * @kbuf: The kbuffer to read
+ * @ts: Address to store the next record's timestamp (may be NULL to ignore)
+ *
+ * Increments the pointers into the subbuffer of the kbuffer to point to the
+ * next event so that the next kbuffer_read_event() will return a
+ * new event.
+ *
+ * Returns the data of the next event if a new event exists on the subbuffer,
+ * NULL otherwise.
+ */
+void *kbuffer_next_event(struct kbuffer *kbuf, unsigned long long *ts)
+{
+ int ret;
+
+ if (!kbuf || !kbuf->subbuffer)
+ return NULL;
+
+ ret = next_event(kbuf);
+ if (ret < 0)
+ return NULL;
+
+ if (ts)
+ *ts = kbuf->timestamp;
+
+ return kbuf->data + kbuf->index;
+}
+
+/**
+ * kbuffer_load_subbuffer - load a new subbuffer into the kbuffer
+ * @kbuf: The kbuffer to load
+ * @subbuffer: The subbuffer to load into @kbuf.
+ *
+ * Load a new subbuffer (page) into @kbuf. This will reset all
+ * the pointers and update the @kbuf timestamp. The next read will
+ * return the first event on @subbuffer.
+ *
+ * Returns 0 on succes, -1 otherwise.
+ */
+int kbuffer_load_subbuffer(struct kbuffer *kbuf, void *subbuffer)
+{
+ unsigned long long flags;
+ void *ptr = subbuffer;
+
+ if (!kbuf || !subbuffer)
+ return -1;
+
+ kbuf->subbuffer = subbuffer;
+
+ kbuf->timestamp = read_8(kbuf, ptr);
+ ptr += 8;
+
+ kbuf->curr = 0;
+
+ if (kbuf->flags & KBUFFER_FL_LONG_8)
+ kbuf->start = 16;
+ else
+ kbuf->start = 12;
+
+ kbuf->data = subbuffer + kbuf->start;
+
+ flags = read_long(kbuf, ptr);
+ kbuf->size = (unsigned int)flags & COMMIT_MASK;
+
+ if (flags & MISSING_EVENTS) {
+ if (flags & MISSING_STORED) {
+ ptr = kbuf->data + kbuf->size;
+ kbuf->lost_events = read_long(kbuf, ptr);
+ } else
+ kbuf->lost_events = -1;
+ } else
+ kbuf->lost_events = 0;
+
+ kbuf->index = 0;
+ kbuf->next = 0;
+
+ next_event(kbuf);
+
+ return 0;
+}
+
+/**
+ * kbuffer_read_event - read the next event in the kbuffer subbuffer
+ * @kbuf: The kbuffer to read from
+ * @ts: The address to store the timestamp of the event (may be NULL to ignore)
+ *
+ * Returns a pointer to the data part of the current event.
+ * NULL if no event is left on the subbuffer.
+ */
+void *kbuffer_read_event(struct kbuffer *kbuf, unsigned long long *ts)
+{
+ if (!kbuf || !kbuf->subbuffer)
+ return NULL;
+
+ if (kbuf->curr >= kbuf->size)
+ return NULL;
+
+ if (ts)
+ *ts = kbuf->timestamp;
+ return kbuf->data + kbuf->index;
+}
+
+/**
+ * kbuffer_timestamp - Return the timestamp of the current event
+ * @kbuf: The kbuffer to read from
+ *
+ * Returns the timestamp of the current (next) event.
+ */
+unsigned long long kbuffer_timestamp(struct kbuffer *kbuf)
+{
+ return kbuf->timestamp;
+}
+
+/**
+ * kbuffer_read_at_offset - read the event that is at offset
+ * @kbuf: The kbuffer to read from
+ * @offset: The offset into the subbuffer
+ * @ts: The address to store the timestamp of the event (may be NULL to ignore)
+ *
+ * The @offset must be an index from the @kbuf subbuffer beginning.
+ * If @offset is bigger than the stored subbuffer, NULL will be returned.
+ *
+ * Returns the data of the record that is at @offset. Note, @offset does
+ * not need to be the start of the record, the offset just needs to be
+ * in the record (or beginning of it).
+ *
+ * Note, the kbuf timestamp and pointers are updated to the
+ * returned record. That is, kbuffer_read_event() will return the same
+ * data and timestamp, and kbuffer_next_event() will increment from
+ * this record.
+ */
+void *kbuffer_read_at_offset(struct kbuffer *kbuf, int offset,
+ unsigned long long *ts)
+{
+ void *data;
+
+ if (offset < kbuf->start)
+ offset = 0;
+ else
+ offset -= kbuf->start;
+
+ /* Reset the buffer */
+ kbuffer_load_subbuffer(kbuf, kbuf->subbuffer);
+
+ while (kbuf->curr < offset) {
+ data = kbuffer_next_event(kbuf, ts);
+ if (!data)
+ break;
+ }
+
+ return data;
+}
+
+/**
+ * kbuffer_subbuffer_size - the size of the loaded subbuffer
+ * @kbuf: The kbuffer to read from
+ *
+ * Returns the size of the subbuffer. Note, this size is
+ * where the last event resides. The stored subbuffer may actually be
+ * bigger due to padding and such.
+ */
+int kbuffer_subbuffer_size(struct kbuffer *kbuf)
+{
+ return kbuf->size;
+}
+
+/**
+ * kbuffer_curr_index - Return the index of the record
+ * @kbuf: The kbuffer to read from
+ *
+ * Returns the index from the start of the data part of
+ * the subbuffer to the current location. Note this is not
+ * from the start of the subbuffer. An index of zero will
+ * point to the first record. Use kbuffer_curr_offset() for
+ * the actually offset (that can be used by kbuffer_read_at_offset())
+ */
+int kbuffer_curr_index(struct kbuffer *kbuf)
+{
+ return kbuf->curr;
+}
+
+/**
+ * kbuffer_curr_offset - Return the offset of the record
+ * @kbuf: The kbuffer to read from
+ *
+ * Returns the offset from the start of the subbuffer to the
+ * current location.
+ */
+int kbuffer_curr_offset(struct kbuffer *kbuf)
+{
+ return kbuf->curr + kbuf->start;
+}
+
+/**
+ * kbuffer_event_size - return the size of the event data
+ * @kbuf: The kbuffer to read
+ *
+ * Returns the size of the event data (the payload not counting
+ * the meta data of the record) of the current event.
+ */
+int kbuffer_event_size(struct kbuffer *kbuf)
+{
+ return kbuf->next - kbuf->index;
+}
+
+/**
+ * kbuffer_curr_size - return the size of the entire record
+ * @kbuf: The kbuffer to read
+ *
+ * Returns the size of the entire record (meta data and payload)
+ * of the current event.
+ */
+int kbuffer_curr_size(struct kbuffer *kbuf)
+{
+ return kbuf->next - kbuf->curr;
+}
+
+/**
+ * kbuffer_missed_events - return the # of missed events from last event.
+ * @kbuf: The kbuffer to read from
+ *
+ * Returns the # of missed events (if recorded) before the current
+ * event. Note, only events on the beginning of a subbuffer can
+ * have missed events, all other events within the buffer will be
+ * zero.
+ */
+int kbuffer_missed_events(struct kbuffer *kbuf)
+{
+ /* Only the first event can have missed events */
+ if (kbuf->curr)
+ return 0;
+
+ return kbuf->lost_events;
+}
+
+/**
+ * kbuffer_set_old_forma - set the kbuffer to use the old format parsing
+ * @kbuf: The kbuffer to set
+ *
+ * This is obsolete (or should be). The first kernels to use the
+ * new ring buffer had a slightly different ring buffer format
+ * (2.6.30 and earlier). It is still somewhat supported by kbuffer,
+ * but should not be counted on in the future.
+ */
+void kbuffer_set_old_format(struct kbuffer *kbuf)
+{
+ kbuf->flags |= KBUFFER_FL_OLD_FORMAT;
+
+ kbuf->next_event = __old_next_event;
+}
diff --git a/traceevent/kbuffer.h b/traceevent/kbuffer.h
new file mode 100644
index 0000000..c831f64
--- /dev/null
+++ b/traceevent/kbuffer.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2012 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License (not later!)
+ *
+ * This program 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#ifndef _KBUFFER_H
+#define _KBUFFER_H
+
+#ifndef TS_SHIFT
+#define TS_SHIFT 27
+#endif
+
+enum kbuffer_endian {
+ KBUFFER_ENDIAN_BIG,
+ KBUFFER_ENDIAN_LITTLE,
+};
+
+enum kbuffer_long_size {
+ KBUFFER_LSIZE_4,
+ KBUFFER_LSIZE_8,
+};
+
+enum {
+ KBUFFER_TYPE_PADDING = 29,
+ KBUFFER_TYPE_TIME_EXTEND = 30,
+ KBUFFER_TYPE_TIME_STAMP = 31,
+};
+
+struct kbuffer;
+
+struct kbuffer *kbuffer_alloc(enum kbuffer_long_size size, enum kbuffer_endian endian);
+void kbuffer_free(struct kbuffer *kbuf);
+int kbuffer_load_subbuffer(struct kbuffer *kbuf, void *subbuffer);
+void *kbuffer_read_event(struct kbuffer *kbuf, unsigned long long *ts);
+void *kbuffer_next_event(struct kbuffer *kbuf, unsigned long long *ts);
+unsigned long long kbuffer_timestamp(struct kbuffer *kbuf);
+
+void *kbuffer_translate_data(int swap, void *data, unsigned int *size);
+
+void *kbuffer_read_at_offset(struct kbuffer *kbuf, int offset, unsigned long long *ts);
+
+int kbuffer_curr_index(struct kbuffer *kbuf);
+
+int kbuffer_curr_offset(struct kbuffer *kbuf);
+int kbuffer_curr_size(struct kbuffer *kbuf);
+int kbuffer_event_size(struct kbuffer *kbuf);
+int kbuffer_missed_events(struct kbuffer *kbuf);
+int kbuffer_subbuffer_size(struct kbuffer *kbuf);
+
+void kbuffer_set_old_format(struct kbuffer *kbuf);
+
+#endif /* _K_BUFFER_H */
diff --git a/traceevent/parse-filter.c b/traceevent/parse-filter.c
new file mode 100644
index 0000000..ec308ae
--- /dev/null
+++ b/traceevent/parse-filter.c
@@ -0,0 +1,2303 @@
+/*
+ * Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License (not later!)
+ *
+ * This program 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <sys/types.h>
+
+#include "event-parse.h"
+#include "event-utils.h"
+
+#define COMM "COMM"
+
+static struct format_field comm = {
+ .name = "COMM",
+};
+
+struct event_list {
+ struct event_list *next;
+ struct event_format *event;
+};
+
+#define MAX_ERR_STR_SIZE 256
+
+static void show_error(char **error_str, const char *fmt, ...)
+{
+ unsigned long long index;
+ const char *input;
+ char *error;
+ va_list ap;
+ int len;
+ int i;
+
+ if (!error_str)
+ return;
+
+ input = pevent_get_input_buf();
+ index = pevent_get_input_buf_ptr();
+ len = input ? strlen(input) : 0;
+
+ error = malloc_or_die(MAX_ERR_STR_SIZE + (len*2) + 3);
+
+ if (len) {
+ strcpy(error, input);
+ error[len] = '\n';
+ for (i = 1; i < len && i < index; i++)
+ error[len+i] = ' ';
+ error[len + i] = '^';
+ error[len + i + 1] = '\n';
+ len += i+2;
+ }
+
+ va_start(ap, fmt);
+ vsnprintf(error + len, MAX_ERR_STR_SIZE, fmt, ap);
+ va_end(ap);
+
+ *error_str = error;
+}
+
+static void free_token(char *token)
+{
+ pevent_free_token(token);
+}
+
+static enum event_type read_token(char **tok)
+{
+ enum event_type type;
+ char *token = NULL;
+
+ do {
+ free_token(token);
+ type = pevent_read_token(&token);
+ } while (type == EVENT_NEWLINE || type == EVENT_SPACE);
+
+ /* If token is = or ! check to see if the next char is ~ */
+ if (token &&
+ (strcmp(token, "=") == 0 || strcmp(token, "!") == 0) &&
+ pevent_peek_char() == '~') {
+ /* append it */
+ *tok = malloc_or_die(3);
+ sprintf(*tok, "%c%c", *token, '~');
+ free_token(token);
+ /* Now remove the '~' from the buffer */
+ pevent_read_token(&token);
+ free_token(token);
+ } else
+ *tok = token;
+
+ return type;
+}
+
+static int filter_cmp(const void *a, const void *b)
+{
+ const struct filter_type *ea = a;
+ const struct filter_type *eb = b;
+
+ if (ea->event_id < eb->event_id)
+ return -1;
+
+ if (ea->event_id > eb->event_id)
+ return 1;
+
+ return 0;
+}
+
+static struct filter_type *
+find_filter_type(struct event_filter *filter, int id)
+{
+ struct filter_type *filter_type;
+ struct filter_type key;
+
+ key.event_id = id;
+
+ filter_type = bsearch(&key, filter->event_filters,
+ filter->filters,
+ sizeof(*filter->event_filters),
+ filter_cmp);
+
+ return filter_type;
+}
+
+static struct filter_type *
+add_filter_type(struct event_filter *filter, int id)
+{
+ struct filter_type *filter_type;
+ int i;
+
+ filter_type = find_filter_type(filter, id);
+ if (filter_type)
+ return filter_type;
+
+ filter->event_filters = realloc(filter->event_filters,
+ sizeof(*filter->event_filters) *
+ (filter->filters + 1));
+ if (!filter->event_filters)
+ die("Could not allocate filter");
+
+ for (i = 0; i < filter->filters; i++) {
+ if (filter->event_filters[i].event_id > id)
+ break;
+ }
+
+ if (i < filter->filters)
+ memmove(&filter->event_filters[i+1],
+ &filter->event_filters[i],
+ sizeof(*filter->event_filters) *
+ (filter->filters - i));
+
+ filter_type = &filter->event_filters[i];
+ filter_type->event_id = id;
+ filter_type->event = pevent_find_event(filter->pevent, id);
+ filter_type->filter = NULL;
+
+ filter->filters++;
+
+ return filter_type;
+}
+
+/**
+ * pevent_filter_alloc - create a new event filter
+ * @pevent: The pevent that this filter is associated with
+ */
+struct event_filter *pevent_filter_alloc(struct pevent *pevent)
+{
+ struct event_filter *filter;
+
+ filter = malloc_or_die(sizeof(*filter));
+ memset(filter, 0, sizeof(*filter));
+ filter->pevent = pevent;
+ pevent_ref(pevent);
+
+ return filter;
+}
+
+static struct filter_arg *allocate_arg(void)
+{
+ struct filter_arg *arg;
+
+ arg = malloc_or_die(sizeof(*arg));
+ memset(arg, 0, sizeof(*arg));
+
+ return arg;
+}
+
+static void free_arg(struct filter_arg *arg)
+{
+ if (!arg)
+ return;
+
+ switch (arg->type) {
+ case FILTER_ARG_NONE:
+ case FILTER_ARG_BOOLEAN:
+ break;
+
+ case FILTER_ARG_NUM:
+ free_arg(arg->num.left);
+ free_arg(arg->num.right);
+ break;
+
+ case FILTER_ARG_EXP:
+ free_arg(arg->exp.left);
+ free_arg(arg->exp.right);
+ break;
+
+ case FILTER_ARG_STR:
+ free(arg->str.val);
+ regfree(&arg->str.reg);
+ free(arg->str.buffer);
+ break;
+
+ case FILTER_ARG_VALUE:
+ if (arg->value.type == FILTER_STRING ||
+ arg->value.type == FILTER_CHAR)
+ free(arg->value.str);
+ break;
+
+ case FILTER_ARG_OP:
+ free_arg(arg->op.left);
+ free_arg(arg->op.right);
+ default:
+ break;
+ }
+
+ free(arg);
+}
+
+static void add_event(struct event_list **events,
+ struct event_format *event)
+{
+ struct event_list *list;
+
+ list = malloc_or_die(sizeof(*list));
+ list->next = *events;
+ *events = list;
+ list->event = event;
+}
+
+static int event_match(struct event_format *event,
+ regex_t *sreg, regex_t *ereg)
+{
+ if (sreg) {
+ return !regexec(sreg, event->system, 0, NULL, 0) &&
+ !regexec(ereg, event->name, 0, NULL, 0);
+ }
+
+ return !regexec(ereg, event->system, 0, NULL, 0) ||
+ !regexec(ereg, event->name, 0, NULL, 0);
+}
+
+static int
+find_event(struct pevent *pevent, struct event_list **events,
+ char *sys_name, char *event_name)
+{
+ struct event_format *event;
+ regex_t ereg;
+ regex_t sreg;
+ int match = 0;
+ char *reg;
+ int ret;
+ int i;
+
+ if (!event_name) {
+ /* if no name is given, then swap sys and name */
+ event_name = sys_name;
+ sys_name = NULL;
+ }
+
+ reg = malloc_or_die(strlen(event_name) + 3);
+ sprintf(reg, "^%s$", event_name);
+
+ ret = regcomp(&ereg, reg, REG_ICASE|REG_NOSUB);
+ free(reg);
+
+ if (ret)
+ return -1;
+
+ if (sys_name) {
+ reg = malloc_or_die(strlen(sys_name) + 3);
+ sprintf(reg, "^%s$", sys_name);
+ ret = regcomp(&sreg, reg, REG_ICASE|REG_NOSUB);
+ free(reg);
+ if (ret) {
+ regfree(&ereg);
+ return -1;
+ }
+ }
+
+ for (i = 0; i < pevent->nr_events; i++) {
+ event = pevent->events[i];
+ if (event_match(event, sys_name ? &sreg : NULL, &ereg)) {
+ match = 1;
+ add_event(events, event);
+ }
+ }
+
+ regfree(&ereg);
+ if (sys_name)
+ regfree(&sreg);
+
+ if (!match)
+ return -1;
+
+ return 0;
+}
+
+static void free_events(struct event_list *events)
+{
+ struct event_list *event;
+
+ while (events) {
+ event = events;
+ events = events->next;
+ free(event);
+ }
+}
+
+static struct filter_arg *
+create_arg_item(struct event_format *event, const char *token,
+ enum event_type type, char **error_str)
+{
+ struct format_field *field;
+ struct filter_arg *arg;
+
+ arg = allocate_arg();
+
+ switch (type) {
+
+ case EVENT_SQUOTE:
+ case EVENT_DQUOTE:
+ arg->type = FILTER_ARG_VALUE;
+ arg->value.type =
+ type == EVENT_DQUOTE ? FILTER_STRING : FILTER_CHAR;
+ arg->value.str = strdup(token);
+ if (!arg->value.str)
+ die("malloc string");
+ break;
+ case EVENT_ITEM:
+ /* if it is a number, then convert it */
+ if (isdigit(token[0])) {
+ arg->type = FILTER_ARG_VALUE;
+ arg->value.type = FILTER_NUMBER;
+ arg->value.val = strtoull(token, NULL, 0);
+ break;
+ }
+ /* Consider this a field */
+ field = pevent_find_any_field(event, token);
+ if (!field) {
+ if (strcmp(token, COMM) != 0) {
+ /* not a field, Make it false */
+ arg->type = FILTER_ARG_BOOLEAN;
+ arg->boolean.value = FILTER_FALSE;
+ break;
+ }
+ /* If token is 'COMM' then it is special */
+ field = &comm;
+ }
+ arg->type = FILTER_ARG_FIELD;
+ arg->field.field = field;
+ break;
+ default:
+ free_arg(arg);
+ show_error(error_str, "expected a value but found %s",
+ token);
+ return NULL;
+ }
+ return arg;
+}
+
+static struct filter_arg *
+create_arg_op(enum filter_op_type btype)
+{
+ struct filter_arg *arg;
+
+ arg = allocate_arg();
+ arg->type = FILTER_ARG_OP;
+ arg->op.type = btype;
+
+ return arg;
+}
+
+static struct filter_arg *
+create_arg_exp(enum filter_exp_type etype)
+{
+ struct filter_arg *arg;
+
+ arg = allocate_arg();
+ arg->type = FILTER_ARG_EXP;
+ arg->op.type = etype;
+
+ return arg;
+}
+
+static struct filter_arg *
+create_arg_cmp(enum filter_exp_type etype)
+{
+ struct filter_arg *arg;
+
+ arg = allocate_arg();
+ /* Use NUM and change if necessary */
+ arg->type = FILTER_ARG_NUM;
+ arg->op.type = etype;
+
+ return arg;
+}
+
+static int add_right(struct filter_arg *op, struct filter_arg *arg,
+ char **error_str)
+{
+ struct filter_arg *left;
+ char *str;
+ int op_type;
+ int ret;
+
+ switch (op->type) {
+ case FILTER_ARG_EXP:
+ if (op->exp.right)
+ goto out_fail;
+ op->exp.right = arg;
+ break;
+
+ case FILTER_ARG_OP:
+ if (op->op.right)
+ goto out_fail;
+ op->op.right = arg;
+ break;
+
+ case FILTER_ARG_NUM:
+ if (op->op.right)
+ goto out_fail;
+ /*
+ * The arg must be num, str, or field
+ */
+ switch (arg->type) {
+ case FILTER_ARG_VALUE:
+ case FILTER_ARG_FIELD:
+ break;
+ default:
+ show_error(error_str,
+ "Illegal rvalue");
+ return -1;
+ }
+
+ /*
+ * Depending on the type, we may need to
+ * convert this to a string or regex.
+ */
+ switch (arg->value.type) {
+ case FILTER_CHAR:
+ /*
+ * A char should be converted to number if
+ * the string is 1 byte, and the compare
+ * is not a REGEX.
+ */
+ if (strlen(arg->value.str) == 1 &&
+ op->num.type != FILTER_CMP_REGEX &&
+ op->num.type != FILTER_CMP_NOT_REGEX) {
+ arg->value.type = FILTER_NUMBER;
+ goto do_int;
+ }
+ /* fall through */
+ case FILTER_STRING:
+
+ /* convert op to a string arg */
+ op_type = op->num.type;
+ left = op->num.left;
+ str = arg->value.str;
+
+ /* reset the op for the new field */
+ memset(op, 0, sizeof(*op));
+
+ /*
+ * If left arg was a field not found then
+ * NULL the entire op.
+ */
+ if (left->type == FILTER_ARG_BOOLEAN) {
+ free_arg(left);
+ free_arg(arg);
+ op->type = FILTER_ARG_BOOLEAN;
+ op->boolean.value = FILTER_FALSE;
+ break;
+ }
+
+ /* Left arg must be a field */
+ if (left->type != FILTER_ARG_FIELD) {
+ show_error(error_str,
+ "Illegal lvalue for string comparison");
+ return -1;
+ }
+
+ /* Make sure this is a valid string compare */
+ switch (op_type) {
+ case FILTER_CMP_EQ:
+ op_type = FILTER_CMP_MATCH;
+ break;
+ case FILTER_CMP_NE:
+ op_type = FILTER_CMP_NOT_MATCH;
+ break;
+
+ case FILTER_CMP_REGEX:
+ case FILTER_CMP_NOT_REGEX:
+ ret = regcomp(&op->str.reg, str, REG_ICASE|REG_NOSUB);
+ if (ret) {
+ show_error(error_str,
+ "RegEx '%s' did not compute",
+ str);
+ return -1;
+ }
+ break;
+ default:
+ show_error(error_str,
+ "Illegal comparison for string");
+ return -1;
+ }
+
+ op->type = FILTER_ARG_STR;
+ op->str.type = op_type;
+ op->str.field = left->field.field;
+ op->str.val = strdup(str);
+ if (!op->str.val)
+ die("malloc string");
+ /*
+ * Need a buffer to copy data for tests
+ */
+ op->str.buffer = malloc_or_die(op->str.field->size + 1);
+ /* Null terminate this buffer */
+ op->str.buffer[op->str.field->size] = 0;
+
+ /* We no longer have left or right args */
+ free_arg(arg);
+ free_arg(left);
+
+ break;
+
+ case FILTER_NUMBER:
+
+ do_int:
+ switch (op->num.type) {
+ case FILTER_CMP_REGEX:
+ case FILTER_CMP_NOT_REGEX:
+ show_error(error_str,
+ "Op not allowed with integers");
+ return -1;
+
+ default:
+ break;
+ }
+
+ /* numeric compare */
+ op->num.right = arg;
+ break;
+ default:
+ goto out_fail;
+ }
+ break;
+ default:
+ goto out_fail;
+ }
+
+ return 0;
+
+ out_fail:
+ show_error(error_str,
+ "Syntax error");
+ return -1;
+}
+
+static struct filter_arg *
+rotate_op_right(struct filter_arg *a, struct filter_arg *b)
+{
+ struct filter_arg *arg;
+
+ arg = a->op.right;
+ a->op.right = b;
+ return arg;
+}
+
+static int add_left(struct filter_arg *op, struct filter_arg *arg)
+{
+ switch (op->type) {
+ case FILTER_ARG_EXP:
+ if (arg->type == FILTER_ARG_OP)
+ arg = rotate_op_right(arg, op);
+ op->exp.left = arg;
+ break;
+
+ case FILTER_ARG_OP:
+ op->op.left = arg;
+ break;
+ case FILTER_ARG_NUM:
+ if (arg->type == FILTER_ARG_OP)
+ arg = rotate_op_right(arg, op);
+
+ /* left arg of compares must be a field */
+ if (arg->type != FILTER_ARG_FIELD &&
+ arg->type != FILTER_ARG_BOOLEAN)
+ return -1;
+ op->num.left = arg;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+enum op_type {
+ OP_NONE,
+ OP_BOOL,
+ OP_NOT,
+ OP_EXP,
+ OP_CMP,
+};
+
+static enum op_type process_op(const char *token,
+ enum filter_op_type *btype,
+ enum filter_cmp_type *ctype,
+ enum filter_exp_type *etype)
+{
+ *btype = FILTER_OP_NOT;
+ *etype = FILTER_EXP_NONE;
+ *ctype = FILTER_CMP_NONE;
+
+ if (strcmp(token, "&&") == 0)
+ *btype = FILTER_OP_AND;
+ else if (strcmp(token, "||") == 0)
+ *btype = FILTER_OP_OR;
+ else if (strcmp(token, "!") == 0)
+ return OP_NOT;
+
+ if (*btype != FILTER_OP_NOT)
+ return OP_BOOL;
+
+ /* Check for value expressions */
+ if (strcmp(token, "+") == 0) {
+ *etype = FILTER_EXP_ADD;
+ } else if (strcmp(token, "-") == 0) {
+ *etype = FILTER_EXP_SUB;
+ } else if (strcmp(token, "*") == 0) {
+ *etype = FILTER_EXP_MUL;
+ } else if (strcmp(token, "/") == 0) {
+ *etype = FILTER_EXP_DIV;
+ } else if (strcmp(token, "%") == 0) {
+ *etype = FILTER_EXP_MOD;
+ } else if (strcmp(token, ">>") == 0) {
+ *etype = FILTER_EXP_RSHIFT;
+ } else if (strcmp(token, "<<") == 0) {
+ *etype = FILTER_EXP_LSHIFT;
+ } else if (strcmp(token, "&") == 0) {
+ *etype = FILTER_EXP_AND;
+ } else if (strcmp(token, "|") == 0) {
+ *etype = FILTER_EXP_OR;
+ } else if (strcmp(token, "^") == 0) {
+ *etype = FILTER_EXP_XOR;
+ } else if (strcmp(token, "~") == 0)
+ *etype = FILTER_EXP_NOT;
+
+ if (*etype != FILTER_EXP_NONE)
+ return OP_EXP;
+
+ /* Check for compares */
+ if (strcmp(token, "==") == 0)
+ *ctype = FILTER_CMP_EQ;
+ else if (strcmp(token, "!=") == 0)
+ *ctype = FILTER_CMP_NE;
+ else if (strcmp(token, "<") == 0)
+ *ctype = FILTER_CMP_LT;
+ else if (strcmp(token, ">") == 0)
+ *ctype = FILTER_CMP_GT;
+ else if (strcmp(token, "<=") == 0)
+ *ctype = FILTER_CMP_LE;
+ else if (strcmp(token, ">=") == 0)
+ *ctype = FILTER_CMP_GE;
+ else if (strcmp(token, "=~") == 0)
+ *ctype = FILTER_CMP_REGEX;
+ else if (strcmp(token, "!~") == 0)
+ *ctype = FILTER_CMP_NOT_REGEX;
+ else
+ return OP_NONE;
+
+ return OP_CMP;
+}
+
+static int check_op_done(struct filter_arg *arg)
+{
+ switch (arg->type) {
+ case FILTER_ARG_EXP:
+ return arg->exp.right != NULL;
+
+ case FILTER_ARG_OP:
+ return arg->op.right != NULL;
+
+ case FILTER_ARG_NUM:
+ return arg->num.right != NULL;
+
+ case FILTER_ARG_STR:
+ /* A string conversion is always done */
+ return 1;
+
+ case FILTER_ARG_BOOLEAN:
+ /* field not found, is ok */
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+enum filter_vals {
+ FILTER_VAL_NORM,
+ FILTER_VAL_FALSE,
+ FILTER_VAL_TRUE,
+};
+
+void reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
+ struct filter_arg *arg)
+{
+ struct filter_arg *other_child;
+ struct filter_arg **ptr;
+
+ if (parent->type != FILTER_ARG_OP &&
+ arg->type != FILTER_ARG_OP)
+ die("can not reparent other than OP");
+
+ /* Get the sibling */
+ if (old_child->op.right == arg) {
+ ptr = &old_child->op.right;
+ other_child = old_child->op.left;
+ } else if (old_child->op.left == arg) {
+ ptr = &old_child->op.left;
+ other_child = old_child->op.right;
+ } else
+ die("Error in reparent op, find other child");
+
+ /* Detach arg from old_child */
+ *ptr = NULL;
+
+ /* Check for root */
+ if (parent == old_child) {
+ free_arg(other_child);
+ *parent = *arg;
+ /* Free arg without recussion */
+ free(arg);
+ return;
+ }
+
+ if (parent->op.right == old_child)
+ ptr = &parent->op.right;
+ else if (parent->op.left == old_child)
+ ptr = &parent->op.left;
+ else
+ die("Error in reparent op");
+ *ptr = arg;
+
+ free_arg(old_child);
+}
+
+enum filter_vals test_arg(struct filter_arg *parent, struct filter_arg *arg)
+{
+ enum filter_vals lval, rval;
+
+ switch (arg->type) {
+
+ /* bad case */
+ case FILTER_ARG_BOOLEAN:
+ return FILTER_VAL_FALSE + arg->boolean.value;
+
+ /* good cases: */
+ case FILTER_ARG_STR:
+ case FILTER_ARG_VALUE:
+ case FILTER_ARG_FIELD:
+ return FILTER_VAL_NORM;
+
+ case FILTER_ARG_EXP:
+ lval = test_arg(arg, arg->exp.left);
+ if (lval != FILTER_VAL_NORM)
+ return lval;
+ rval = test_arg(arg, arg->exp.right);
+ if (rval != FILTER_VAL_NORM)
+ return rval;
+ return FILTER_VAL_NORM;
+
+ case FILTER_ARG_NUM:
+ lval = test_arg(arg, arg->num.left);
+ if (lval != FILTER_VAL_NORM)
+ return lval;
+ rval = test_arg(arg, arg->num.right);
+ if (rval != FILTER_VAL_NORM)
+ return rval;
+ return FILTER_VAL_NORM;
+
+ case FILTER_ARG_OP:
+ if (arg->op.type != FILTER_OP_NOT) {
+ lval = test_arg(arg, arg->op.left);
+ switch (lval) {
+ case FILTER_VAL_NORM:
+ break;
+ case FILTER_VAL_TRUE:
+ if (arg->op.type == FILTER_OP_OR)
+ return FILTER_VAL_TRUE;
+ rval = test_arg(arg, arg->op.right);
+ if (rval != FILTER_VAL_NORM)
+ return rval;
+
+ reparent_op_arg(parent, arg, arg->op.right);
+ return FILTER_VAL_NORM;
+
+ case FILTER_VAL_FALSE:
+ if (arg->op.type == FILTER_OP_AND)
+ return FILTER_VAL_FALSE;
+ rval = test_arg(arg, arg->op.right);
+ if (rval != FILTER_VAL_NORM)
+ return rval;
+
+ reparent_op_arg(parent, arg, arg->op.right);
+ return FILTER_VAL_NORM;
+ }
+ }
+
+ rval = test_arg(arg, arg->op.right);
+ switch (rval) {
+ case FILTER_VAL_NORM:
+ break;
+ case FILTER_VAL_TRUE:
+ if (arg->op.type == FILTER_OP_OR)
+ return FILTER_VAL_TRUE;
+ if (arg->op.type == FILTER_OP_NOT)
+ return FILTER_VAL_FALSE;
+
+ reparent_op_arg(parent, arg, arg->op.left);
+ return FILTER_VAL_NORM;
+
+ case FILTER_VAL_FALSE:
+ if (arg->op.type == FILTER_OP_AND)
+ return FILTER_VAL_FALSE;
+ if (arg->op.type == FILTER_OP_NOT)
+ return FILTER_VAL_TRUE;
+
+ reparent_op_arg(parent, arg, arg->op.left);
+ return FILTER_VAL_NORM;
+ }
+
+ return FILTER_VAL_NORM;
+ default:
+ die("bad arg in filter tree");
+ }
+ return FILTER_VAL_NORM;
+}
+
+/* Remove any unknown event fields */
+static struct filter_arg *collapse_tree(struct filter_arg *arg)
+{
+ enum filter_vals ret;
+
+ ret = test_arg(arg, arg);
+ switch (ret) {
+ case FILTER_VAL_NORM:
+ return arg;
+
+ case FILTER_VAL_TRUE:
+ case FILTER_VAL_FALSE:
+ free_arg(arg);
+ arg = allocate_arg();
+ arg->type = FILTER_ARG_BOOLEAN;
+ arg->boolean.value = ret == FILTER_VAL_TRUE;
+ }
+
+ return arg;
+}
+
+static int
+process_filter(struct event_format *event, struct filter_arg **parg,
+ char **error_str, int not)
+{
+ enum event_type type;
+ char *token = NULL;
+ struct filter_arg *current_op = NULL;
+ struct filter_arg *current_exp = NULL;
+ struct filter_arg *left_item = NULL;
+ struct filter_arg *arg = NULL;
+ enum op_type op_type;
+ enum filter_op_type btype;
+ enum filter_exp_type etype;
+ enum filter_cmp_type ctype;
+ int ret;
+
+ *parg = NULL;
+
+ do {
+ free(token);
+ type = read_token(&token);
+ switch (type) {
+ case EVENT_SQUOTE:
+ case EVENT_DQUOTE:
+ case EVENT_ITEM:
+ arg = create_arg_item(event, token, type, error_str);
+ if (!arg)
+ goto fail;
+ if (!left_item)
+ left_item = arg;
+ else if (current_exp) {
+ ret = add_right(current_exp, arg, error_str);
+ if (ret < 0)
+ goto fail;
+ left_item = NULL;
+ /* Not's only one one expression */
+ if (not) {
+ arg = NULL;
+ if (current_op)
+ goto fail_print;
+ free(token);
+ *parg = current_exp;
+ return 0;
+ }
+ } else
+ goto fail_print;
+ arg = NULL;
+ break;
+
+ case EVENT_DELIM:
+ if (*token == ',') {
+ show_error(error_str,
+ "Illegal token ','");
+ goto fail;
+ }
+
+ if (*token == '(') {
+ if (left_item) {
+ show_error(error_str,
+ "Open paren can not come after item");
+ goto fail;
+ }
+ if (current_exp) {
+ show_error(error_str,
+ "Open paren can not come after expression");
+ goto fail;
+ }
+
+ ret = process_filter(event, &arg, error_str, 0);
+ if (ret != 1) {
+ if (ret == 0)
+ show_error(error_str,
+ "Unbalanced number of '('");
+ goto fail;
+ }
+ ret = 0;
+
+ /* A not wants just one expression */
+ if (not) {
+ if (current_op)
+ goto fail_print;
+ *parg = arg;
+ return 0;
+ }
+
+ if (current_op)
+ ret = add_right(current_op, arg, error_str);
+ else
+ current_exp = arg;
+
+ if (ret < 0)
+ goto fail;
+
+ } else { /* ')' */
+ if (!current_op && !current_exp)
+ goto fail_print;
+
+ /* Make sure everything is finished at this level */
+ if (current_exp && !check_op_done(current_exp))
+ goto fail_print;
+ if (current_op && !check_op_done(current_op))
+ goto fail_print;
+
+ if (current_op)
+ *parg = current_op;
+ else
+ *parg = current_exp;
+ return 1;
+ }
+ break;
+
+ case EVENT_OP:
+ op_type = process_op(token, &btype, &ctype, &etype);
+
+ /* All expect a left arg except for NOT */
+ switch (op_type) {
+ case OP_BOOL:
+ /* Logic ops need a left expression */
+ if (!current_exp && !current_op)
+ goto fail_print;
+ /* fall through */
+ case OP_NOT:
+ /* logic only processes ops and exp */
+ if (left_item)
+ goto fail_print;
+ break;
+ case OP_EXP:
+ case OP_CMP:
+ if (!left_item)
+ goto fail_print;
+ break;
+ case OP_NONE:
+ show_error(error_str,
+ "Unknown op token %s", token);
+ goto fail;
+ }
+
+ ret = 0;
+ switch (op_type) {
+ case OP_BOOL:
+ arg = create_arg_op(btype);
+ if (current_op)
+ ret = add_left(arg, current_op);
+ else
+ ret = add_left(arg, current_exp);
+ current_op = arg;
+ current_exp = NULL;
+ break;
+
+ case OP_NOT:
+ arg = create_arg_op(btype);
+ if (current_op)
+ ret = add_right(current_op, arg, error_str);
+ if (ret < 0)
+ goto fail;
+ current_exp = arg;
+ ret = process_filter(event, &arg, error_str, 1);
+ if (ret < 0)
+ goto fail;
+ ret = add_right(current_exp, arg, error_str);
+ if (ret < 0)
+ goto fail;
+ break;
+
+ case OP_EXP:
+ case OP_CMP:
+ if (op_type == OP_EXP)
+ arg = create_arg_exp(etype);
+ else
+ arg = create_arg_cmp(ctype);
+
+ if (current_op)
+ ret = add_right(current_op, arg, error_str);
+ if (ret < 0)
+ goto fail;
+ ret = add_left(arg, left_item);
+ if (ret < 0) {
+ arg = NULL;
+ goto fail_print;
+ }
+ current_exp = arg;
+ break;
+ default:
+ break;
+ }
+ arg = NULL;
+ if (ret < 0)
+ goto fail_print;
+ break;
+ case EVENT_NONE:
+ break;
+ default:
+ goto fail_print;
+ }
+ } while (type != EVENT_NONE);
+
+ if (!current_op && !current_exp)
+ goto fail_print;
+
+ if (!current_op)
+ current_op = current_exp;
+
+ current_op = collapse_tree(current_op);
+
+ *parg = current_op;
+
+ return 0;
+
+ fail_print:
+ show_error(error_str, "Syntax error");
+ fail:
+ free_arg(current_op);
+ free_arg(current_exp);
+ free_arg(arg);
+ free(token);
+ return -1;
+}
+
+static int
+process_event(struct event_format *event, const char *filter_str,
+ struct filter_arg **parg, char **error_str)
+{
+ int ret;
+
+ pevent_buffer_init(filter_str, strlen(filter_str));
+
+ ret = process_filter(event, parg, error_str, 0);
+ if (ret == 1) {
+ show_error(error_str,
+ "Unbalanced number of ')'");
+ return -1;
+ }
+ if (ret < 0)
+ return ret;
+
+ /* If parg is NULL, then make it into FALSE */
+ if (!*parg) {
+ *parg = allocate_arg();
+ (*parg)->type = FILTER_ARG_BOOLEAN;
+ (*parg)->boolean.value = FILTER_FALSE;
+ }
+
+ return 0;
+}
+
+static int filter_event(struct event_filter *filter,
+ struct event_format *event,
+ const char *filter_str, char **error_str)
+{
+ struct filter_type *filter_type;
+ struct filter_arg *arg;
+ int ret;
+
+ if (filter_str) {
+ ret = process_event(event, filter_str, &arg, error_str);
+ if (ret < 0)
+ return ret;
+
+ } else {
+ /* just add a TRUE arg */
+ arg = allocate_arg();
+ arg->type = FILTER_ARG_BOOLEAN;
+ arg->boolean.value = FILTER_TRUE;
+ }
+
+ filter_type = add_filter_type(filter, event->id);
+ if (filter_type->filter)
+ free_arg(filter_type->filter);
+ filter_type->filter = arg;
+
+ return 0;
+}
+
+/**
+ * pevent_filter_add_filter_str - add a new filter
+ * @filter: the event filter to add to
+ * @filter_str: the filter string that contains the filter
+ * @error_str: string containing reason for failed filter
+ *
+ * Returns 0 if the filter was successfully added
+ * -1 if there was an error.
+ *
+ * On error, if @error_str points to a string pointer,
+ * it is set to the reason that the filter failed.
+ * This string must be freed with "free".
+ */
+int pevent_filter_add_filter_str(struct event_filter *filter,
+ const char *filter_str,
+ char **error_str)
+{
+ struct pevent *pevent = filter->pevent;
+ struct event_list *event;
+ struct event_list *events = NULL;
+ const char *filter_start;
+ const char *next_event;
+ char *this_event;
+ char *event_name = NULL;
+ char *sys_name = NULL;
+ char *sp;
+ int rtn = 0;
+ int len;
+ int ret;
+
+ /* clear buffer to reset show error */
+ pevent_buffer_init("", 0);
+
+ if (error_str)
+ *error_str = NULL;
+
+ filter_start = strchr(filter_str, ':');
+ if (filter_start)
+ len = filter_start - filter_str;
+ else
+ len = strlen(filter_str);
+
+
+ do {
+ next_event = strchr(filter_str, ',');
+ if (next_event &&
+ (!filter_start || next_event < filter_start))
+ len = next_event - filter_str;
+ else if (filter_start)
+ len = filter_start - filter_str;
+ else
+ len = strlen(filter_str);
+
+ this_event = malloc_or_die(len + 1);
+ memcpy(this_event, filter_str, len);
+ this_event[len] = 0;
+
+ if (next_event)
+ next_event++;
+
+ filter_str = next_event;
+
+ sys_name = strtok_r(this_event, "/", &sp);
+ event_name = strtok_r(NULL, "/", &sp);
+
+ if (!sys_name) {
+ show_error(error_str, "No filter found");
+ /* This can only happen when events is NULL, but still */
+ free_events(events);
+ free(this_event);
+ return -1;
+ }
+
+ /* Find this event */
+ ret = find_event(pevent, &events, strim(sys_name), strim(event_name));
+ if (ret < 0) {
+ if (event_name)
+ show_error(error_str,
+ "No event found under '%s.%s'",
+ sys_name, event_name);
+ else
+ show_error(error_str,
+ "No event found under '%s'",
+ sys_name);
+ free_events(events);
+ free(this_event);
+ return -1;
+ }
+ free(this_event);
+ } while (filter_str);
+
+ /* Skip the ':' */
+ if (filter_start)
+ filter_start++;
+
+ /* filter starts here */
+ for (event = events; event; event = event->next) {
+ ret = filter_event(filter, event->event, filter_start,
+ error_str);
+ /* Failures are returned if a parse error happened */
+ if (ret < 0)
+ rtn = ret;
+
+ if (ret >= 0 && pevent->test_filters) {
+ char *test;
+ test = pevent_filter_make_string(filter, event->event->id);
+ printf(" '%s: %s'\n", event->event->name, test);
+ free(test);
+ }
+ }
+
+ free_events(events);
+
+ if (rtn >= 0 && pevent->test_filters)
+ exit(0);
+
+ return rtn;
+}
+
+static void free_filter_type(struct filter_type *filter_type)
+{
+ free_arg(filter_type->filter);
+}
+
+/**
+ * pevent_filter_remove_event - remove a filter for an event
+ * @filter: the event filter to remove from
+ * @event_id: the event to remove a filter for
+ *
+ * Removes the filter saved for an event defined by @event_id
+ * from the @filter.
+ *
+ * Returns 1: if an event was removed
+ * 0: if the event was not found
+ */
+int pevent_filter_remove_event(struct event_filter *filter,
+ int event_id)
+{
+ struct filter_type *filter_type;
+ unsigned long len;
+
+ if (!filter->filters)
+ return 0;
+
+ filter_type = find_filter_type(filter, event_id);
+
+ if (!filter_type)
+ return 0;
+
+ free_filter_type(filter_type);
+
+ /* The filter_type points into the event_filters array */
+ len = (unsigned long)(filter->event_filters + filter->filters) -
+ (unsigned long)(filter_type + 1);
+
+ memmove(filter_type, filter_type + 1, len);
+ filter->filters--;
+
+ memset(&filter->event_filters[filter->filters], 0,
+ sizeof(*filter_type));
+
+ return 1;
+}
+
+/**
+ * pevent_filter_reset - clear all filters in a filter
+ * @filter: the event filter to reset
+ *
+ * Removes all filters from a filter and resets it.
+ */
+void pevent_filter_reset(struct event_filter *filter)
+{
+ int i;
+
+ for (i = 0; i < filter->filters; i++)
+ free_filter_type(&filter->event_filters[i]);
+
+ free(filter->event_filters);
+ filter->filters = 0;
+ filter->event_filters = NULL;
+}
+
+void pevent_filter_free(struct event_filter *filter)
+{
+ pevent_unref(filter->pevent);
+
+ pevent_filter_reset(filter);
+
+ free(filter);
+}
+
+static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg);
+
+static int copy_filter_type(struct event_filter *filter,
+ struct event_filter *source,
+ struct filter_type *filter_type)
+{
+ struct filter_arg *arg;
+ struct event_format *event;
+ const char *sys;
+ const char *name;
+ char *str;
+
+ /* Can't assume that the pevent's are the same */
+ sys = filter_type->event->system;
+ name = filter_type->event->name;
+ event = pevent_find_event_by_name(filter->pevent, sys, name);
+ if (!event)
+ return -1;
+
+ str = arg_to_str(source, filter_type->filter);
+ if (!str)
+ return -1;
+
+ if (strcmp(str, "TRUE") == 0 || strcmp(str, "FALSE") == 0) {
+ /* Add trivial event */
+ arg = allocate_arg();
+ arg->type = FILTER_ARG_BOOLEAN;
+ if (strcmp(str, "TRUE") == 0)
+ arg->boolean.value = 1;
+ else
+ arg->boolean.value = 0;
+
+ filter_type = add_filter_type(filter, event->id);
+ filter_type->filter = arg;
+
+ free(str);
+ return 0;
+ }
+
+ filter_event(filter, event, str, NULL);
+ free(str);
+
+ return 0;
+}
+
+/**
+ * pevent_filter_copy - copy a filter using another filter
+ * @dest - the filter to copy to
+ * @source - the filter to copy from
+ *
+ * Returns 0 on success and -1 if not all filters were copied
+ */
+int pevent_filter_copy(struct event_filter *dest, struct event_filter *source)
+{
+ int ret = 0;
+ int i;
+
+ pevent_filter_reset(dest);
+
+ for (i = 0; i < source->filters; i++) {
+ if (copy_filter_type(dest, source, &source->event_filters[i]))
+ ret = -1;
+ }
+ return ret;
+}
+
+
+/**
+ * pevent_update_trivial - update the trivial filters with the given filter
+ * @dest - the filter to update
+ * @source - the filter as the source of the update
+ * @type - the type of trivial filter to update.
+ *
+ * Scan dest for trivial events matching @type to replace with the source.
+ *
+ * Returns 0 on success and -1 if there was a problem updating, but
+ * events may have still been updated on error.
+ */
+int pevent_update_trivial(struct event_filter *dest, struct event_filter *source,
+ enum filter_trivial_type type)
+{
+ struct pevent *src_pevent;
+ struct pevent *dest_pevent;
+ struct event_format *event;
+ struct filter_type *filter_type;
+ struct filter_arg *arg;
+ char *str;
+ int i;
+
+ src_pevent = source->pevent;
+ dest_pevent = dest->pevent;
+
+ /* Do nothing if either of the filters has nothing to filter */
+ if (!dest->filters || !source->filters)
+ return 0;
+
+ for (i = 0; i < dest->filters; i++) {
+ filter_type = &dest->event_filters[i];
+ arg = filter_type->filter;
+ if (arg->type != FILTER_ARG_BOOLEAN)
+ continue;
+ if ((arg->boolean.value && type == FILTER_TRIVIAL_FALSE) ||
+ (!arg->boolean.value && type == FILTER_TRIVIAL_TRUE))
+ continue;
+
+ event = filter_type->event;
+
+ if (src_pevent != dest_pevent) {
+ /* do a look up */
+ event = pevent_find_event_by_name(src_pevent,
+ event->system,
+ event->name);
+ if (!event)
+ return -1;
+ }
+
+ str = pevent_filter_make_string(source, event->id);
+ if (!str)
+ continue;
+
+ /* Don't bother if the filter is trivial too */
+ if (strcmp(str, "TRUE") != 0 && strcmp(str, "FALSE") != 0)
+ filter_event(dest, event, str, NULL);
+ free(str);
+ }
+ return 0;
+}
+
+/**
+ * pevent_filter_clear_trivial - clear TRUE and FALSE filters
+ * @filter: the filter to remove trivial filters from
+ * @type: remove only true, false, or both
+ *
+ * Removes filters that only contain a TRUE or FALES boolean arg.
+ */
+void pevent_filter_clear_trivial(struct event_filter *filter,
+ enum filter_trivial_type type)
+{
+ struct filter_type *filter_type;
+ int count = 0;
+ int *ids = NULL;
+ int i;
+
+ if (!filter->filters)
+ return;
+
+ /*
+ * Two steps, first get all ids with trivial filters.
+ * then remove those ids.
+ */
+ for (i = 0; i < filter->filters; i++) {
+ filter_type = &filter->event_filters[i];
+ if (filter_type->filter->type != FILTER_ARG_BOOLEAN)
+ continue;
+ switch (type) {
+ case FILTER_TRIVIAL_FALSE:
+ if (filter_type->filter->boolean.value)
+ continue;
+ case FILTER_TRIVIAL_TRUE:
+ if (!filter_type->filter->boolean.value)
+ continue;
+ default:
+ break;
+ }
+
+ ids = realloc(ids, sizeof(*ids) * (count + 1));
+ if (!ids)
+ die("Can't allocate ids");
+ ids[count++] = filter_type->event_id;
+ }
+
+ if (!count)
+ return;
+
+ for (i = 0; i < count; i++)
+ pevent_filter_remove_event(filter, ids[i]);
+
+ free(ids);
+}
+
+/**
+ * pevent_filter_event_has_trivial - return true event contains trivial filter
+ * @filter: the filter with the information
+ * @event_id: the id of the event to test
+ * @type: trivial type to test for (TRUE, FALSE, EITHER)
+ *
+ * Returns 1 if the event contains a matching trivial type
+ * otherwise 0.
+ */
+int pevent_filter_event_has_trivial(struct event_filter *filter,
+ int event_id,
+ enum filter_trivial_type type)
+{
+ struct filter_type *filter_type;
+
+ if (!filter->filters)
+ return 0;
+
+ filter_type = find_filter_type(filter, event_id);
+
+ if (!filter_type)
+ return 0;
+
+ if (filter_type->filter->type != FILTER_ARG_BOOLEAN)
+ return 0;
+
+ switch (type) {
+ case FILTER_TRIVIAL_FALSE:
+ return !filter_type->filter->boolean.value;
+
+ case FILTER_TRIVIAL_TRUE:
+ return filter_type->filter->boolean.value;
+ default:
+ return 1;
+ }
+}
+
+static int test_filter(struct event_format *event,
+ struct filter_arg *arg, struct pevent_record *record);
+
+static const char *
+get_comm(struct event_format *event, struct pevent_record *record)
+{
+ const char *comm;
+ int pid;
+
+ pid = pevent_data_pid(event->pevent, record);
+ comm = pevent_data_comm_from_pid(event->pevent, pid);
+ return comm;
+}
+
+static unsigned long long
+get_value(struct event_format *event,
+ struct format_field *field, struct pevent_record *record)
+{
+ unsigned long long val;
+
+ /* Handle our dummy "comm" field */
+ if (field == &comm) {
+ const char *name;
+
+ name = get_comm(event, record);
+ return (unsigned long)name;
+ }
+
+ pevent_read_number_field(field, record->data, &val);
+
+ if (!(field->flags & FIELD_IS_SIGNED))
+ return val;
+
+ switch (field->size) {
+ case 1:
+ return (char)val;
+ case 2:
+ return (short)val;
+ case 4:
+ return (int)val;
+ case 8:
+ return (long long)val;
+ }
+ return val;
+}
+
+static unsigned long long
+get_arg_value(struct event_format *event, struct filter_arg *arg, struct pevent_record *record);
+
+static unsigned long long
+get_exp_value(struct event_format *event, struct filter_arg *arg, struct pevent_record *record)
+{
+ unsigned long long lval, rval;
+
+ lval = get_arg_value(event, arg->exp.left, record);
+ rval = get_arg_value(event, arg->exp.right, record);
+
+ switch (arg->exp.type) {
+ case FILTER_EXP_ADD:
+ return lval + rval;
+
+ case FILTER_EXP_SUB:
+ return lval - rval;
+
+ case FILTER_EXP_MUL:
+ return lval * rval;
+
+ case FILTER_EXP_DIV:
+ return lval / rval;
+
+ case FILTER_EXP_MOD:
+ return lval % rval;
+
+ case FILTER_EXP_RSHIFT:
+ return lval >> rval;
+
+ case FILTER_EXP_LSHIFT:
+ return lval << rval;
+
+ case FILTER_EXP_AND:
+ return lval & rval;
+
+ case FILTER_EXP_OR:
+ return lval | rval;
+
+ case FILTER_EXP_XOR:
+ return lval ^ rval;
+
+ case FILTER_EXP_NOT:
+ default:
+ die("error in exp");
+ }
+ return 0;
+}
+
+static unsigned long long
+get_arg_value(struct event_format *event, struct filter_arg *arg, struct pevent_record *record)
+{
+ switch (arg->type) {
+ case FILTER_ARG_FIELD:
+ return get_value(event, arg->field.field, record);
+
+ case FILTER_ARG_VALUE:
+ if (arg->value.type != FILTER_NUMBER)
+ die("must have number field!");
+ return arg->value.val;
+
+ case FILTER_ARG_EXP:
+ return get_exp_value(event, arg, record);
+
+ default:
+ die("oops in filter");
+ }
+ return 0;
+}
+
+static int test_num(struct event_format *event,
+ struct filter_arg *arg, struct pevent_record *record)
+{
+ unsigned long long lval, rval;
+
+ lval = get_arg_value(event, arg->num.left, record);
+ rval = get_arg_value(event, arg->num.right, record);
+
+ switch (arg->num.type) {
+ case FILTER_CMP_EQ:
+ return lval == rval;
+
+ case FILTER_CMP_NE:
+ return lval != rval;
+
+ case FILTER_CMP_GT:
+ return lval > rval;
+
+ case FILTER_CMP_LT:
+ return lval < rval;
+
+ case FILTER_CMP_GE:
+ return lval >= rval;
+
+ case FILTER_CMP_LE:
+ return lval <= rval;
+
+ default:
+ /* ?? */
+ return 0;
+ }
+}
+
+static const char *get_field_str(struct filter_arg *arg, struct pevent_record *record)
+{
+ struct event_format *event;
+ struct pevent *pevent;
+ unsigned long long addr;
+ const char *val = NULL;
+ static char hex[64];
+
+ /* If the field is not a string convert it */
+ if (arg->str.field->flags & FIELD_IS_STRING) {
+ val = record->data + arg->str.field->offset;
+
+ /*
+ * We need to copy the data since we can't be sure the field
+ * is null terminated.
+ */
+ if (*(val + arg->str.field->size - 1)) {
+ /* copy it */
+ memcpy(arg->str.buffer, val, arg->str.field->size);
+ /* the buffer is already NULL terminated */
+ val = arg->str.buffer;
+ }
+
+ } else {
+ event = arg->str.field->event;
+ pevent = event->pevent;
+ addr = get_value(event, arg->str.field, record);
+
+ if (arg->str.field->flags & (FIELD_IS_POINTER | FIELD_IS_LONG))
+ /* convert to a kernel symbol */
+ val = pevent_find_function(pevent, addr);
+
+ if (val == NULL) {
+ /* just use the hex of the string name */
+ snprintf(hex, 64, "0x%llx", addr);
+ val = hex;
+ }
+ }
+
+ return val;
+}
+
+static int test_str(struct event_format *event,
+ struct filter_arg *arg, struct pevent_record *record)
+{
+ const char *val;
+
+ if (arg->str.field == &comm)
+ val = get_comm(event, record);
+ else
+ val = get_field_str(arg, record);
+
+ switch (arg->str.type) {
+ case FILTER_CMP_MATCH:
+ return strcmp(val, arg->str.val) == 0;
+
+ case FILTER_CMP_NOT_MATCH:
+ return strcmp(val, arg->str.val) != 0;
+
+ case FILTER_CMP_REGEX:
+ /* Returns zero on match */
+ return !regexec(&arg->str.reg, val, 0, NULL, 0);
+
+ case FILTER_CMP_NOT_REGEX:
+ return regexec(&arg->str.reg, val, 0, NULL, 0);
+
+ default:
+ /* ?? */
+ return 0;
+ }
+}
+
+static int test_op(struct event_format *event,
+ struct filter_arg *arg, struct pevent_record *record)
+{
+ switch (arg->op.type) {
+ case FILTER_OP_AND:
+ return test_filter(event, arg->op.left, record) &&
+ test_filter(event, arg->op.right, record);
+
+ case FILTER_OP_OR:
+ return test_filter(event, arg->op.left, record) ||
+ test_filter(event, arg->op.right, record);
+
+ case FILTER_OP_NOT:
+ return !test_filter(event, arg->op.right, record);
+
+ default:
+ /* ?? */
+ return 0;
+ }
+}
+
+static int test_filter(struct event_format *event,
+ struct filter_arg *arg, struct pevent_record *record)
+{
+ switch (arg->type) {
+ case FILTER_ARG_BOOLEAN:
+ /* easy case */
+ return arg->boolean.value;
+
+ case FILTER_ARG_OP:
+ return test_op(event, arg, record);
+
+ case FILTER_ARG_NUM:
+ return test_num(event, arg, record);
+
+ case FILTER_ARG_STR:
+ return test_str(event, arg, record);
+
+ case FILTER_ARG_EXP:
+ case FILTER_ARG_VALUE:
+ case FILTER_ARG_FIELD:
+ /*
+ * Expressions, fields and values evaluate
+ * to true if they return non zero
+ */
+ return !!get_arg_value(event, arg, record);
+
+ default:
+ die("oops!");
+ /* ?? */
+ return 0;
+ }
+}
+
+/**
+ * pevent_event_filtered - return true if event has filter
+ * @filter: filter struct with filter information
+ * @event_id: event id to test if filter exists
+ *
+ * Returns 1 if filter found for @event_id
+ * otherwise 0;
+ */
+int pevent_event_filtered(struct event_filter *filter,
+ int event_id)
+{
+ struct filter_type *filter_type;
+
+ if (!filter->filters)
+ return 0;
+
+ filter_type = find_filter_type(filter, event_id);
+
+ return filter_type ? 1 : 0;
+}
+
+/**
+ * pevent_filter_match - test if a record matches a filter
+ * @filter: filter struct with filter information
+ * @record: the record to test against the filter
+ *
+ * Returns:
+ * 1 - filter found for event and @record matches
+ * 0 - filter found for event and @record does not match
+ * -1 - no filter found for @record's event
+ * -2 - if no filters exist
+ */
+int pevent_filter_match(struct event_filter *filter,
+ struct pevent_record *record)
+{
+ struct pevent *pevent = filter->pevent;
+ struct filter_type *filter_type;
+ int event_id;
+
+ if (!filter->filters)
+ return FILTER_NONE;
+
+ event_id = pevent_data_type(pevent, record);
+
+ filter_type = find_filter_type(filter, event_id);
+
+ if (!filter_type)
+ return FILTER_NOEXIST;
+
+ return test_filter(filter_type->event, filter_type->filter, record) ?
+ FILTER_MATCH : FILTER_MISS;
+}
+
+static char *op_to_str(struct event_filter *filter, struct filter_arg *arg)
+{
+ char *str = NULL;
+ char *left = NULL;
+ char *right = NULL;
+ char *op = NULL;
+ int left_val = -1;
+ int right_val = -1;
+ int val;
+ int len;
+
+ switch (arg->op.type) {
+ case FILTER_OP_AND:
+ op = "&&";
+ /* fall through */
+ case FILTER_OP_OR:
+ if (!op)
+ op = "||";
+
+ left = arg_to_str(filter, arg->op.left);
+ right = arg_to_str(filter, arg->op.right);
+ if (!left || !right)
+ break;
+
+ /* Try to consolidate boolean values */
+ if (strcmp(left, "TRUE") == 0)
+ left_val = 1;
+ else if (strcmp(left, "FALSE") == 0)
+ left_val = 0;
+
+ if (strcmp(right, "TRUE") == 0)
+ right_val = 1;
+ else if (strcmp(right, "FALSE") == 0)
+ right_val = 0;
+
+ if (left_val >= 0) {
+ if ((arg->op.type == FILTER_OP_AND && !left_val) ||
+ (arg->op.type == FILTER_OP_OR && left_val)) {
+ /* Just return left value */
+ str = left;
+ left = NULL;
+ break;
+ }
+ if (right_val >= 0) {
+ /* just evaluate this. */
+ val = 0;
+ switch (arg->op.type) {
+ case FILTER_OP_AND:
+ val = left_val && right_val;
+ break;
+ case FILTER_OP_OR:
+ val = left_val || right_val;
+ break;
+ default:
+ break;
+ }
+ str = malloc_or_die(6);
+ if (val)
+ strcpy(str, "TRUE");
+ else
+ strcpy(str, "FALSE");
+ break;
+ }
+ }
+ if (right_val >= 0) {
+ if ((arg->op.type == FILTER_OP_AND && !right_val) ||
+ (arg->op.type == FILTER_OP_OR && right_val)) {
+ /* Just return right value */
+ str = right;
+ right = NULL;
+ break;
+ }
+ /* The right value is meaningless */
+ str = left;
+ left = NULL;
+ break;
+ }
+
+ len = strlen(left) + strlen(right) + strlen(op) + 10;
+ str = malloc_or_die(len);
+ snprintf(str, len, "(%s) %s (%s)",
+ left, op, right);
+ break;
+
+ case FILTER_OP_NOT:
+ op = "!";
+ right = arg_to_str(filter, arg->op.right);
+ if (!right)
+ break;
+
+ /* See if we can consolidate */
+ if (strcmp(right, "TRUE") == 0)
+ right_val = 1;
+ else if (strcmp(right, "FALSE") == 0)
+ right_val = 0;
+ if (right_val >= 0) {
+ /* just return the opposite */
+ str = malloc_or_die(6);
+ if (right_val)
+ strcpy(str, "FALSE");
+ else
+ strcpy(str, "TRUE");
+ break;
+ }
+ len = strlen(right) + strlen(op) + 3;
+ str = malloc_or_die(len);
+ snprintf(str, len, "%s(%s)", op, right);
+ break;
+
+ default:
+ /* ?? */
+ break;
+ }
+ free(left);
+ free(right);
+ return str;
+}
+
+static char *val_to_str(struct event_filter *filter, struct filter_arg *arg)
+{
+ char *str;
+
+ str = malloc_or_die(30);
+
+ snprintf(str, 30, "%lld", arg->value.val);
+
+ return str;
+}
+
+static char *field_to_str(struct event_filter *filter, struct filter_arg *arg)
+{
+ return strdup(arg->field.field->name);
+}
+
+static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg)
+{
+ char *lstr;
+ char *rstr;
+ char *op;
+ char *str = NULL;
+ int len;
+
+ lstr = arg_to_str(filter, arg->exp.left);
+ rstr = arg_to_str(filter, arg->exp.right);
+ if (!lstr || !rstr)
+ goto out;
+
+ switch (arg->exp.type) {
+ case FILTER_EXP_ADD:
+ op = "+";
+ break;
+ case FILTER_EXP_SUB:
+ op = "-";
+ break;
+ case FILTER_EXP_MUL:
+ op = "*";
+ break;
+ case FILTER_EXP_DIV:
+ op = "/";
+ break;
+ case FILTER_EXP_MOD:
+ op = "%";
+ break;
+ case FILTER_EXP_RSHIFT:
+ op = ">>";
+ break;
+ case FILTER_EXP_LSHIFT:
+ op = "<<";
+ break;
+ case FILTER_EXP_AND:
+ op = "&";
+ break;
+ case FILTER_EXP_OR:
+ op = "|";
+ break;
+ case FILTER_EXP_XOR:
+ op = "^";
+ break;
+ default:
+ die("oops in exp");
+ }
+
+ len = strlen(op) + strlen(lstr) + strlen(rstr) + 4;
+ str = malloc_or_die(len);
+ snprintf(str, len, "%s %s %s", lstr, op, rstr);
+out:
+ free(lstr);
+ free(rstr);
+
+ return str;
+}
+
+static char *num_to_str(struct event_filter *filter, struct filter_arg *arg)
+{
+ char *lstr;
+ char *rstr;
+ char *str = NULL;
+ char *op = NULL;
+ int len;
+
+ lstr = arg_to_str(filter, arg->num.left);
+ rstr = arg_to_str(filter, arg->num.right);
+ if (!lstr || !rstr)
+ goto out;
+
+ switch (arg->num.type) {
+ case FILTER_CMP_EQ:
+ op = "==";
+ /* fall through */
+ case FILTER_CMP_NE:
+ if (!op)
+ op = "!=";
+ /* fall through */
+ case FILTER_CMP_GT:
+ if (!op)
+ op = ">";
+ /* fall through */
+ case FILTER_CMP_LT:
+ if (!op)
+ op = "<";
+ /* fall through */
+ case FILTER_CMP_GE:
+ if (!op)
+ op = ">=";
+ /* fall through */
+ case FILTER_CMP_LE:
+ if (!op)
+ op = "<=";
+
+ len = strlen(lstr) + strlen(op) + strlen(rstr) + 4;
+ str = malloc_or_die(len);
+ sprintf(str, "%s %s %s", lstr, op, rstr);
+
+ break;
+
+ default:
+ /* ?? */
+ break;
+ }
+
+out:
+ free(lstr);
+ free(rstr);
+ return str;
+}
+
+static char *str_to_str(struct event_filter *filter, struct filter_arg *arg)
+{
+ char *str = NULL;
+ char *op = NULL;
+ int len;
+
+ switch (arg->str.type) {
+ case FILTER_CMP_MATCH:
+ op = "==";
+ /* fall through */
+ case FILTER_CMP_NOT_MATCH:
+ if (!op)
+ op = "!=";
+ /* fall through */
+ case FILTER_CMP_REGEX:
+ if (!op)
+ op = "=~";
+ /* fall through */
+ case FILTER_CMP_NOT_REGEX:
+ if (!op)
+ op = "!~";
+
+ len = strlen(arg->str.field->name) + strlen(op) +
+ strlen(arg->str.val) + 6;
+ str = malloc_or_die(len);
+ snprintf(str, len, "%s %s \"%s\"",
+ arg->str.field->name,
+ op, arg->str.val);
+ break;
+
+ default:
+ /* ?? */
+ break;
+ }
+ return str;
+}
+
+static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg)
+{
+ char *str;
+
+ switch (arg->type) {
+ case FILTER_ARG_BOOLEAN:
+ str = malloc_or_die(6);
+ if (arg->boolean.value)
+ strcpy(str, "TRUE");
+ else
+ strcpy(str, "FALSE");
+ return str;
+
+ case FILTER_ARG_OP:
+ return op_to_str(filter, arg);
+
+ case FILTER_ARG_NUM:
+ return num_to_str(filter, arg);
+
+ case FILTER_ARG_STR:
+ return str_to_str(filter, arg);
+
+ case FILTER_ARG_VALUE:
+ return val_to_str(filter, arg);
+
+ case FILTER_ARG_FIELD:
+ return field_to_str(filter, arg);
+
+ case FILTER_ARG_EXP:
+ return exp_to_str(filter, arg);
+
+ default:
+ /* ?? */
+ return NULL;
+ }
+
+}
+
+/**
+ * pevent_filter_make_string - return a string showing the filter
+ * @filter: filter struct with filter information
+ * @event_id: the event id to return the filter string with
+ *
+ * Returns a string that displays the filter contents.
+ * This string must be freed with free(str).
+ * NULL is returned if no filter is found.
+ */
+char *
+pevent_filter_make_string(struct event_filter *filter, int event_id)
+{
+ struct filter_type *filter_type;
+
+ if (!filter->filters)
+ return NULL;
+
+ filter_type = find_filter_type(filter, event_id);
+
+ if (!filter_type)
+ return NULL;
+
+ return arg_to_str(filter, filter_type->filter);
+}
+
+/**
+ * pevent_filter_compare - compare two filters and return if they are the same
+ * @filter1: Filter to compare with @filter2
+ * @filter2: Filter to compare with @filter1
+ *
+ * Returns:
+ * 1 if the two filters hold the same content.
+ * 0 if they do not.
+ */
+int pevent_filter_compare(struct event_filter *filter1, struct event_filter *filter2)
+{
+ struct filter_type *filter_type1;
+ struct filter_type *filter_type2;
+ char *str1, *str2;
+ int result;
+ int i;
+
+ /* Do the easy checks first */
+ if (filter1->filters != filter2->filters)
+ return 0;
+ if (!filter1->filters && !filter2->filters)
+ return 1;
+
+ /*
+ * Now take a look at each of the events to see if they have the same
+ * filters to them.
+ */
+ for (i = 0; i < filter1->filters; i++) {
+ filter_type1 = &filter1->event_filters[i];
+ filter_type2 = find_filter_type(filter2, filter_type1->event_id);
+ if (!filter_type2)
+ break;
+ if (filter_type1->filter->type != filter_type2->filter->type)
+ break;
+ switch (filter_type1->filter->type) {
+ case FILTER_TRIVIAL_FALSE:
+ case FILTER_TRIVIAL_TRUE:
+ /* trivial types just need the type compared */
+ continue;
+ default:
+ break;
+ }
+ /* The best way to compare complex filters is with strings */
+ str1 = arg_to_str(filter1, filter_type1->filter);
+ str2 = arg_to_str(filter2, filter_type2->filter);
+ if (str1 && str2)
+ result = strcmp(str1, str2) != 0;
+ else
+ /* bail out if allocation fails */
+ result = 1;
+
+ free(str1);
+ free(str2);
+ if (result)
+ break;
+ }
+
+ if (i < filter1->filters)
+ return 0;
+ return 1;
+}
+
diff --git a/traceevent/parse-utils.c b/traceevent/parse-utils.c
new file mode 100644
index 0000000..bba701c
--- /dev/null
+++ b/traceevent/parse-utils.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License (not later!)
+ *
+ * This program 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <errno.h>
+
+#define __weak __attribute__((weak))
+
+void __vdie(const char *fmt, va_list ap)
+{
+ int ret = errno;
+
+ if (errno)
+ perror("trace-cmd");
+ else
+ ret = -1;
+
+ fprintf(stderr, " ");
+ vfprintf(stderr, fmt, ap);
+
+ fprintf(stderr, "\n");
+ exit(ret);
+}
+
+void __die(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ __vdie(fmt, ap);
+ va_end(ap);
+}
+
+void __weak die(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ __vdie(fmt, ap);
+ va_end(ap);
+}
+
+void __vwarning(const char *fmt, va_list ap)
+{
+ if (errno)
+ perror("trace-cmd");
+ errno = 0;
+
+ fprintf(stderr, " ");
+ vfprintf(stderr, fmt, ap);
+
+ fprintf(stderr, "\n");
+}
+
+void __warning(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ __vwarning(fmt, ap);
+ va_end(ap);
+}
+
+void __weak warning(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ __vwarning(fmt, ap);
+ va_end(ap);
+}
+
+void __vpr_stat(const char *fmt, va_list ap)
+{
+ vprintf(fmt, ap);
+ printf("\n");
+}
+
+void __pr_stat(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ __vpr_stat(fmt, ap);
+ va_end(ap);
+}
+
+void __weak vpr_stat(const char *fmt, va_list ap)
+{
+ __vpr_stat(fmt, ap);
+}
+
+void __weak pr_stat(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ __vpr_stat(fmt, ap);
+ va_end(ap);
+}
+
+void __weak *malloc_or_die(unsigned int size)
+{
+ void *data;
+
+ data = malloc(size);
+ if (!data)
+ die("malloc");
+ return data;
+}
diff --git a/traceevent/trace-seq.c b/traceevent/trace-seq.c
new file mode 100644
index 0000000..d7f2e68
--- /dev/null
+++ b/traceevent/trace-seq.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2009 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License (not later!)
+ *
+ * This program 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "event-parse.h"
+#include "event-utils.h"
+
+/*
+ * The TRACE_SEQ_POISON is to catch the use of using
+ * a trace_seq structure after it was destroyed.
+ */
+#define TRACE_SEQ_POISON ((void *)0xdeadbeef)
+#define TRACE_SEQ_CHECK(s) \
+do { \
+ if ((s)->buffer == TRACE_SEQ_POISON) \
+ die("Usage of trace_seq after it was destroyed"); \
+} while (0)
+
+/**
+ * trace_seq_init - initialize the trace_seq structure
+ * @s: a pointer to the trace_seq structure to initialize
+ */
+void trace_seq_init(struct trace_seq *s)
+{
+ s->len = 0;
+ s->readpos = 0;
+ s->buffer_size = TRACE_SEQ_BUF_SIZE;
+ s->buffer = malloc_or_die(s->buffer_size);
+}
+
+/**
+ * trace_seq_reset - re-initialize the trace_seq structure
+ * @s: a pointer to the trace_seq structure to reset
+ */
+void trace_seq_reset(struct trace_seq *s)
+{
+ if (!s)
+ return;
+ TRACE_SEQ_CHECK(s);
+ s->len = 0;
+ s->readpos = 0;
+}
+
+/**
+ * trace_seq_destroy - free up memory of a trace_seq
+ * @s: a pointer to the trace_seq to free the buffer
+ *
+ * Only frees the buffer, not the trace_seq struct itself.
+ */
+void trace_seq_destroy(struct trace_seq *s)
+{
+ if (!s)
+ return;
+ TRACE_SEQ_CHECK(s);
+ free(s->buffer);
+ s->buffer = TRACE_SEQ_POISON;
+}
+
+static void expand_buffer(struct trace_seq *s)
+{
+ s->buffer_size += TRACE_SEQ_BUF_SIZE;
+ s->buffer = realloc(s->buffer, s->buffer_size);
+ if (!s->buffer)
+ die("Can't allocate trace_seq buffer memory");
+}
+
+/**
+ * trace_seq_printf - sequence printing of trace information
+ * @s: trace sequence descriptor
+ * @fmt: printf format string
+ *
+ * It returns 0 if the trace oversizes the buffer's free
+ * space, 1 otherwise.
+ *
+ * The tracer may use either sequence operations or its own
+ * copy to user routines. To simplify formating of a trace
+ * trace_seq_printf is used to store strings into a special
+ * buffer (@s). Then the output may be either used by
+ * the sequencer or pulled into another buffer.
+ */
+int
+trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
+{
+ va_list ap;
+ int len;
+ int ret;
+
+ TRACE_SEQ_CHECK(s);
+
+ try_again:
+ len = (s->buffer_size - 1) - s->len;
+
+ va_start(ap, fmt);
+ ret = vsnprintf(s->buffer + s->len, len, fmt, ap);
+ va_end(ap);
+
+ if (ret >= len) {
+ expand_buffer(s);
+ goto try_again;
+ }
+
+ s->len += ret;
+
+ return 1;
+}
+
+/**
+ * trace_seq_vprintf - sequence printing of trace information
+ * @s: trace sequence descriptor
+ * @fmt: printf format string
+ *
+ * The tracer may use either sequence operations or its own
+ * copy to user routines. To simplify formating of a trace
+ * trace_seq_printf is used to store strings into a special
+ * buffer (@s). Then the output may be either used by
+ * the sequencer or pulled into another buffer.
+ */
+int
+trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args)
+{
+ int len;
+ int ret;
+
+ TRACE_SEQ_CHECK(s);
+
+ try_again:
+ len = (s->buffer_size - 1) - s->len;
+
+ ret = vsnprintf(s->buffer + s->len, len, fmt, args);
+
+ if (ret >= len) {
+ expand_buffer(s);
+ goto try_again;
+ }
+
+ s->len += ret;
+
+ return len;
+}
+
+/**
+ * trace_seq_puts - trace sequence printing of simple string
+ * @s: trace sequence descriptor
+ * @str: simple string to record
+ *
+ * The tracer may use either the sequence operations or its own
+ * copy to user routines. This function records a simple string
+ * into a special buffer (@s) for later retrieval by a sequencer
+ * or other mechanism.
+ */
+int trace_seq_puts(struct trace_seq *s, const char *str)
+{
+ int len;
+
+ TRACE_SEQ_CHECK(s);
+
+ len = strlen(str);
+
+ while (len > ((s->buffer_size - 1) - s->len))
+ expand_buffer(s);
+
+ memcpy(s->buffer + s->len, str, len);
+ s->len += len;
+
+ return len;
+}
+
+int trace_seq_putc(struct trace_seq *s, unsigned char c)
+{
+ TRACE_SEQ_CHECK(s);
+
+ while (s->len >= (s->buffer_size - 1))
+ expand_buffer(s);
+
+ s->buffer[s->len++] = c;
+
+ return 1;
+}
+
+void trace_seq_terminate(struct trace_seq *s)
+{
+ TRACE_SEQ_CHECK(s);
+
+ /* There's always one character left on the buffer */
+ s->buffer[s->len] = 0;
+}
+
+int trace_seq_do_printf(struct trace_seq *s)
+{
+ TRACE_SEQ_CHECK(s);
+ return printf("%.*s", s->len, s->buffer);
+}