MySmartUSB-MK3-Interface

MySmartUSB MK3 Interface
git clone git://xatko.vsos.ethz.ch/MySmartUSB-MK3-Interface.git
Log | Files | Refs

commit 3cdfc00cde4b68971b98c5bf31ab8dfea7e92a8b
Author: Dominik Schmidt <das1993@hotmail.com>
Date:   Mon, 10 Dec 2012 00:00:04 +0100

Initial Commit

Diffstat:
Makefile | 10++++++++++
cmd.c | 147+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cmd.h | 29+++++++++++++++++++++++++++++
com.c | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
com.h | 7+++++++
ctrl.c | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
dev.c | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
dev.h | 6++++++
log.c | 31+++++++++++++++++++++++++++++++
log.h | 19+++++++++++++++++++
main.c | 0
11 files changed, 525 insertions(+), 0 deletions(-)

diff --git a/Makefile b/Makefile @@ -0,0 +1,10 @@ +CC = /usr/bin/gcc +CFLAGS = -O2 -I. +TARGET = ctrl +LIBS = cmd.o dev.o log.o com.o +.PHONY: $(TARGET) +$(TARGET): $(LIBS) + $(CC) $(CFLAGS) $(TARGET).c -o $@ $(LIBS) + +%.o: %.c + $(CC) -c $(CFLAGS) -o $@ $< diff --git a/cmd.c b/cmd.c @@ -0,0 +1,147 @@ +#include <cmd.h> +#include <log.h> +#include <com.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +char COMMAND_TYPE_names[COMMAND_COUNT][COMMAND_TYPE_names_length]={"Status","Reset","Board-Reset","Board-power","Reset-line","Rescue-clock"}; + +int cmd_board_reset(struct command *cmd,int fd){ + if(sendMagicPacket(fd,'r')<0){ + do_log("cmd_board_reset","Couldn't send reset packet", LOG_LEVEL_ERROR, LOG_TYPE_NORMAL); + return -1; + } + int ret=0; + char *buf=readString(fd,3); + if(parseMagicPacket(buf)=='r'){ + ret=-2; + } + free(buf); + return ret; +} +int cmd_reset(struct command *cmd, int fd){ + if(sendString(fd,"@main reset")<0){ + do_log("cmd_reset","Couldn't send reset string", LOG_LEVEL_ERROR, LOG_TYPE_NORMAL); + return -1; + } + char *ret=readString(fd, 0); + if(checkIfOk(ret)){ + do_log("cmd_reset","Couldn't reset device", LOG_LEVEL_ERROR, LOG_TYPE_NORMAL); + free(ret); + return -2; + } + free(ret); + return 0; +} +int cmd_status(struct command *cmd, int fd){ + if(sendMagicPacket(fd,'i')<0){ + do_log("cmd_board_reset","Couldn't send status request packet", LOG_LEVEL_ERROR, LOG_TYPE_NORMAL); + return -1; + } + char *ret=readString(fd, 3); + char c=parseMagicPacket(ret); + do_log("cmd_status", &c, LOG_LEVEL_INFO, LOG_TYPE_NORMAL); + free(ret); + return 0; +} +int cmd_reset_line(struct command *cmd, int fd){ + char c=0; + if(*(char*)cmd->data!='1'&&*(char*)cmd->data!='0'){ + do_log("cmd_reset_line","Value must be either 1 or 0",LOG_LEVEL_ERROR,LOG_TYPE_NORMAL); + return -1; + } + char str[]={'@','l','i','n','e','s',' ','r','s','t',' ',c}; + if(sendString(fd,str)<0){ + do_log("cmd_reset_line","Couldn't send power string", LOG_LEVEL_ERROR, LOG_TYPE_NORMAL); + return -2; + } + char *r=readString(fd,0); + printf("%s\n",r); + if(!checkIfOk(r)){ + do_log("cmd_reset_line","Couldn't set reset line", LOG_LEVEL_ERROR, LOG_TYPE_NORMAL); + free(r); + return -3; + } + free(r); + return 0; +} +int cmd_board_power(struct command *cmd, int fd){ + char c=0; + if(*(char*)cmd->data=='1'){ + c='+'; + } + else if(*(char*)cmd->data=='0'){ + c='-'; + } + else{ + do_log("cmd_board_power","Value must be either 1 or 0",LOG_LEVEL_ERROR,LOG_TYPE_NORMAL); + return -1; + } + if(sendMagicPacket(fd,c)<0){ + do_log("cmd_board_reset","Couldn't send power string", LOG_LEVEL_ERROR, LOG_TYPE_NORMAL); + return -2; + } + char r=readMagicPacket(fd); + if(r!=c){ + return -3; + } + return 0; +} +int executeCommand(struct command *cmd, int fd){ + int (*func)(struct command *, int)=NULL; + switch(cmd->type){ + case COMMAND_BOARD_RESET: + func=&cmd_board_reset; + break; + case COMMAND_RESET: + func=&cmd_reset; + break; + case COMMAND_STATUS: + func=&cmd_status; + break; + case COMMAND_BOARD_POWER: + func=&cmd_board_power; + break; + case COMMAND_RESET_LINE: + func=&cmd_reset_line; + break; + default: + do_log("executeCommand", "Commandtype unknown", LOG_LEVEL_ERROR, LOG_TYPE_NORMAL); + return -1; + break; + } + if(func(cmd,fd)<0){ + do_log("executeCommand","Couldn't execute command",LOG_LEVEL_ERROR,LOG_TYPE_NORMAL); + } + else{ + do_log("executeCommand","Executing successfull",LOG_LEVEL_DEBUG,LOG_TYPE_NORMAL); + } + return 0; +} +int processCommands(struct command **cmdlist, int fd){ + unsigned int i=0; + char *str=malloc(strlen("Executing command %s failed")+COMMAND_TYPE_names_length); + while(cmdlist[i]!=NULL){ + sprintf(str,"Executing command %s",COMMAND_TYPE_names[cmdlist[i]->type]); + do_log("processCommands",str,LOG_LEVEL_DEBUG,LOG_TYPE_NORMAL); + if(executeCommand(cmdlist[i], fd)<0){ + sprintf(str,"Executing command %s failed",COMMAND_TYPE_names[cmdlist[i]->type]); + do_log("processCommands",str,LOG_LEVEL_ERROR,LOG_TYPE_NORMAL); + } + i++; + } + return 0; +} +struct command *newCommand(unsigned short type){ + struct command *cmd; + unsigned int i=0; + if(type>COMMAND_TYPEARGS_00){ + i=1; + } + else if(type>COMMAND_TYPEARGS_01){ + i=2; + } + cmd=(struct command *)malloc(sizeof(struct command)-1+i); + cmd->type=type; + return cmd; +} diff --git a/cmd.h b/cmd.h @@ -0,0 +1,29 @@ +#pragma once + +enum COMMAND_TYPE{ + COMMAND_STATUS=0, + COMMAND_RESET, + COMMAND_BOARD_RESET, + COMMAND_TYPEARGS_00=COMMAND_BOARD_RESET, + COMMAND_BOARD_POWER, + COMMAND_RESET_LINE, + COMMAND_RESCUE_CLOCK, + COMMAND_TYPEARGS_01=COMMAND_RESCUE_CLOCK, + COMMAND_TYPEARGS_02=COMMAND_TYPEARGS_01, + COMMAND_COUNT +}; +#define COMMAND_TYPE_names_length 18 +struct command{ + unsigned short type; + void *data; +}; +extern char COMMAND_TYPE_names[COMMAND_COUNT][COMMAND_TYPE_names_length]; + + +extern int cmd_board_reset(struct command *cmd,int fd); +extern int cmd_reset(struct command *cmd, int fd); +extern int cmd_status(struct command *cmd, int fd); +extern int cmd_board_power(struct command *cmd, int fd); +extern int executeCommand(struct command *cmd, int fd); +extern int processCommands(struct command **cmdlist, int fd); +extern struct command *newCommand(unsigned short type); diff --git a/com.c b/com.c @@ -0,0 +1,85 @@ +#include <com.h> +#include <log.h> +#include <stdlib.h> +#include <cmd.h> +#include <string.h> +#include <stdio.h> +char *readString(int fd, unsigned int length){ + unsigned int size=10; + char *str=malloc(size); + + unsigned int i=0; + char c; + int ret; + while((ret=read(fd,&c,sizeof(char)))){ + if(ret<=0){ + do_log("readString","Read Error",LOG_LEVEL_ERROR,LOG_TYPE_SIGNAL); + free(str); + return NULL; + } + if(i+1>=size){ + size+=10; + str=realloc((void *)str,size); + } + if(length!=0&&i>=length){ + str[i]='\0'; + break; + } + if(c==0x0A){ + str[i]='\0'; + } + else if(c==0){ + continue; + } + else{ + str[i]=c; + } + i++; + } + return str; +} +char readMagicPacket(int fd){ + int ret; + char c,r; + r=0; + unsigned int i=0; + while((ret=read(fd,&c,sizeof(char)))){ + if(ret<=0){ + do_log("readString","Read Error",LOG_LEVEL_ERROR,LOG_TYPE_SIGNAL); + return 0; + } + if(c==0x0A){ + break; + } + else if((c>='a'&&c<='z')||c=='+'||c=='-'){ + r=c; + } + } + return r; +} +int sendRawString(int fd, const char *str){ + return write(fd,str,strlen(str)); +} +int sendString(int fd, const char *str){ + unsigned int length=strlen(str); + char *newstr=malloc(length+1); + strcpy(newstr,str); + newstr[length]=0xA; + return write(fd,newstr,length+1); +} +int sendMagicPacket(int fd, char c){ + char magic[]={0xE6,0xB5,0xBA,0xB9,0xB2,0xB3,0xA9,c}; + return sendRawString(fd,magic); +} +char parseMagicPacket(char *str){ + unsigned int i=0; + for(i=0; i<strlen(str);i++){ + if((str[i]>='a'&&str[i]<='z')||str[i]=='+'||str[i]=='-'){ + return str[i]; + } + } + return 0; +} +int checkIfOk(char *str){ + return (str[0]=='o'&&str[1]=='k'); +} diff --git a/com.h b/com.h @@ -0,0 +1,7 @@ +#pragma once +extern char *readString(int fd, unsigned int length); +extern int sendRawString(int fd, const char *str); +extern int sendString(int fd, const char *str); +extern int sendMagicPacket(int fd, char c); +extern int checkIfOk(char *str); +char parseMagicPacket(char *str); diff --git a/ctrl.c b/ctrl.c @@ -0,0 +1,96 @@ +#include <stdio.h> +#include <log.h> +#include <cmd.h> +#include <stdlib.h> +#include <termios.h> +#include <com.h> + +struct conf{ + struct command **cmdlist; + unsigned short int need_mymode; + char oldmode; +}; +struct conf config; + +char *filename; +unsigned short int log_level=LOG_LEVEL_DEBUG; + +int parseArguments(int argc, char **argv, struct conf *config){ + unsigned int i=0; + unsigned int cmdcnt=0; + unsigned int alloc=10; + config->cmdlist=(struct command **)malloc(alloc*sizeof(struct command **)); + struct command *newcmd; + + for(i=0;i<argc;i++){ + newcmd=NULL; + if(strcmp(argv[i],"-R")==0){ + newcmd=newCommand(COMMAND_RESET); + config->need_mymode=1; + } + else if(strcmp(argv[i],"-r")==0){ + newcmd=newCommand(COMMAND_BOARD_RESET); + } + else if(strcmp("-s", argv[i])==0){ + newcmd=newCommand(COMMAND_STATUS); + } + else if(strcmp("-p", argv[i])==0){ + newcmd=newCommand(COMMAND_BOARD_POWER); + newcmd->data=argv[++i]; + } + else if(strcmp("-rL", argv[i])==0){ + newcmd=newCommand(COMMAND_RESET_LINE); + newcmd->data=argv[++i]; + config->need_mymode=1; + } + + if(newcmd!=NULL){ + if(cmdcnt+1>alloc){ + alloc+=10; + config->cmdlist=realloc((void *)config->cmdlist, alloc*sizeof(struct command **)); + } + config->cmdlist[cmdcnt]=newcmd; + cmdcnt++; + } + } + config->cmdlist[cmdcnt]=NULL; + return 0; +} +int prepareCommandExecution(int fd, struct conf *config){ + config->oldmode=0; + if(config->need_mymode){ + sendMagicPacket(fd,'i'); + config->oldmode=readMagicPacket(fd); + if(config->oldmode!='m'){ + sendMagicPacket(fd,'m'); + setBaudRate(fd,B500000); + if(readMagicPacket(fd)!='m'){ + do_log("prepareCommandExecution","Couldn't switch to mymode",LOG_LEVEL_ERROR,LOG_TYPE_NORMAL); + return -1; + } + } + + } + return 0; +} +int finishCommandExecution(int fd, struct conf *config){ + if(config->oldmode>0){ + sendMagicPacket(fd,config->oldmode); + } +} +int main(int argc, char **argv){ + filename=argv[0]; + parseArguments(argc-1, &argv[1],&config); + + int fd=openDevice("/dev/ttyUSB0"); + if(fd<0){ + do_log("main","Couldn't open device",LOG_LEVEL_FATAL,LOG_TYPE_NORMAL); + return 1; + } + prepareCommandExecution(fd, &config); + processCommands(config.cmdlist,fd); + finishCommandExecution(fd, &config); + + closeDevice(fd); + return 0; +} diff --git a/dev.c b/dev.c @@ -0,0 +1,95 @@ +#include <dev.h> +#include <termios.h> +#include <log.h> +#include <cmd.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <stdlib.h> +#include <com.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +int closeDevice(int dev){ + fsync(dev); + return close(dev); +} +int autoConfigBaud(int fd){ + speed_t speed[3]={B500000, B115200, B19200}; + unsigned int i=0; + struct command query; + query.type=COMMAND_STATUS; + for(i=0;i<=3; i++){ + sendMagicPacket(fd,'i'); + char c=readMagicPacket(fd); + if(c!=0){ + break; + } + + if(i==3){ + do_log("autoConfigBaud","Couldn't evaluate correct baudrate", LOG_LEVEL_FATAL,LOG_TYPE_NORMAL); + return -1; + } + if(setBaudRate(fd,speed[i])<0){ + do_log("autoConfigBaud","Couldn't set baudrate", LOG_LEVEL_FATAL,LOG_TYPE_NORMAL); + return -2; + } + } + + return 0; +} +int setBaudRate(int fd, speed_t baud){ + struct termios options; + if(tcgetattr(fd, &options)<0){ + do_log("setBaudRate","Couldn't load Options",LOG_LEVEL_ERROR,LOG_TYPE_SIGNAL); + return -1; + } + if(cfsetispeed(&options, baud)<0){ + do_log("setBaudRate","Couldn't set InputSpeed",LOG_LEVEL_ERROR,LOG_TYPE_SIGNAL); + closeDevice(fd); + return -2; + } + if(cfsetospeed(&options, baud)<0){ + do_log("setBaudRate","Couldn't set OutputSpeed",LOG_LEVEL_ERROR,LOG_TYPE_SIGNAL); + closeDevice(fd); + return -3; + } + if(tcsetattr(fd, TCSANOW, &options)<0){ + do_log("setBaudRate","Couldn't set Options",LOG_LEVEL_ERROR,LOG_TYPE_SIGNAL); + closeDevice(fd); + return -4; + } + return 0; + +} +int openDevice(char *dev){ + int fd = open(dev, O_RDWR | O_NOCTTY ); + if(fd<0){ + do_log("openDevice", "Couldn't open Device", LOG_LEVEL_FATAL,LOG_TYPE_SIGNAL); + return -1; + } + ioctl(fd, TIOCEXCL); + struct termios options; + tcgetattr(fd, &options); + + options.c_cflag|=(CLOCAL | CREAD); + options.c_cflag&=~CSIZE; + options.c_cflag|=CS8; + options.c_cflag&=~PARENB; + options.c_cflag&=~CSTOPB; + options.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG); + options.c_iflag &= ~(IXON | IXOFF | IXANY ); + options.c_oflag &= ~(OCRNL | ONLCR | ONLRET |ONOCR | OFILL | OLCUC | OPOST); + + options.c_cc[VTIME]=5; + options.c_cc[VMIN]=0; + + if(tcsetattr(fd, TCSANOW, &options)<0){ + do_log("openDevice","Couldn't set Options",LOG_LEVEL_FATAL,LOG_TYPE_SIGNAL); + closeDevice(fd); + return -4; + } + if(autoConfigBaud(fd)<0){ + return -5; + } + return fd; +} diff --git a/dev.h b/dev.h @@ -0,0 +1,6 @@ +#pragma once +#include <termios.h> +extern int closeDevice(int dev); +extern int autoConfigBaud(int fd); +extern int openDevice(char *dev); +extern int setBaudRate(int fd, speed_t baud); diff --git a/log.c b/log.c @@ -0,0 +1,31 @@ +#include <log.h> +#include <stdio.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +char LOG_LEVEL_names[LOG_LEVEL_COUNT][8]={"DEBUG","INFO","WARNING","ERROR","FATAL"}; +void log_string(char *str, unsigned short int level){ + FILE *stream; + if(level>=LOG_LEVEL_WARNING){ + stream=stderr; + } + else{ + stream=stdout; + } + fprintf(stream,"%s\n",str); +} +void do_log(char *src, char *msg, unsigned short int level, unsigned short int type){ + int error=errno; + char *str=malloc(strlen("%s[%s]: %s (%s)")+strlen(src)+strlen(msg)+strlen(LOG_LEVEL_names[level])+strlen(strerror(error))); + if(type==LOG_TYPE_SIGNAL){ + sprintf(str,"%s[%s]: %s (%s)",LOG_LEVEL_names[level],src,msg,strerror(error)); + } + else if(type==LOG_TYPE_RESULT){ + sprintf(str,"%s",msg); + } + else{ + sprintf(str,"%s[%s]: %s",LOG_LEVEL_names[level],src,msg); + } + log_string(str,level); + free(str); +} diff --git a/log.h b/log.h @@ -0,0 +1,19 @@ +#pragma once +enum LOG_TYPE{ + LOG_TYPE_RESULT, + LOG_TYPE_NORMAL, + LOG_TYPE_SIGNAL +}; +enum LOG_LEVEL{ + LOG_LEVEL_DEBUG, + LOG_LEVEL_INFO, + LOG_LEVEL_WARNING, + LOG_LEVEL_ERROR, + LOG_LEVEL_FATAL, + LOG_LEVEL_COUNT +}; + +extern void log_string(char *str, unsigned short int level); +extern void do_log(char *src, char *msg, unsigned short int level, unsigned short int type); +#define LOG_LEVEL_names_length 8 +extern char LOG_LEVEL_names[LOG_LEVEL_COUNT][LOG_LEVEL_names_length]; diff --git a/main.c b/main.c