ようこそゲストさん

無能日記

メッセージ欄

分類 【R&D (remote)】 で検索

一覧で表示する

2006/09/17(日) クロッサム2+USB

はてブ 2007/04/09 13:03 R&D (remote)poti
以前買ってきたクロッサム2+USBで遊ぶ

USBシリアルとして認識(カーネル再構築必要)させた後、
/dev/ttyU00とかという名前で見えるようになるので、
普通にたたいてあげる。

ただ、何故かレスポンスが返ってこないのがあったりした。
(仕様書には、レスポンスが返ってくるように書かれているが実は帰ってこない?!)

以下ソースコードです。
結構適当です。(SLEEP長すぎ!)
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <errno.h>

#define DEVNAME "/dev/ttyUSB0"
#define DEVNAMBUFF 256
#define LINEBUFF 256

#define INITCMD "\r/c\r"
#define INITCMDLEN strlen("\r/c\r")

#define RESPONSE_TIMEOUT 10
#define COMMAND_SLEEP 1

#define GetDial(c) (c/41)
#define GetKey(c) (c%41)
#define GetCode(d,k) (d*41 +k)

unsigned char PatchData[] = {
        0xA2,0x10,0xBD,0x23,0x10,0x9D,0x00,0x01,    /* 0 */
        0xCA,0x10,0xF7,0xA2,0x40,0xBD,0x33,0x10,
        0x9D,0x00,0x0B,0xCA,0x10,0xF7,0x3C,0x00,    /* 1 */
        0x2B,0x3C,0x00,0x2C,0x3C,0x32,0x06,0x58,
        0x4C,0x00,0x0B,0x7F,0xD7,0x3C,0x80,0xDF,    /* 2 */
        0x8F,0xDE,0x42,0xEA,0x20,0x58,0xC4,0x4C,
        0x15,0x0B,0x00,0x4F,0xFE,0x6F,0xFF,0x8F,    /* 3 */
        0xFE,0x3C,0x00,0xDA,0xCF,0xDA,0x64,0x06,
        0xD0,0x05,0x6F,0xFE,0x4C,0x00,0x01,0xC2,    /* 4 */
        0x9F,0xFE,0x7F,0xFF,0x20,0xEE,0xC0,0x20,
        0xC8,0xC5,0x9F,0xFC,0x20,0x2A,0x0B,0xA5,    /* 5 */
        0x25,0xD0,0xED,0x80,0xD6,0xA7,0x23,0x01,
        0x60,0xBF,0x23,0x3C,0x00,0x2A,0xA2,0x00,    /* 6 */
        0x20,0x44,0xCD,0xC9,0x2F,0xD0,0xF1,0xE8,
        0x4C,0x9E,0xC9,0xFF,0xFF,0xFF,0xFF,0xFF,    /* 7 */
        0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
};

