/* 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, 0, 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 double_list *chips; int chip_count; ) #include 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) { int n; if (!node->parent) return DIRTREE_RECURSE; // Skip the directory itself. if (sscanf(node->name, "gpiochip%d", &n)!=1) return 0; dlist_add(&TT.chips, strdup(node->name)); TT.chip_count++; return 0; } static int comparator(const void *a, const void *b) { struct double_list *lhs = *(struct double_list **)a, *rhs = *(struct double_list **)b; return strcmp(lhs->data, rhs->data); } // call cb() in sorted order static void foreach_chip(void (*cb)(char *name)) { struct double_list **sorted; int i = 0; dirtree_flagread("/dev", DIRTREE_SHUTUP, collect_chips); if (!TT.chips) return; sorted = xmalloc(TT.chip_count*sizeof(void *)); for (i = 0; inext; qsort(sorted, TT.chip_count, sizeof(void *), comparator); for (i = 0; idata); cb(toybuf); } free(sorted); llist_traverse(&TT.chips, llist_free_arg); } 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= 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