From 5b2a7bacaa5b5c52fefc9828cc082356a3bfb2cb Mon Sep 17 00:00:00 2001 From: Elara6331 Date: Mon, 25 Dec 2023 12:04:03 -0800 Subject: [PATCH] Add gpioget command --- build.zig | 1 + src/cmd/get.zig | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ src/gpio.zig | 9 +++++--- src/uapi.zig | 12 +++++------ 4 files changed, 68 insertions(+), 9 deletions(-) create mode 100644 src/cmd/get.zig diff --git a/build.zig b/build.zig index 93ba403..0f66566 100644 --- a/build.zig +++ b/build.zig @@ -15,6 +15,7 @@ const examples = [_]Item{ const commands = [_]Item{ .{ .name = "gpiodetect", .src = "src/cmd/detect.zig" }, .{ .name = "gpioinfo", .src = "src/cmd/info.zig" }, + .{ .name = "gpioget", .src = "src/cmd/get.zig" }, }; pub fn build(b: *std.Build) !void { diff --git a/src/cmd/get.zig b/src/cmd/get.zig new file mode 100644 index 0000000..c74e01f --- /dev/null +++ b/src/cmd/get.zig @@ -0,0 +1,55 @@ +const std = @import("std"); +const gpio = @import("gpio"); + +pub fn main() !void { + var gpa = std.heap.GeneralPurposeAllocator(.{}){}; + defer std.debug.assert(gpa.deinit() == .ok); + const alloc = gpa.allocator(); + + var args = try std.process.argsAlloc(alloc); + defer std.process.argsFree(alloc, args); + + const stdout = std.io.getStdOut().writer(); + + if (args.len < 3) { + try stdout.print("Usage: {s} \n\n", .{args[0]}); + return error.InsufficientArguments; + } + + var path: []const u8 = if (hasPrefix(args[1], "gpiochip")) + try std.mem.concat(alloc, u8, &.{ "/dev/", args[1] }) + else + try std.mem.concat(alloc, u8, &.{ "/dev/gpiochip", args[1] }); + defer alloc.free(path); + + var chip = try gpio.getChip(path); + defer chip.close(); + try chip.setConsumer("gpioget"); + + var offsets = std.ArrayList(u32).init(alloc); + defer offsets.deinit(); + + // Iterate over each argument starting from the second one + for (args[2..args.len]) |argument| { + // Parse each argument as an integer and add it to offsets + var offset = try std.fmt.parseInt(u32, argument, 10); + try offsets.append(offset); + } + + var lines = try chip.requestLines(offsets.items, .{ .input = true }); + defer lines.close(); + const vals = try lines.getValues(); + + var i: u32 = 0; + while (i < args.len - 2) : (i += 1) { + const value: u1 = if (vals.isSet(i)) 1 else 0; + try stdout.print("{d} ", .{value}); + } + + try stdout.writeByte('\n'); +} + +fn hasPrefix(s: []const u8, prefix: []const u8) bool { + if (s.len < prefix.len) return false; + return (std.mem.eql(u8, s[0..prefix.len], prefix)); +} diff --git a/src/gpio.zig b/src/gpio.zig index 189d6a4..e22c229 100644 --- a/src/gpio.zig +++ b/src/gpio.zig @@ -209,11 +209,14 @@ pub const Lines = struct { try gpio.uapi.setLineConfig(self.handle, lc); } - /// Returns the values of all the controlled lines as a bitset. + /// Gets the values of all the controlled lines as a bitset pub fn getValues(self: Lines) !gpio.uapi.LineValueBitset { if (self.closed) return error.LineClosed; - const vals = try gpio.uapi.getLineValues(self.handle); - return vals.bits; + var vals = gpio.uapi.LineValueBitset{ .mask = 0 }; + var i: u32 = 0; + // Add all the indices to the list of values to get + while (i < self.num_lines) : (i += 1) vals.set(i); + return try gpio.uapi.getLineValues(self.handle, vals); } /// Releases all the resources held by the requested `lines`. diff --git a/src/uapi.zig b/src/uapi.zig index bd1d80e..3a74dc4 100644 --- a/src/uapi.zig +++ b/src/uapi.zig @@ -231,13 +231,13 @@ pub fn getLine(fd: std.os.fd_t, lr: LineRequest) !std.os.fd_t { return lrp.fd; } -/// Executes `GPIO_V2_LINE_GET_VALUES_IOCTL` on the given fd and returns the resulting -/// `LineValues` value -pub fn getLineValues(fd: std.os.fd_t) !LineValues { +/// Executes `GPIO_V2_LINE_GET_VALUES_IOCTL` on the given fd with the given mask, +/// and returns a bitset representing all the line values. +pub fn getLineValues(fd: std.os.fd_t, mask: LineValueBitset) !LineValueBitset { + var vals = LineValues{ .mask = mask }; const req = std.os.linux.IOCTL.IOWR(0xB4, 0x0E, LineValues); - var values = std.mem.zeroes(LineValues); - try handleErrno(std.os.linux.ioctl(fd, req, @intFromPtr(&values))); - return values; + try handleErrno(std.os.linux.ioctl(fd, req, @intFromPtr(&vals))); + return vals.bits; } /// Executes `GPIO_V2_LINE_SET_VALUES_IOCTL` on the given fd