static int 
serial_open(const char *devname, struct termios *oldtio) {
        struct termios newtio;
        int fd;

        if (devname == NULL) {
                fprintf(stderr, "serial device name is NULL\n");
                return -1;
        }

        if ((fd = open(devname, O_RDWR|O_NOCTTY)) < 0) {
                fprintf(stderr, "can't open device file\n");
                return -1;
        }
 
        if (tcgetattr(fd, oldtio) < 0) {
                fprintf(stderr, "failed tcgetattr()\n");
                return -1;
        }

        memset(&newtio, 0, sizeof(struct termios));

        newtio.c_cflag = B9600 | CS8 | CLOCAL | CREAD;
        newtio.c_iflag = IGNPAR | ICRNL;
        newtio.c_oflag = 0;
        newtio.c_lflag = ICANON;
        cfmakeraw(&newtio);
      newtio.c_cc[VINTR]    = 0;     /* Ctrl-c */ 
        newtio.c_cc[VQUIT]    = 0;     /* Ctrl-\ */
        newtio.c_cc[VERASE]   = 0;     /* del */
        newtio.c_cc[VKILL]    = 0;     /* @ */
        newtio.c_cc[VEOF]     = 4;     /* Ctrl-d */
        newtio.c_cc[VTIME]    = 0;     /* not use charactor timer */
        newtio.c_cc[VMIN]     = 1;     /* block while one charactor */
        newtio.c_cc[VSWTC]    = 0;     /* '\0' */
        newtio.c_cc[VSTART]   = 0;     /* Ctrl-q */ 
        newtio.c_cc[VSTOP]    = 0;     /* Ctrl-s */
        newtio.c_cc[VSUSP]    = 0;     /* Ctrl-z */
        newtio.c_cc[VEOL]     = 0;     /* '\0' */
        newtio.c_cc[VREPRINT] = 0;     /* Ctrl-r */
        newtio.c_cc[VDISCARD] = 0;     /* Ctrl-u */
        newtio.c_cc[VWERASE]  = 0;     /* Ctrl-w */
        newtio.c_cc[VLNEXT]   = 0;     /* Ctrl-v */
        newtio.c_cc[VEOL2]    = 0;     /* '\0' */

        if (tcflush(fd, TCIFLUSH) < 0) {
                fprintf(stderr, "failed tcflush()\n");
                return -1;
        }
        if (tcsetattr(fd,TCSANOW,&newtio) < 0) {
                fprintf(stderr, "failed tcsetattr()\n");
                return -1;
        }

        return fd;
}

static int 
serial_initialize(int fd) {
        unsigned char initdat[LINEBUFF];
        int writelen;
        int i;

        if (fd < 0) {
                fprintf(stderr, "invalid file discriptor\n");
                return 1;
        }

        memset(initdat, 0xFF, LINEBUFF);
        memcpy(initdat, PatchData, sizeof(PatchData)); 

        writelen = write(fd, initdat, LINEBUFF);

        for (i = 0; i < LINEBUFF; i++) {
                if (i % 16 == 0) {
                        printf("\n");
                }
                printf("%02x ", initdat[i]);
        }
        printf("\n");
        printf("write data = %d\n", writelen);

        if (writelen != LINEBUFF) {
                fprintf(stderr, "write failed initial data\n");
                return 1;
        }
        return 0;
}
static int 
serial_close(int fd, struct termios *oldtio) {

        if (fd < 0) {
                fprintf(stderr, "invalid file discriptor\n");
                return 1;
        }

        if (tcsetattr(fd, TCSANOW, oldtio) < 0){
                fprintf(stderr, "failed tcsetattr()\n");
                return 1;
        }

        if (close(fd) < 0){
                fprintf(stderr, "failed close()\n");
                return 1;
        }
        return 0;
}
static int
get_response(int fd, unsigned char *resbuff, int buflen) {
        fd_set rfds;
        int fdmax;
        struct timeval tv;
        int retval;
        int len;
        int i;

        memset(resbuff, 0, buflen);

        FD_ZERO(&rfds);
        FD_SET(fd, &rfds);
        fdmax = fd + 1;

        tv.tv_sec = RESPONSE_TIMEOUT;
        tv.tv_usec = 0;

        retval = select(fdmax, &rfds, NULL, NULL, &tv);
        if (retval < 0) {
                fprintf(stderr, "select error fd = %d errcode = %d\n", 
                    fd, errno);
        } else if (retval) {
                if (FD_ISSET(fd, &rfds)) { 
                        len = read(fd, resbuff, LINEBUFF);
                        resbuff[len] = '\0';
                        fprintf(stderr, "command response <%s>\n", resbuff);
                }
        } else {
                fprintf(stderr, "response timeout\n");
        }
        return 0;
}

