Equivalent to the content of the gpiod debian package. Very different
interface to the traditional Raspberry Pi command, but that command
explicitly calls itself deprecated and tells you to use the gpiod
package's commands instead.

"Works for me" on a Raspberry Pi 400, with a (small) variety of things
connected to GPIOs as inputs and outputs.

Missing gpiomon, which -- since the rest of these are about a year old
at this point -- it doesn't look like I'm going to get around to writing
any time soon unless someone asks for it...
---
 toys/pending/gpiod.c | 259 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 259 insertions(+)
 create mode 100644 toys/pending/gpiod.c
From 667df2ffa9b050383c77785367f414dba9954297 Mon Sep 17 00:00:00 2001
From: Elliott Hughes <[email protected]>
Date: Mon, 21 Feb 2022 17:11:41 -0800
Subject: [PATCH] gpiod: new commands.

Equivalent to the content of the gpiod debian package. Very different
interface to the traditional Raspberry Pi command, but that command
explicitly calls itself deprecated and tells you to use the gpiod
package's commands instead.

"Works for me" on a Raspberry Pi 400, with a (small) variety of things
connected to GPIOs as inputs and outputs.

Missing gpiomon, which -- since the rest of these are about a year old
at this point -- it doesn't look like I'm going to get around to writing
any time soon unless someone asks for it...
---
 toys/pending/gpiod.c | 259 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 259 insertions(+)
 create mode 100644 toys/pending/gpiod.c

