-
Notifications
You must be signed in to change notification settings - Fork 23
contrib: add a lua module allowing to display cdba board status with conky #99
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
brgl
wants to merge
1
commit into
linux-msm:master
Choose a base branch
from
brgl:contrib/conky-lua
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,238 @@ | ||
| -- SPDX-License-Identifier: BSD-3-Clause | ||
| -- SPDX-FileCopyrightText: 2026 Qualcomm Technologies, Inc. and/or its subsidiaries | ||
|
|
||
| local yaml = require("lyaml") | ||
| local stat = require("posix.sys.stat") | ||
| local unistd = require("posix.unistd") | ||
| local pwd = require("posix.pwd") | ||
|
|
||
| local function read_cdba_cfg() | ||
| local pw = pwd.getpwnam("cdba") | ||
| if not pw then | ||
| return nil | ||
| end | ||
|
|
||
| local fd = io.open(pw.pw_dir .. "/.cdba", "r") | ||
| if not fd then | ||
| fd = io.open("/etc/cdba", "r") | ||
| if not fd then | ||
| return nil | ||
| end | ||
| end | ||
|
|
||
| local data = fd:read("*a") | ||
| fd:close() | ||
|
|
||
| return yaml.load(data) | ||
| end | ||
|
|
||
| local cdba_cfg = read_cdba_cfg() | ||
|
|
||
| local function file_exists(path) | ||
| local fd = io.open(path, "r") | ||
| if fd then | ||
| fd:close() | ||
| return true | ||
| end | ||
|
|
||
| return false | ||
| end | ||
|
|
||
| local function stat_file(path) | ||
| local st, err = stat.stat(path) | ||
| if not st then | ||
| return nil, ("stat failed for '%s': %s"):format(path, err) | ||
| end | ||
|
|
||
| return st | ||
| end | ||
|
|
||
| local function dev_major(dev) | ||
| local hi = math.floor(dev / 2 ^ 32) | ||
|
|
||
| return (math.floor(dev / 2 ^ 8) % 2 ^ 12) + (hi - hi % 2 ^ 12) | ||
| end | ||
|
|
||
| local function dev_minor(dev) | ||
| local mid = math.floor(dev / 2 ^ 12) | ||
|
|
||
| return (dev % 2 ^ 8) + (mid - mid % 2 ^ 8) | ||
| end | ||
|
|
||
| local function parse_proc_locks() | ||
| local fd, err = io.open("/proc/locks", "r") | ||
| if not fd then | ||
| return nil, err | ||
| end | ||
|
|
||
| local records = {} | ||
|
|
||
| for line in fd:lines() do | ||
| local id, kind, mode, ltype, pid, maj, min, ino, first, last = line:match( | ||
| "^(%d+):%s+(%S+)%s+(%S+)%s+(%S+)%s+(%-?%d+)%s+(%x+):(%x+):(%d+)%s+(%d+)%s+(%S+)$" | ||
| ) | ||
|
|
||
| if id then | ||
| records[#records + 1] = { | ||
| id = tonumber(id), | ||
| kind = kind, | ||
| mode = mode, | ||
| type = ltype, | ||
| pid = tonumber(pid), | ||
| major = tonumber(maj, 16), | ||
| minor = tonumber(min, 16), | ||
| inode = tonumber(ino), | ||
| start = tonumber(first), | ||
| ["end"] = last, | ||
| } | ||
| end | ||
| end | ||
|
|
||
| fd:close() | ||
| return records | ||
| end | ||
|
|
||
| local function match_lock(locks, st) | ||
| local dev = st.st_dev | ||
| local inode = st.st_ino | ||
|
|
||
| local major = dev_major(dev) | ||
| local minor = dev_minor(dev) | ||
|
|
||
| for _, lock in ipairs(locks) do | ||
| if lock.major == major and lock.minor == minor and lock.inode == inode then | ||
| return lock | ||
| end | ||
| end | ||
|
|
||
| return nil | ||
| end | ||
|
|
||
| local function uptime() | ||
| local fd, err = io.open("/proc/uptime", "r") | ||
| if not fd then | ||
| return nil, err | ||
| end | ||
|
|
||
| local line = fd:read("*l") | ||
| fd:close() | ||
|
|
||
| local up = line and line:match("^(%S+)") | ||
| if not up then | ||
| return nil, "unexpected /proc/uptime format" | ||
| end | ||
|
|
||
| return tonumber(up) | ||
| end | ||
|
|
||
| local function proc_starttime(pid) | ||
| local fd, err = io.open("/proc/" .. pid .. "/stat", "r") | ||
| if not fd then | ||
| return nil, err | ||
| end | ||
|
|
||
| local line = fd:read("*l") | ||
| fd:close() | ||
| if not line then | ||
| return nil, "empty proc stat entry" | ||
| end | ||
|
|
||
| local after_comm = line:match(".*%)%s*(.*)$") | ||
| if not after_comm then | ||
| return nil, "unexpected proc stat format" | ||
| end | ||
|
|
||
| local fields = {} | ||
| for tok in after_comm:gmatch("%S+") do | ||
| fields[#fields + 1] = tok | ||
| end | ||
|
|
||
| local starttime = fields[22 - 2] | ||
| if not starttime then | ||
| return nil, "starttime missing in proc stat entry" | ||
| end | ||
|
|
||
| return tonumber(starttime) | ||
| end | ||
|
|
||
| local function sec_since_started(lock) | ||
| local ticks, err = proc_starttime(lock.pid) | ||
| if not ticks then | ||
| return nil, err | ||
| end | ||
|
|
||
| local up, err = uptime() | ||
| if not up then | ||
| return nil, err | ||
| end | ||
|
|
||
| return math.floor(up - (ticks / unistd.sysconf(unistd._SC_CLK_TCK))) | ||
| end | ||
|
|
||
| local function cdba_dev_status(dev) | ||
| local locks, err = parse_proc_locks() | ||
| if not locks then | ||
| return "ERROR: " .. err | ||
| end | ||
|
|
||
| local path = "/tmp/cdba-" .. dev.board .. ".lock" | ||
| local state = "idle" | ||
|
|
||
| if file_exists(path) then | ||
| local st, err = stat_file(path) | ||
| if not st then | ||
| return "ERROR: " .. err | ||
| end | ||
|
|
||
| local lock = match_lock(locks, st) | ||
| if lock then | ||
| local sec, err = sec_since_started(lock) | ||
| if not sec then | ||
| return "ERROR: " .. err | ||
| end | ||
|
|
||
| state = string.format("running (%ds)", sec) | ||
| end | ||
| end | ||
|
|
||
| return string.format("%-20s%s", dev.name .. ":", state) | ||
| end | ||
|
|
||
| --- Conky-facing entry point for rendering cdba device info. | ||
| -- | ||
| -- Called as ${lua cdba <index> <field>} from conky.config, once per field per | ||
| -- device, with index counting up from 1. Returns "" if index exceeds the | ||
| -- number of devices configured in ~/.cdba, which conky templates use as the | ||
| -- sentinel to stop rendering further rows. | ||
| -- | ||
| -- @param index 1-based device index, as a string or number | ||
| -- @param field one of "name", "board", or "status" | ||
| -- @return the requested field value or "" after the last device, or an | ||
| -- "ERROR: ..." string on invalid input | ||
| function conky_cdba(index, field) | ||
| local idx = tonumber(index) | ||
|
|
||
| if not cdba_cfg then | ||
| return "ERROR: failed to load the cdba config" | ||
| end | ||
|
|
||
| if not idx or idx < 1 then | ||
| return "ERROR: invalid index value: " .. tostring(index) | ||
| end | ||
|
|
||
| if idx > #cdba_cfg.devices then | ||
| return "" | ||
| end | ||
|
|
||
| local dev = cdba_cfg.devices[idx] | ||
|
|
||
| if field == "name" then | ||
| return dev.name | ||
| elseif field == "board" then | ||
| return dev.board | ||
| elseif field == "status" then | ||
| return cdba_dev_status(dev) | ||
| end | ||
|
|
||
| return "ERROR: invalid field name: '" .. field .. "'" | ||
| end | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.