static int
cmd_loop(int fd) {
        int end = 0;
        int len;
        unsigned char reqcmd[LINEBUFF];
        unsigned char makecmd[LINEBUFF];
        unsigned char resbuff[LINEBUFF];
        int i;

        if (fd < 0) {
                fprintf(stderr, "invalid file discriptor\n");
                return 1;
        }

        while (end == 0) {
                printf(">");
                fgets(reqcmd, LINEBUFF, stdin);
                len = strlen(reqcmd);
                reqcmd[len - 1] = '\0';
                if (len < 2) {
                        fprintf(stderr, "invalid command %s\n", reqcmd);
                        continue;
                }
                if (strncmp(reqcmd, "/C", 2) == 0) {
                        write(fd, INITCMD, INITCMDLEN);
                        sleep(COMMAND_SLEEP);
                        continue;
                } else if (strncmp(reqcmd, "/I", 2) == 0) {
                        get_response(fd, resbuff, LINEBUFF);
                        serial_initialize(fd);
                        sleep(COMMAND_SLEEP);
                        continue;
                } else if (strncmp(reqcmd, "/q", 2) == 0) {
                        end = 1;
                        continue;
                } else if(strncmp(reqcmd, "/c", 2) != 0 && 
                    strncmp(reqcmd, "/t", 2) != 0 && 
                    strncmp(reqcmd, "/k", 2) != 0 && 
                    strncmp(reqcmd, "/i", 2) != 0 && 
                    strncmp(reqcmd, "/p", 2) != 0 && 
                    strncmp(reqcmd, "/r", 2) != 0) { 
                        fprintf(stderr, "unexpected command\n");
                        continue;
                }

                fprintf(stderr, "try send clear command \n");
                write(fd, INITCMD, INITCMDLEN);
                sleep(COMMAND_SLEEP);
                write(fd, INITCMD, INITCMDLEN);
                sleep(COMMAND_SLEEP);
                get_response(fd, resbuff, LINEBUFF);
                if (strncmp(resbuff, "Ok\r\n", 4) != 0) {
                        continue;
                } else {
                        fprintf(stderr, "response is \"Ok\"\n");
                }

                fprintf(stderr, "try send command <%s> (%d)\n", 
                    reqcmd, strlen(reqcmd));

                snprintf(makecmd, LINEBUFF, "\r%s\r", reqcmd);

                write(fd, makecmd, strlen(makecmd));
                sleep(COMMAND_SLEEP);

        }
        return 0;
}int main(int argc, char **argv) {
        int fd = -1;
        int len;
        unsigned char devname[DEVNAMBUFF];
        unsigned char readbuff[LINEBUFF];
        struct termios oldtio;
        int ch;
        int init = 0;

        strcpy(devname, DEVNAME);

        while ((ch = getopt(argc, argv, "id:")) != -1){
                switch (ch){
                case 'i':
                        init = 1;
                        break;
                case 'd':
                        strcpy(devname, optarg);
                        break;
                default:
                        fprintf(stderr, "%s -i -d <devname>\n", argv[0]);
                        exit(1);
                }
        }

        if ((fd = serial_open(devname, &oldtio)) < 0) {
                fprintf(stderr, "can't open serial\n");
                return 1;
        }

        if (init) {
                printf("please init\n");
                if ((len = read(fd, readbuff, LINEBUFF)) < 0) {
                        fprintf(stderr, "fatal command handling\n");
                        return 1;
                }
                readbuff[len] = '\0';
                printf("response %s\n", readbuff); 

                if (serial_initialize(fd)) {
                        fprintf(stderr, "can't nitialize serial\n");
                        return 1;
                }
        }
        if (cmd_loop(fd)) {
                fprintf(stderr, "fatal command handling\n");
                return 1;
        }

        if (serial_close(fd, &oldtio)) {
                fprintf(stderr, "can't close serial\n");
                return 1;
        }
        return 0;
}
/t3,3とかやったりするとチャンネルが変えれます
だからなんだ。。。。
近いうちにCGI化します。じゃないと意味なさそう。