mdcart

annotate src/main.c @ 0:e6d499a8eb1d

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 12 Mar 2017 06:20:22 +0200
parents
children c8d3d23ccd1f
rev   line source
nuclear@0 1 #include <stdio.h>
nuclear@0 2 #include <stdlib.h>
nuclear@0 3 #include <string.h>
nuclear@0 4 #include <stdint.h>
nuclear@0 5 #include <errno.h>
nuclear@0 6 #include <assert.h>
nuclear@0 7 #include <unistd.h>
nuclear@0 8 #include <fcntl.h>
nuclear@0 9 #include <termios.h>
nuclear@0 10
nuclear@0 11 enum {
nuclear@0 12 OP_NONE,
nuclear@0 13 OP_WRITE,
nuclear@0 14 OP_READ,
nuclear@0 15 OP_RESET
nuclear@0 16 };
nuclear@0 17
nuclear@0 18 int op_write(FILE *dev, FILE *fp);
nuclear@0 19 int op_read(FILE *dev, FILE *fp);
nuclear@0 20 int op_reset(FILE *dev);
nuclear@0 21 int parse_args(int argc, char **argv);
nuclear@0 22
nuclear@0 23 int op, verify = 0;
nuclear@0 24 const char *devname = "/dev/ttyUSB0";
nuclear@0 25 char *fname = 0;
nuclear@0 26 uint32_t start_addr;
nuclear@0 27 int read_size = 128 * 1024;
nuclear@0 28
nuclear@0 29 int main(int argc, char **argv)
nuclear@0 30 {
nuclear@0 31 FILE *fp, *devfp;
nuclear@0 32 int dev;
nuclear@0 33 struct termios term;
nuclear@0 34
nuclear@0 35 if(parse_args(argc, argv) == -1) {
nuclear@0 36 return 1;
nuclear@0 37 }
nuclear@0 38
nuclear@0 39 if((dev = open(devname, O_RDWR)) == -1) {
nuclear@0 40 fprintf(stderr, "failed to open device %s: %s\n", devname, strerror(errno));
nuclear@0 41 return 1;
nuclear@0 42 }
nuclear@0 43 if(tcgetattr(dev, &term) == -1) {
nuclear@0 44 fprintf(stderr, "failed to get terminal attributes for %s: %s\n", devname, strerror(errno));
nuclear@0 45 return 1;
nuclear@0 46 }
nuclear@0 47 term.c_cflag = CS8 | CLOCAL;
nuclear@0 48 term.c_iflag &= ~(IXON | IXOFF);
nuclear@0 49 term.c_lflag = 0;
nuclear@0 50
nuclear@0 51 cfsetispeed(&term, B38400);
nuclear@0 52 cfsetospeed(&term, B38400);
nuclear@0 53
nuclear@0 54 if(tcsetattr(dev, TCSANOW, &term) == -1) {
nuclear@0 55 fprintf(stderr, "failed to set terminal attributes for %s: %s\n", devname, strerror(errno));
nuclear@0 56 return 1;
nuclear@0 57 }
nuclear@0 58
nuclear@0 59 if(!(devfp = fdopen(dev, "r+"))) {
nuclear@0 60 perror("failed to attach I/O stream to the device file\n");
nuclear@0 61 return 1;
nuclear@0 62 }
nuclear@0 63 setvbuf(devfp, 0, _IONBF, 0);
nuclear@0 64
nuclear@0 65 if(fname && !(fp = fopen(fname, op == OP_READ ? "w" : "r"))) {
nuclear@0 66 fprintf(stderr, "failed to open %s: %s\n", fname, strerror(errno));
nuclear@0 67 return 1;
nuclear@0 68 }
nuclear@0 69
nuclear@0 70 switch(op) {
nuclear@0 71 case OP_WRITE:
nuclear@0 72 if(op_write(devfp, fp) == -1) {
nuclear@0 73 fprintf(stderr, "write failed\n");
nuclear@0 74 return 1;
nuclear@0 75 }
nuclear@0 76 break;
nuclear@0 77
nuclear@0 78 case OP_READ:
nuclear@0 79 if(op_read(devfp, fp) == -1) {
nuclear@0 80 fprintf(stderr, "read failed\n");
nuclear@0 81 return 1;
nuclear@0 82 }
nuclear@0 83 break;
nuclear@0 84
nuclear@0 85 case OP_RESET:
nuclear@0 86 if(op_reset(devfp) == -1) {
nuclear@0 87 fprintf(stderr, "reset failed\n");
nuclear@0 88 return 1;
nuclear@0 89 }
nuclear@0 90 break;
nuclear@0 91
nuclear@0 92 default:
nuclear@0 93 break;
nuclear@0 94 }
nuclear@0 95
nuclear@0 96 fclose(devfp);
nuclear@0 97 close(dev);
nuclear@0 98 if(fp) {
nuclear@0 99 fclose(fp);
nuclear@0 100 }
nuclear@0 101 return 0;
nuclear@0 102 }
nuclear@0 103
nuclear@0 104 #define RET_IF_FAIL(x) \
nuclear@0 105 if(!fgets(buf, sizeof buf, dev) || buf[0] != 'O') return x
nuclear@0 106
nuclear@0 107 int op_write(FILE *dev, FILE *fp)
nuclear@0 108 {
nuclear@0 109 char buf[128];
nuclear@0 110 int c;
nuclear@0 111
nuclear@0 112 fprintf(dev, "p\n");
nuclear@0 113 RET_IF_FAIL(-1);
nuclear@0 114 fprintf(dev, "a%d\n", start_addr);
nuclear@0 115 RET_IF_FAIL(-1);
nuclear@0 116
nuclear@0 117 while((c = fgetc(fp)) != -1) {
nuclear@0 118 fprintf(dev, "w%d\n", c);
nuclear@0 119 RET_IF_FAIL(-1);
nuclear@0 120 }
nuclear@0 121
nuclear@0 122 fprintf(dev, "b\n");
nuclear@0 123 RET_IF_FAIL(-1);
nuclear@0 124 return 0;
nuclear@0 125 }
nuclear@0 126
nuclear@0 127 int op_read(FILE *dev, FILE *fp)
nuclear@0 128 {
nuclear@0 129 char buf[128];
nuclear@0 130 int i, val;
nuclear@0 131
nuclear@0 132 fprintf(dev, "p\n");
nuclear@0 133 RET_IF_FAIL(-1);
nuclear@0 134 fprintf(dev, "a%d\n", start_addr);
nuclear@0 135 RET_IF_FAIL(-1);
nuclear@0 136
nuclear@0 137 for(i=0; i<read_size; i++) {
nuclear@0 138 fprintf(dev, "r\n");
nuclear@0 139 if(!fgets(buf, sizeof buf, dev) || buf[0] != 'O') {
nuclear@0 140 fprintf(stderr, "read error after %d bytes\n", i);
nuclear@0 141 break;
nuclear@0 142 }
nuclear@0 143 val = atoi(buf + 3); /* skip 'O', 'K', ' ' */
nuclear@0 144 fputc(val, fp);
nuclear@0 145 }
nuclear@0 146
nuclear@0 147 fprintf(dev, "b\n");
nuclear@0 148 RET_IF_FAIL(-1);
nuclear@0 149 return 0;
nuclear@0 150 }
nuclear@0 151
nuclear@0 152 int op_reset(FILE *dev)
nuclear@0 153 {
nuclear@0 154 char buf[128];
nuclear@0 155 fprintf(dev, "p\n");
nuclear@0 156 RET_IF_FAIL(-1);
nuclear@0 157 fprintf(dev, "b\n");
nuclear@0 158 RET_IF_FAIL(-1);
nuclear@0 159 return 0;
nuclear@0 160 }
nuclear@0 161
nuclear@0 162 int parse_args(int argc, char **argv)
nuclear@0 163 {
nuclear@0 164 int i;
nuclear@0 165
nuclear@0 166 for(i=1; i<argc; i++) {
nuclear@0 167 if(strcmp(argv[i], "-w") == 0 || strcmp(argv[i], "-write") == 0) {
nuclear@0 168 op = OP_WRITE;
nuclear@0 169 if(!(fname = argv[++i])) {
nuclear@0 170 fprintf(stderr, "%s must be followed by a filename\n", argv[i - 1]);
nuclear@0 171 return -1;
nuclear@0 172 }
nuclear@0 173
nuclear@0 174 } else if(strcmp(argv[i], "-r") == 0 || strcmp(argv[i], "-read") == 0) {
nuclear@0 175 op = OP_READ;
nuclear@0 176 if(!(fname = argv[++i])) {
nuclear@0 177 fprintf(stderr, "%s must be followed by a filename\n", argv[i - 1]);
nuclear@0 178 return -1;
nuclear@0 179 }
nuclear@0 180
nuclear@0 181 } else if(strcmp(argv[i], "-a") == 0 || strcmp(argv[i], "-addr") == 0) {
nuclear@0 182 char *endp;
nuclear@0 183 if(!argv[++i] || ((start_addr = strtol(argv[i], &endp, 0)), endp == argv[i])) {
nuclear@0 184 fprintf(stderr, "%s must be followed by an address\n", argv[i - 1]);
nuclear@0 185 return -1;
nuclear@0 186 }
nuclear@0 187
nuclear@0 188 } else if(strcmp(argv[i], "-R") == 0 || strcmp(argv[i], "-reset") == 0) {
nuclear@0 189 op = OP_RESET;
nuclear@0 190
nuclear@0 191 } else if(strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "-size") == 0) {
nuclear@0 192 char *endp;
nuclear@0 193 if(!argv[++i] || ((read_size = strtol(argv[i], &endp, 0)), endp == argv[i])) {
nuclear@0 194 fprintf(stderr, "%s must be followed by a size in bytes\n", argv[i - 1]);
nuclear@0 195 return -1;
nuclear@0 196 }
nuclear@0 197
nuclear@0 198 } else if(strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "-verify") == 0) {
nuclear@0 199 verify = 1;
nuclear@0 200
nuclear@0 201 } else if(strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "-device") == 0) {
nuclear@0 202 devname = argv[++i];
nuclear@0 203
nuclear@0 204 } else if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-help") == 0) {
nuclear@0 205 printf("Usage: %s [options]\n", argv[0]);
nuclear@0 206 printf("Options:\n");
nuclear@0 207 printf(" -w|-write <filename>\n");
nuclear@0 208 printf(" -r|-read <filename>\n");
nuclear@0 209 printf(" -a|-addr <address>: start address for read/write operations\n");
nuclear@0 210 printf(" -R|-reset: reboot machine\n");
nuclear@0 211 printf(" -v|-verify: do verification after writing\n");
nuclear@0 212 printf(" -s|-size: read size in bytes\n");
nuclear@0 213 printf(" -d|-device <device file>: serial device (eg /dev/ttyUSB0)\n");
nuclear@0 214 printf(" -h|-help: print usage and exit\n");
nuclear@0 215 return 0;
nuclear@0 216
nuclear@0 217 } else {
nuclear@0 218 fprintf(stderr, "invalid argument: %s\n", argv[i]);
nuclear@0 219 return -1;
nuclear@0 220 }
nuclear@0 221 }
nuclear@0 222
nuclear@0 223 if(!op) {
nuclear@0 224 fprintf(stderr, "you must specify an operation\n");
nuclear@0 225 return -1;
nuclear@0 226 }
nuclear@0 227 return 0;
nuclear@0 228 }