mdcart
changeset 0:e6d499a8eb1d
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 12 Mar 2017 06:20:22 +0200 |
parents | |
children | c8d3d23ccd1f |
files | Makefile src/main.c |
diffstat | 2 files changed, 240 insertions(+), 0 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/Makefile Sun Mar 12 06:20:22 2017 +0200 1.3 @@ -0,0 +1,12 @@ 1.4 +src = $(wildcard src/*.c) 1.5 +obj = $(src:.c=.o) 1.6 +bin = mdcart 1.7 + 1.8 +CFLAGS = -pedantic -Wall -g -O0 1.9 + 1.10 +$(bin): $(obj) 1.11 + $(CC) -o $@ $(obj) $(LDFLAGS) 1.12 + 1.13 +.PHONY: clean 1.14 +clean: 1.15 + rm -f $(obj) $(bin)
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/src/main.c Sun Mar 12 06:20:22 2017 +0200 2.3 @@ -0,0 +1,228 @@ 2.4 +#include <stdio.h> 2.5 +#include <stdlib.h> 2.6 +#include <string.h> 2.7 +#include <stdint.h> 2.8 +#include <errno.h> 2.9 +#include <assert.h> 2.10 +#include <unistd.h> 2.11 +#include <fcntl.h> 2.12 +#include <termios.h> 2.13 + 2.14 +enum { 2.15 + OP_NONE, 2.16 + OP_WRITE, 2.17 + OP_READ, 2.18 + OP_RESET 2.19 +}; 2.20 + 2.21 +int op_write(FILE *dev, FILE *fp); 2.22 +int op_read(FILE *dev, FILE *fp); 2.23 +int op_reset(FILE *dev); 2.24 +int parse_args(int argc, char **argv); 2.25 + 2.26 +int op, verify = 0; 2.27 +const char *devname = "/dev/ttyUSB0"; 2.28 +char *fname = 0; 2.29 +uint32_t start_addr; 2.30 +int read_size = 128 * 1024; 2.31 + 2.32 +int main(int argc, char **argv) 2.33 +{ 2.34 + FILE *fp, *devfp; 2.35 + int dev; 2.36 + struct termios term; 2.37 + 2.38 + if(parse_args(argc, argv) == -1) { 2.39 + return 1; 2.40 + } 2.41 + 2.42 + if((dev = open(devname, O_RDWR)) == -1) { 2.43 + fprintf(stderr, "failed to open device %s: %s\n", devname, strerror(errno)); 2.44 + return 1; 2.45 + } 2.46 + if(tcgetattr(dev, &term) == -1) { 2.47 + fprintf(stderr, "failed to get terminal attributes for %s: %s\n", devname, strerror(errno)); 2.48 + return 1; 2.49 + } 2.50 + term.c_cflag = CS8 | CLOCAL; 2.51 + term.c_iflag &= ~(IXON | IXOFF); 2.52 + term.c_lflag = 0; 2.53 + 2.54 + cfsetispeed(&term, B38400); 2.55 + cfsetospeed(&term, B38400); 2.56 + 2.57 + if(tcsetattr(dev, TCSANOW, &term) == -1) { 2.58 + fprintf(stderr, "failed to set terminal attributes for %s: %s\n", devname, strerror(errno)); 2.59 + return 1; 2.60 + } 2.61 + 2.62 + if(!(devfp = fdopen(dev, "r+"))) { 2.63 + perror("failed to attach I/O stream to the device file\n"); 2.64 + return 1; 2.65 + } 2.66 + setvbuf(devfp, 0, _IONBF, 0); 2.67 + 2.68 + if(fname && !(fp = fopen(fname, op == OP_READ ? "w" : "r"))) { 2.69 + fprintf(stderr, "failed to open %s: %s\n", fname, strerror(errno)); 2.70 + return 1; 2.71 + } 2.72 + 2.73 + switch(op) { 2.74 + case OP_WRITE: 2.75 + if(op_write(devfp, fp) == -1) { 2.76 + fprintf(stderr, "write failed\n"); 2.77 + return 1; 2.78 + } 2.79 + break; 2.80 + 2.81 + case OP_READ: 2.82 + if(op_read(devfp, fp) == -1) { 2.83 + fprintf(stderr, "read failed\n"); 2.84 + return 1; 2.85 + } 2.86 + break; 2.87 + 2.88 + case OP_RESET: 2.89 + if(op_reset(devfp) == -1) { 2.90 + fprintf(stderr, "reset failed\n"); 2.91 + return 1; 2.92 + } 2.93 + break; 2.94 + 2.95 + default: 2.96 + break; 2.97 + } 2.98 + 2.99 + fclose(devfp); 2.100 + close(dev); 2.101 + if(fp) { 2.102 + fclose(fp); 2.103 + } 2.104 + return 0; 2.105 +} 2.106 + 2.107 +#define RET_IF_FAIL(x) \ 2.108 + if(!fgets(buf, sizeof buf, dev) || buf[0] != 'O') return x 2.109 + 2.110 +int op_write(FILE *dev, FILE *fp) 2.111 +{ 2.112 + char buf[128]; 2.113 + int c; 2.114 + 2.115 + fprintf(dev, "p\n"); 2.116 + RET_IF_FAIL(-1); 2.117 + fprintf(dev, "a%d\n", start_addr); 2.118 + RET_IF_FAIL(-1); 2.119 + 2.120 + while((c = fgetc(fp)) != -1) { 2.121 + fprintf(dev, "w%d\n", c); 2.122 + RET_IF_FAIL(-1); 2.123 + } 2.124 + 2.125 + fprintf(dev, "b\n"); 2.126 + RET_IF_FAIL(-1); 2.127 + return 0; 2.128 +} 2.129 + 2.130 +int op_read(FILE *dev, FILE *fp) 2.131 +{ 2.132 + char buf[128]; 2.133 + int i, val; 2.134 + 2.135 + fprintf(dev, "p\n"); 2.136 + RET_IF_FAIL(-1); 2.137 + fprintf(dev, "a%d\n", start_addr); 2.138 + RET_IF_FAIL(-1); 2.139 + 2.140 + for(i=0; i<read_size; i++) { 2.141 + fprintf(dev, "r\n"); 2.142 + if(!fgets(buf, sizeof buf, dev) || buf[0] != 'O') { 2.143 + fprintf(stderr, "read error after %d bytes\n", i); 2.144 + break; 2.145 + } 2.146 + val = atoi(buf + 3); /* skip 'O', 'K', ' ' */ 2.147 + fputc(val, fp); 2.148 + } 2.149 + 2.150 + fprintf(dev, "b\n"); 2.151 + RET_IF_FAIL(-1); 2.152 + return 0; 2.153 +} 2.154 + 2.155 +int op_reset(FILE *dev) 2.156 +{ 2.157 + char buf[128]; 2.158 + fprintf(dev, "p\n"); 2.159 + RET_IF_FAIL(-1); 2.160 + fprintf(dev, "b\n"); 2.161 + RET_IF_FAIL(-1); 2.162 + return 0; 2.163 +} 2.164 + 2.165 +int parse_args(int argc, char **argv) 2.166 +{ 2.167 + int i; 2.168 + 2.169 + for(i=1; i<argc; i++) { 2.170 + if(strcmp(argv[i], "-w") == 0 || strcmp(argv[i], "-write") == 0) { 2.171 + op = OP_WRITE; 2.172 + if(!(fname = argv[++i])) { 2.173 + fprintf(stderr, "%s must be followed by a filename\n", argv[i - 1]); 2.174 + return -1; 2.175 + } 2.176 + 2.177 + } else if(strcmp(argv[i], "-r") == 0 || strcmp(argv[i], "-read") == 0) { 2.178 + op = OP_READ; 2.179 + if(!(fname = argv[++i])) { 2.180 + fprintf(stderr, "%s must be followed by a filename\n", argv[i - 1]); 2.181 + return -1; 2.182 + } 2.183 + 2.184 + } else if(strcmp(argv[i], "-a") == 0 || strcmp(argv[i], "-addr") == 0) { 2.185 + char *endp; 2.186 + if(!argv[++i] || ((start_addr = strtol(argv[i], &endp, 0)), endp == argv[i])) { 2.187 + fprintf(stderr, "%s must be followed by an address\n", argv[i - 1]); 2.188 + return -1; 2.189 + } 2.190 + 2.191 + } else if(strcmp(argv[i], "-R") == 0 || strcmp(argv[i], "-reset") == 0) { 2.192 + op = OP_RESET; 2.193 + 2.194 + } else if(strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "-size") == 0) { 2.195 + char *endp; 2.196 + if(!argv[++i] || ((read_size = strtol(argv[i], &endp, 0)), endp == argv[i])) { 2.197 + fprintf(stderr, "%s must be followed by a size in bytes\n", argv[i - 1]); 2.198 + return -1; 2.199 + } 2.200 + 2.201 + } else if(strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "-verify") == 0) { 2.202 + verify = 1; 2.203 + 2.204 + } else if(strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "-device") == 0) { 2.205 + devname = argv[++i]; 2.206 + 2.207 + } else if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-help") == 0) { 2.208 + printf("Usage: %s [options]\n", argv[0]); 2.209 + printf("Options:\n"); 2.210 + printf(" -w|-write <filename>\n"); 2.211 + printf(" -r|-read <filename>\n"); 2.212 + printf(" -a|-addr <address>: start address for read/write operations\n"); 2.213 + printf(" -R|-reset: reboot machine\n"); 2.214 + printf(" -v|-verify: do verification after writing\n"); 2.215 + printf(" -s|-size: read size in bytes\n"); 2.216 + printf(" -d|-device <device file>: serial device (eg /dev/ttyUSB0)\n"); 2.217 + printf(" -h|-help: print usage and exit\n"); 2.218 + return 0; 2.219 + 2.220 + } else { 2.221 + fprintf(stderr, "invalid argument: %s\n", argv[i]); 2.222 + return -1; 2.223 + } 2.224 + } 2.225 + 2.226 + if(!op) { 2.227 + fprintf(stderr, "you must specify an operation\n"); 2.228 + return -1; 2.229 + } 2.230 + return 0; 2.231 +}