mdcart

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