/* * Copyright (C) 2021 Denis 'GNUtoo' Carikli * * 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 3 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, see . */ #include #include #include #include #include #include #include #include #include #include "compatible_devices.h" #include "exynos4412_gpios.h" #include "exynos4412_gpios_data.h" #include "modem_gpios_data.h" #include "tests.h" int usage(char* progname) { printf("Usage: %s \n", progname); printf("\n"); printf("Available commands:\n"); printf("\tflash: dump flash GPIO (gpj1 1) status\n"); printf("\tgpl1: dump GPL1 GPIOs status" " (for tests on gpio127 and gpio128)\n"); printf("\tgpl2: dump GPL2 GPIOs status" " (for tests on gpio127 and gpio128)\n"); printf("\tgps: dump GPS GPIOs status\n"); printf("\tgpy0: dump GPY0 GPIOs status" " (for tests on gpio127 and gpio128)\n"); printf("\tmodem: dump the modem GPIOs status\n"); printf("\ttest: run self tests\n"); return 0; } int dump_flash_gpio_status(int debug, char* devmem, int fd, size_t page_size, void *gpio_hardware_blocks_addr) { int rc; rc = dump_gpio_infos(debug, devmem, fd, page_size, gpio_hardware_blocks_addr, "gpj1", 1); if (rc == -1) { printf("dump_gpio_infos failed with error %d\n", rc); /* TODO: return more precise error */ return EX_UNAVAILABLE; } return 0; } int dump_flash_gps_status(int debug, char* devmem, int fd, size_t page_size, void *gpio_hardware_blocks_addr) { int rc; rc = dump_gpio_infos(debug, devmem, fd, page_size, gpio_hardware_blocks_addr, "gpl2", 1); if (rc == -1) { printf("dump_gpio_infos failed with error %d\n", rc); /* TODO: return more precise error */ return EX_UNAVAILABLE; } rc = dump_gpio_infos(debug, devmem, fd, page_size, gpio_hardware_blocks_addr, "gpl2", 2); if (rc == -1) { printf("dump_gpio_infos failed with error %d\n", rc); /* TODO: return more precise error */ return EX_UNAVAILABLE; } return 0; } int dump_gpio_bank_status(int debug, char* devmem, int fd, size_t page_size, void *gpio_hardware_blocks_addr, char* bank) { int i; int nr_gpios; int rc; nr_gpios = get_bank_gpio_numbers(debug, bank); if (nr_gpios == -1) { /* The get_bank_gpio_numbers function * already prints some error */ /* TODO: return more precise error */ return EX_UNAVAILABLE; } for (i=0; i < nr_gpios; i++) { rc = dump_gpio_infos(debug, devmem, fd, page_size, gpio_hardware_blocks_addr, bank, i); if (rc == -1) { printf("dump_gpio_infos failed with error %d\n", rc); /* TODO: return more precise error */ return EX_UNAVAILABLE; } } return 0; } int main(int argc, char *argv[]) { int fd = 0; int rc = 0; int debug = 0; char *devmem = "/dev/mem"; size_t page_size = 4096; void *gpio_hardware_blocks_addr; assert(argc >= 1); if (argc != 2) { usage(argv[0]); return EX_USAGE; } if (!device_is_compatible(debug)) { printf("Exiting due to incompatible device\n"); return 0; } /* * TODO: check if root or tell the user to become root in case or * access error */ fd = open(devmem, O_RDWR | O_SYNC); if (fd == -1) { rc = errno; printf("Opening %s failed with error %d: %s\n", devmem, rc, strerror(rc)); /* TODO: return more precise error */ return EX_UNAVAILABLE; } if (strcmp("flash", argv[1]) && strcmp("gpl1", argv[1]) && strcmp("gpl2", argv[1]) && strcmp("gps", argv[1]) && strcmp("gpy0", argv[1]) && strcmp("modem", argv[1]) && strcmp("test", argv[1])) { usage(argv[0]); return EX_USAGE; } gpio_hardware_blocks_addr = mmap_gpio_hardware_blocks(debug, devmem, fd, page_size); if (gpio_hardware_blocks_addr == NULL) { /* mmap_gpio_bank already prints an error */ goto end; } if (argc == 2 && !strcmp("flash", argv[1])) { return dump_flash_gpio_status(debug, devmem, fd, page_size, gpio_hardware_blocks_addr); } else if (argc == 2 && !strcmp("gpl1", argv[1])) { return dump_gpio_bank_status(debug, devmem, fd, page_size, gpio_hardware_blocks_addr, "gpl1"); } else if (argc == 2 && !strcmp("gpl2", argv[1])) { return dump_gpio_bank_status(debug, devmem, fd, page_size, gpio_hardware_blocks_addr, "gpl2"); } else if (argc == 2 && !strcmp("gps", argv[1])) { return dump_flash_gps_status(debug, devmem, fd, page_size, gpio_hardware_blocks_addr); } else if (argc == 2 && !strcmp("gpy0", argv[1])) { return dump_gpio_bank_status(debug, devmem, fd, page_size, gpio_hardware_blocks_addr, "gpy0"); } else if (argc == 2 && !strcmp("modem", argv[1])) { return dump_modem_gpio_infos(debug, devmem, fd, page_size, gpio_hardware_blocks_addr); } else if (argc == 2 && !strcmp("test", argv[1])) { return run_tests(debug, devmem, fd, page_size); } else { usage(argv[0]); return EX_USAGE; } end: rc = close(fd); if (rc == -1) { rc = errno; printf("Closing %s failed with error %d: %s\n", devmem, rc, strerror(rc)); /* TODO: return more precise error */ return EX_UNAVAILABLE; } return 0; }