/*** * * tools/tdmacfg.c * Configuration tool for the RTmac/TDMA discipline * * RTmac - real-time networking media access control subsystem * Copyright (C) 2002 Marc Kleine-Budde , * 2003-2005 Jan Kiszka * * 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 2 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, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include #include #include #include #include #include #include #include #include #include static int f; static struct tdma_config tdma_cfg; static void help(void) { fprintf(stderr, "Usage:\n" "\ttdmacfg master [-b ]\n" "\t [-c calibration_rounds] [-i max_slot_id]\n" "\t [-m max_calibration_requests]\n" "\ttdmacfg slave [-c calibration_rounds] [-i max_slot_id]\n" "\ttdmacfg slot [ [-p /] " "[-s ]\n" "\t [-j ] [-l calibration_log_file]\n" "\t [-t calibration_timeout]]\n" "\ttdmacfg detach\n"); exit(1); } int getintopt(int argc, int pos, char *argv[], int min) { int result; if (pos >= argc) help(); if ((sscanf(argv[pos], "%i", &result) != 1) || (result < min)) { fprintf(stderr, "invalid parameter: %s %s\n", argv[pos-1], argv[pos]); exit(1); } return result; } void write_calibration_log(char *log_filename, unsigned int rounds, __u64 *cal_results) { char str_buf[32]; int log_file; int i; int r; log_file = open(log_filename, O_CREAT | O_WRONLY | O_TRUNC, S_IREAD | S_IWRITE); if (log_file < 0) { perror("create output file"); free(cal_results); exit(1); } for (i = rounds-1; i >= 0; i--) { r = sprintf(str_buf, "%llu\n", (unsigned long long)cal_results[i]); if (write(log_file, str_buf, r) < 0) { perror("write output file"); free(cal_results); exit(1); } } close(log_file); free(cal_results); } void do_master(int argc, char *argv[]) { int r; int i; if (argc < 4) help(); if ((sscanf(argv[3], "%u", &r) != 1) || (r <= 0)) { fprintf(stderr, "invalid cycle period: %s\n", argv[3]); exit(1); } tdma_cfg.args.master.cycle_period = ((uint64_t)r) * 1000; tdma_cfg.args.master.backup_sync_offset = 0; tdma_cfg.args.master.cal_rounds = 100; tdma_cfg.args.master.max_cal_requests = 64; tdma_cfg.args.master.max_slot_id = 7; for (i = 4; i < argc; i++) { if (strcmp(argv[i], "-b") == 0) tdma_cfg.args.master.backup_sync_offset = getintopt(argc, ++i, argv, 0) * 1000; else if (strcmp(argv[i], "-c") == 0) tdma_cfg.args.master.cal_rounds = getintopt(argc, ++i, argv, 0); else if (strcmp(argv[i], "-i") == 0) tdma_cfg.args.master.max_slot_id = getintopt(argc, ++i, argv, 0); else if (strcmp(argv[i], "-m") == 0) tdma_cfg.args.master.max_cal_requests = getintopt(argc, ++i, argv, 1); else help(); } r = ioctl(f, TDMA_IOC_MASTER, &tdma_cfg); if (r < 0) { perror("ioctl"); exit(1); } exit(0); } void do_slave(int argc, char *argv[]) { int i; int r; if (argc < 3) help(); tdma_cfg.args.slave.cal_rounds = 100; tdma_cfg.args.slave.max_slot_id = 7; for (i = 3; i < argc; i++) { if (strcmp(argv[i], "-c") == 0) tdma_cfg.args.slave.cal_rounds = getintopt(argc, ++i, argv, 0); else if (strcmp(argv[i], "-i") == 0) tdma_cfg.args.slave.max_slot_id = getintopt(argc, ++i, argv, 0); else help(); } r = ioctl(f, TDMA_IOC_SLAVE, &tdma_cfg); if (r < 0) { perror("ioctl"); exit(1); } exit(0); } void do_slot(int argc, char *argv[]) { char *log_filename = NULL; int result_size = 0; unsigned int ioc; int r; int i; if (argc < 4) help(); if ((sscanf(argv[3], "%u", &r) != 1) || (r < 0)) { fprintf(stderr, "invalid slot id: %s\n", argv[3]); exit(1); } if (argc > 4) { tdma_cfg.args.set_slot.id = r; if ((sscanf(argv[4], "%u", &r) != 1) || (r < 0)) { fprintf(stderr, "invalid slot offset: %s\n", argv[4]); exit(1); } tdma_cfg.args.set_slot.offset = ((uint64_t)r) * 1000; tdma_cfg.args.set_slot.period = 1; tdma_cfg.args.set_slot.phasing = 0; tdma_cfg.args.set_slot.size = 0; tdma_cfg.args.set_slot.cal_timeout = 0; tdma_cfg.args.set_slot.joint_slot = -1; tdma_cfg.args.set_slot.cal_results = NULL; for (i = 5; i < argc; i++) { if (strcmp(argv[i], "-l") == 0) { if (++i >= argc) help(); log_filename = argv[i]; } else if (strcmp(argv[i], "-p") == 0) { if (++i >= argc) help(); if ((sscanf(argv[i], "%u/%u", &tdma_cfg.args.set_slot.phasing, &tdma_cfg.args.set_slot.period) != 2) || (tdma_cfg.args.set_slot.phasing < 1) || (tdma_cfg.args.set_slot.period < 1) || (tdma_cfg.args.set_slot.phasing > tdma_cfg.args.set_slot.period)) { fprintf(stderr, "invalid parameter: %s %s\n", argv[i-1], argv[i]); exit(1); } tdma_cfg.args.set_slot.phasing--; } else if (strcmp(argv[i], "-s") == 0) tdma_cfg.args.set_slot.size = getintopt(argc, ++i, argv, MIN_SLOT_SIZE); else if (strcmp(argv[i], "-t") == 0) tdma_cfg.args.set_slot.cal_timeout = getintopt(argc, ++i, argv, 0); else if (strcmp(argv[i], "-j") == 0) tdma_cfg.args.set_slot.joint_slot = getintopt(argc, ++i, argv, 0); else help(); } if (log_filename) { /* note: we can reuse tdma_cfg here as the head is the same and * will remain unmodified */ result_size = ioctl(f, TDMA_IOC_CAL_RESULT_SIZE, &tdma_cfg); if (result_size > 0) { tdma_cfg.args.set_slot.cal_results = (__u64 *)malloc(result_size * sizeof(__u64)); if (!tdma_cfg.args.set_slot.cal_results) { fprintf(stderr, "insufficient memory\n"); exit(1); } } else log_filename = NULL; } ioc = TDMA_IOC_SET_SLOT; } else { tdma_cfg.args.remove_slot.id = r; ioc = TDMA_IOC_REMOVE_SLOT; } r = ioctl(f, ioc, &tdma_cfg); if (r < 0) { perror("ioctl"); exit(1); } if (log_filename) write_calibration_log(log_filename, result_size, tdma_cfg.args.set_slot.cal_results); exit(0); } void do_detach(int argc, char *argv[]) { int r; if (argc != 3) help(); r = ioctl(f, TDMA_IOC_DETACH, &tdma_cfg); if (r < 0) { perror("ioctl"); exit(1); } exit(0); } int main(int argc, char *argv[]) { if ((argc < 3) || (strcmp(argv[1], "--help") == 0)) help(); f = open("/dev/rtnet", O_RDWR); if (f < 0) { perror("/dev/rtnet"); exit(1); } strncpy(tdma_cfg.head.if_name, argv[1], IFNAMSIZ); if (strcmp(argv[2], "master") == 0) do_master(argc, argv); if (strcmp(argv[2], "slave") == 0) do_slave(argc, argv); if (strcmp(argv[2], "slot") == 0) do_slot(argc, argv); if (strcmp(argv[2], "detach") == 0) do_detach(argc, argv); help(); return 0; }