diff --git a/toys/pending/gpiod.c b/toys/pending/gpiod.c
new file mode 100644
index 00000000..60297b0f
--- /dev/null
+++ b/toys/pending/gpiod.c
@@ -0,0 +1,259 @@
+/* gpiod.c - gpio tools
+ *
+ * Copyright 2021 The Android Open Source Project
+ *
+ * TODO: gpiomon
+
+USE_GPIODETECT(NEWTOY(gpiodetect, ">0", TOYFLAG_USR|TOYFLAG_BIN))
+USE_GPIOFIND(NEWTOY(gpioinfo, "", TOYFLAG_USR|TOYFLAG_BIN))
+USE_GPIOGET(NEWTOY(gpioget, "<2l", TOYFLAG_USR|TOYFLAG_BIN))
+USE_GPIOINFO(NEWTOY(gpiofind, "<1>1", TOYFLAG_USR|TOYFLAG_BIN))
+USE_GPIOSET(NEWTOY(gpioset, "<2l", TOYFLAG_USR|TOYFLAG_BIN))
+
+config GPIODETECT
+  bool "gpiodetect"
+  default y
+  help
+    usage: gpiodetect
+
+    Show all gpio chips' names, labels, and number of lines.
+
+config GPIOFIND
+  bool "gpiofind"
+  default y
+  help
+    usage: gpiofind NAME
+
+    Show the chip and line number for the given line name.
+
+config GPIOINFO
+  bool "gpioinfo"
+  default y
+  help
+    usage: gpioinfo [CHIP...]
+
+    Show gpio chips' lines.
+
+config GPIOGET
+  bool "gpioget"
+  default y
+  help
+    usage: gpioget [-l] CHIP LINE...
+
+    Gets the values of the given lines on CHIP. Use gpiofind to convert line
+    names to numbers.
+
+    -l	Active low
+
+config GPIOSET
+  bool "gpioset"
+  default y
+  help
+    usage: gpioset [-l] CHIP LINE=VALUE...
+
+    Set the lines on CHIP to the given values. Use gpiofind to convert line
+    names to numbers.
+
+    -l	Active low
+*/
+
+#define FOR_gpiodetect
+#define TT this.gpiod
+#include "toys.h"
+
+GLOBALS(
+  struct arg_list *chips;
+  int chip_count;
+)
+
+#include <linux/gpio.h>
+
+static int open_chip(char *chip)
+{
+  sprintf(toybuf, isdigit(*chip) ? "/dev/gpiochip%s" : "/dev/%s", chip);
+  return xopen(toybuf, O_RDWR);
+}
+
+static int collect_chips(struct dirtree *node)
+{
+  struct arg_list *new;
+  int n;
+
+  if (!node->parent) return DIRTREE_RECURSE; // Skip the directory itself.
+
+  if (sscanf(node->name, "gpiochip%d", &n)!=1) return 0;
+
+  new = xmalloc(sizeof(struct arg_list));
+  new->arg = strdup(node->name);
+  new->next = TT.chips;
+  TT.chips = new;
+  TT.chip_count++;
+  return 0;
+}
+
+static int comparator(const void *a, const void *b)
+{
+  struct arg_list *lhs = *(struct arg_list **)a;
+  struct arg_list *rhs = *(struct arg_list **)b;
+
+  return strcmp(lhs->arg, rhs->arg);
+}
+
+static void foreach_chip(void (*cb)(char *name))
+{
+  struct arg_list **sorted, *chip;
+  int i = 0;
+
+  dirtree_flagread("/dev", DIRTREE_SHUTUP, collect_chips);
+
+  sorted = xmalloc(TT.chip_count*sizeof(void *));
+  for (chip = TT.chips; chip; chip=chip->next, i++) sorted[i] = chip;
+  qsort(sorted, TT.chip_count, sizeof(void *), comparator);
+
+  for (i=0; i<TT.chip_count; i++) {
+    sprintf(toybuf, "/dev/%s", sorted[i]->arg);
+    cb(toybuf);
+  }
+
+  free(sorted);
+  llist_free_arg(TT.chips);
+}
+
+static void gpiodetect(char *path)
+{
+  struct gpiochip_info chip;
+  int fd = xopen(path, O_RDWR);
+
+  xioctl(fd, GPIO_GET_CHIPINFO_IOCTL, &chip);
+  close(fd);
+
+  // gpiochip0 [pinctrl-bcm2711] (58 line)
+  printf("%s [%s] (%u line%s)\n", chip.name, chip.label, chip.lines,
+         chip.lines==1?"":"s");
+}
+
+void gpiodetect_main(void)
+{
+  foreach_chip(gpiodetect);
+}
+
+#define FOR_gpiofind
+#include "generated/flags.h"
+
+static void gpiofind(char *path)
+{
+  struct gpiochip_info chip;
+  struct gpioline_info line;
+  int fd = xopen(path, O_RDWR);
+
+  xioctl(fd, GPIO_GET_CHIPINFO_IOCTL, &chip);
+
+  for (line.line_offset=0; line.line_offset<chip.lines; line.line_offset++) {
+    xioctl(fd, GPIO_GET_LINEINFO_IOCTL, &line);
+    if (!strcmp(line.name, *toys.optargs)) {
+      printf("%s %d\n", chip.name, line.line_offset);
+      break;
+    }
+  }
+  close(fd);
+}
+
+void gpiofind_main(void)
+{
+  foreach_chip(gpiofind);
+}
+
+#define FOR_gpioinfo
+#include "generated/flags.h"
+
+static void gpioinfo_fd(int fd)
+{
+  struct gpiochip_info chip;
+  struct gpioline_info line;
+
+  xioctl(fd, GPIO_GET_CHIPINFO_IOCTL, &chip);
+
+  // gpiochip1 - 8 lines:
+  printf("%s - %d line%s:\n", chip.name, chip.lines, chip.lines==1?"":"s");
+
+  //     line   4: "VDD_SD_IO_SEL" "vdd-sd-io" output active-high [used]
+  // We use slightly wider columns for the name and consumer; just wide enough
+  // to show all Raspberry Pi 400 pins without wrapping an 80-column terminal.
+  for (line.line_offset=0; line.line_offset<chip.lines; line.line_offset++) {
+    xioctl(fd, GPIO_GET_LINEINFO_IOCTL, &line);
+    if (*line.name) sprintf(toybuf, "\"%s\"", line.name);
+    else strcpy(toybuf, "unnamed");
+    if (*line.consumer) sprintf(toybuf+64, "\"%s\"", line.consumer);
+    else strcpy(toybuf+64, "unused");
+    printf("\tline %3d:%18s %18s", line.line_offset, toybuf, toybuf+64);
+    printf(" %sput", line.flags&GPIOLINE_FLAG_IS_OUT?"out":" in");
+    printf(" active-%s", line.flags&GPIOLINE_FLAG_ACTIVE_LOW?"low ":"high");
+    if (line.flags&GPIOLINE_FLAG_KERNEL) printf(" [used]");
+    printf("\n");
+  }
+
+  close(fd);
+}
+
+static void gpioinfo(char *path)
+{
+  gpioinfo_fd(xopen(path, O_RDWR));
+}
+
+void gpioinfo_main(void)
+{
+  int i;
+
+  if (!toys.optc) foreach_chip(gpioinfo);
+  else for (i = 0; toys.optargs[i]; i++) {
+    gpioinfo_fd(open_chip(toys.optargs[i]));
+  }
+}
+
+#define FOR_gpioget
+#include "generated/flags.h"
+
+void gpioget_main(void)
+{
+  struct gpiohandle_request req = { .flags = GPIOHANDLE_REQUEST_INPUT };
+  struct gpiohandle_data data;
+  struct gpiochip_info chip;
+  char **args = toys.optargs;
+  int fd, line;
+
+  fd = open_chip(*args);
+  xioctl(fd, GPIO_GET_CHIPINFO_IOCTL, &chip);
+  if (FLAG(l)) req.flags |= GPIOHANDLE_REQUEST_ACTIVE_LOW;
+  for (args++; *args; args++, req.lines++) {
+    if (req.lines >= GPIOHANDLES_MAX) error_exit("too many requests!");
+    line = atolx_range(*args, 0, chip.lines);
+    req.lineoffsets[req.lines] = line;
+  }
+  xioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
+  xioctl(req.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data);
+  for (line=0; line<req.lines; line++) {
+    printf("%s%d", line>0 ? " " : "", data.values[line]);
+  }
+  xputc('\n');
+}
+
+#define FOR_gpioset
+#include "generated/flags.h"
+
+void gpioset_main(void)
+{
+  struct gpiohandle_request req = { .flags = GPIOHANDLE_REQUEST_OUTPUT };
+  char **args = toys.optargs;
+  int fd, line, value;
+
+  fd = open_chip(*args);
+  if (FLAG(l)) req.flags |= GPIOHANDLE_REQUEST_ACTIVE_LOW;
+  for (args++; *args; args++, req.lines++) {
+    if (req.lines >= GPIOHANDLES_MAX) error_exit("too many requests!");
+    if (sscanf(*args, "%d=%d", &line, &value) != 2)
+      perror_exit("not LINE=VALUE: %s", *args);
+    req.lineoffsets[req.lines] = line;
+    req.default_values[req.lines] = value;
+  }
+  xioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
+}
-- 
2.35.1.473.g83b2b277ed-goog

_______________________________________________
Toybox mailing list
[email protected]
http://lists.landley.net/listinfo.cgi/toybox-landley.net

Reply via email to