Minggu, 25 Mei 2014

acr120.c //acr

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <sys/time.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "acr120.h"

#define STX 0x2
#define ETX 0x3

unsigned char *nib;

int acr120_errno;
static int acr120_proto_mode;
static struct termios old;

static void dec2nibble(unsigned int, unsigned char*);
static void nibble2dec(unsigned int*,unsigned char*);
static int check_bin_error(const unsigned char*, size_t);
static int check_ascii_error(const unsigned char*, size_t);
static int acr120_timeout(int, int);

static const char const *acr120_error[] = {
    "success", // 1
    "open device failure", // 2
    "close device failure",// 3
    "device setting failure",// 4
    "write device failure",// 5
    "read device failure",//6
    "select device failure",//7
    "operation timeout",//8
    "no TAG",//9
    "no value block",//10      
    "login fail, key wrong",//11
    "invalid key format (stored key)",//12
    "read failure",//13
    "unable to read after write",//14
    "read after write error",//15
    "write failure",//16
    "unable to read after increment",//17
    "increment failure",//18
    "unable to read after decrement",//19
    "decrement failure",//20
    "empty value decrement",//21
    "unable to read after copy",//22
    "copy failure",//23
    "data error"//24
};

static void dec2nibble(unsigned int value, unsigned char *nibble)
{
    nibble[3] = value & 0xff;
    nibble[2] = value >> 8 & 0xff;
    nibble[1] = value >> 16 & 0xff;
    nibble[0] = value >> 24 & 0xff;
}


static void nibble2dec(unsigned int *val,unsigned char *nibble)
{


int valoo = (nibble[3] & 0xff) | ((nibble[2] & 0xff) << 8) | ((nibble[1] & 0xff) << 16) | ((nibble[0] & 0xff) << 24);

*val = (nibble[0] & 0xff) | ((nibble[1] & 0xff) << 8) | ((nibble[2] & 0xff) << 16) | ((nibble[3] & 0xff) << 24);


printf("id *= %d\n",*val);
printf("id = %d\n",valoo);


}

static int check_bin_error(const unsigned char *ans, size_t len)
{
    unsigned char check = 0;
    int i, nc = len - 2 * sizeof(unsigned char );
    size_t bytes = 0;

    for (i = 1; i < nc; i++)
        check ^= ans[i];
    return (check == ans[nc]) ? 0 : 1;
}

static int check_ascii_error(const unsigned char *ans, size_t len)
{
    return (ans[len - 2] == 0xd && ans[len -1] == 0xa) ? 0 : 1;
}

const char* acr120_strerror(void)
{
    return acr120_error[acr120_errno - 1];
}

inline int acr120_open(const char *dev, unsigned char sid, speed_t speed)
{
    int fd, ret;
    unsigned char cmd[8], ans[6], val, check = 0;
    size_t bytes = 0;
    struct termios opt;

   // fd = open(dev, O_RDWR | O_NOCTTY, 0644);
   fd = open(dev, O_RDWR | O_NOCTTY, 0110);
    if (fd == -1) {
        acr120_errno = 2;
        return ACR120_ERROR;
    }

    ret = tcgetattr(fd, &opt);
    if (ret == -1) {
        close(fd);
        acr120_errno = 4;
        return ACR120_ERROR;
    }

    /* save previous setting to restore on close */
    memcpy(&old, &opt, sizeof(struct termios));

    cfsetispeed(&opt, speed);
    cfsetospeed(&opt, speed);
    /* set to canonical mode */
    opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    /* disable flow control both input and output */
    opt.c_iflag &= ~(IXON | IXOFF);
    /* disable CR-NL or NL-CR translation both input and output */
    opt.c_iflag &= ~(INLCR | ICRNL);
    opt.c_oflag &= ~(ONLCR | OCRNL);
    ret = tcsetattr(fd, TCSANOW, &opt);
    if (ret == -1) {
        close(fd);
        acr120_errno = 4;
        return ACR120_ERROR;
    }

    /* probe in ASCII mode */
    snprintf((char *) cmd, 5 * sizeof(unsigned char), "re%.2x",
             ACR120_REGISTER_PROTOCOL);
    ret = write(fd, cmd, 4 * sizeof(unsigned char));
    if (ret <= 0) {
        acr120_close(fd);
        acr120_errno = 5;
        return ACR120_ERROR;
    }

    ret = acr120_timeout(fd, 100);
    if (ret == ACR120_ERROR) {
        if (acr120_errno != 8) {
            close(fd);
            return ret;unsigned char cmd[8], ans[6], val, check = 0;
    size_t bytes = 0;
        }
        goto bin;
    } else {
          while (bytes < 4 * sizeof(unsigned char)) {
              ret = read(fd, ans + bytes, 4 * sizeof(unsigned char) - bytes);
              if (ret <= 0) {
                  close(fd);
                  acr120_errno = 6;
                  return ACR120_ERROR;
              }
              bytes += ret;
          }
          if (check_ascii_error(ans, 4)) {
              acr120_errno = 24;
              goto bin;
          }
          ans[2] = 0;
          sscanf((char*) ans, "%x", (unsigned int*) &val);
          goto done;
    }

bin:
    /* read protocol register to obtain protocol mode */
    cmd[0] = STX;
    cmd[1] = sid;
    cmd[2] = 0x3;
    cmd[3] = 'r';
    cmd[4] = 'e';
    cmd[5] = ACR120_REGISTER_PROTOCOL;
    cmd[6] = cmd[1] ^ cmd[2] ^ cmd[3] ^ cmd[4] ^ cmd[5];
    cmd[7] = ETX;

    /* probe in binary mode */
    ret = write(fd, cmd, sizeof(cmd));
    if (ret <= 0) {
        acr120_close(fd);
        acr120_errno = 5;
        return ACR120_ERROR;
    }

    bytes = 0;
    while (bytes < sizeof(ans)) {
        ret = acr120_timeout(fd, 100);
        if (ret == ACR120_ERROR) {
            close(fd);
            return ret;
        }
        ret = read(fd, ans + bytes, sizeof(ans) - bytes);
//printf("%x %x %x %x %x %x %x %x %x %x \n",ans[0],ans[1],ans[2],ans[3],ans[4],ans[5],ans[6],ans[7],ans[8],ans[9]);

        if (ret <= 0) {
            acr120_close(fd);
            acr120_errno = 6;

            return ACR120_ERROR;
        }
        bytes += ret;
        /* eventually there are no error code satisfied for
           reading register value, only check here for
           compability */
        if (bytes > 4 && !check) {
            switch (ans[3]) {
                case 'N':
                    acr120_close(fd);
                    acr120_errno = 9;
                    return ACR120_ERROR;
                case 'I':
                    acr120_close(fd);
                    acr120_errno = 10;
                    return ACR120_ERROR;
                case 'F':
                    acr120_close(fd);
                    acr120_errno = 13;
                    return ACR120_ERROR;
            }
            check ^= 1;
        }
    }

    if (check_bin_error(ans, sizeof(ans))) {
        acr120_close(fd);
        acr120_errno = 24;
        return ACR120_ERROR;
    }
    val = ans[3];

done:
    /* set protocol mode */
    acr120_proto_mode = val >> 1 & 0x1;
    acr120_errno = 1;
    return fd;
}

int acr120_close(int fd)
{
    int ret;

    /* restore previous setting */
    tcsetattr(fd, TCSANOW, &old);
    ret = close(fd);
    if (ret == -1) {
        acr120_errno = 3;
        return ACR120_ERROR;
    }
    acr120_errno = 1;
    return ACR120_SUCCESS;
}          

static int acr120_timeout(int fd, int timeout)
{
    int ret;
    fd_set rset;
    struct timeval val = { .tv_sec = 0, .tv_usec = 1000 * timeout };

    FD_ZERO(&rset);
    FD_SET(fd, &rset);
    ret = select(fd + 1, &rset, NULL, NULL, &val);
    if (ret == 0) {
        acr120_errno = 8;
        return ACR120_ERROR;
    }
    if (ret == -1) {
        acr120_errno = 7;
        return ACR120_ERROR;
    }
    if (FD_ISSET(fd, &rset)) {
        acr120_errno = 1;
        return ACR120_SUCCESS;
    }
    /* should never reach here */
    acr120_errno = 7;
    return ACR120_ERROR;
}

int acr120_reset(int fd, unsigned char sid, int reply, int timeout)
{
    int ret;
    unsigned char cmd[6], ans[12];
    size_t bytes = 0, nw, nr;

    if (acr120_proto_mode) {
        cmd[0] = STX;
        cmd[1] = sid;
        cmd[2] = 0x1;
        cmd[3] = 'x';
        cmd[4] = cmd[1] ^ cmd[2] ^ cmd[3];
        cmd[5] = ETX;
        nw = sizeof(cmd);
        /* no answer on binary mode */
        nr = 0;
    } else {
        cmd[0] = 'x';
        nw = sizeof(unsigned char);unsigned int *val,
        nr = reply ? sizeof(ans) : 0;
    }

    ret = write(fd, cmd, nw);
    if (ret <= 0) {
        acr120_errno = 5;
        return ACR120_ERROR;
    }

    while (bytes < nr) {
        if (timeout) {
            ret = acr120_timeout(fd, timeout);
            if (ret == ACR120_ERROR)
                return ret;
        }
       
        ret = read(fd, ans + bytes, nr - bytes);
        if (ret <= 0) {
            acr120_errno = 6;
            return ACR120_ERROR;
        }
        bytes += ret;
    }

    if (!acr120_proto_mode && reply) {
        if (check_ascii_error(ans, 12)) {
            acr120_errno = 24;
            return ACR120_ERROR;
        }
    }
   
    acr120_errno = 1;
    return ACR120_SUCCESS;
}

int acr120_get_id(int fd, unsigned char *id, int timeout)
{
    int ret;
    unsigned char cmd[6], ans[6];
    size_t bytes = 0;

    cmd[0] = STX;
    cmd[1] = 0xff;
    cmd[2] = 0x1;
    cmd[3] = 'g';
    cmd[4] = cmd[1] ^ cmd[2] ^ cmd[3];
    cmd[5] = ETX;

    ret = write(fd, cmd, sizeof(cmd));
    if (ret == -1) {
        acr120_errno = 5;
        return ACR120_ERROR;
    }

    while (bytes < sizeof(ans)) {
        if (timeout) {
            ret = acr120_timeout(fd, timeout);
            if (ret == ACR120_ERROR)
                return ret;
        }
        ret = read(fd, ans + bytes, sizeof(ans) - bytes);

        if (ret == -1) {
            acr120_errno = 6;

            return ACR120_ERROR;
        }
        bytes += ret;
    }

    if (id)
      *id = ans[3];

    acr120_errno = 1;

    return ACR120_SUCCESS;
}

int acr120_select(int fd, unsigned char sid, unsigned int *uid, int timeout)
{
    int ret;
    unsigned char cmd[6], ans[9], uids[4];
    size_t bytes = 0;

    cmd[0] = STX;
    cmd[1] = sid;
    cmd[2] = 0x1;
    cmd[3] = 's';
    cmd[4] = cmd[1] ^ cmd[2] ^ cmd[3];
    cmd[5] = ETX;

    ret = write(fd, cmd, sizeof(cmd));
    if (ret == -1) {
        acr120_errno = 5;
        return ACR120_ERROR;
    }
    while (bytes < sizeof(ans)) {
        if (timeout) {
            ret = acr120_timeout(fd, timeout);
            if (ret == ACR120_ERROR)
                return ret;
        }
        ret = read(fd, ans + bytes, sizeof(ans) - bytes);
        if (ret == -1) {
            acr120_errno = 6;
            return ACR120_ERROR;
        }
        bytes += ret;
        if (bytes > 3) {
            if (ans[3] == 'N') {
                acr120_errno = 9;
                return ACR120_ERROR;
            }
        }
    }


   if (uid){
memcpy(uids, ans + 3, sizeof(uids));
        nibble2dec(uid, uids);
}

    acr120_errno = 1;
    return ACR120_SUCCESS;
}

/*
 * key ff binary sequence: 02 01 04 6c 01 ff 0d 9a 03
 * key aa or bb binary sequence: 02 01 09 6c 01 aa a0 a1 a2 a3 a4 a5 ce 03
 */
int acr120_login(int fd, unsigned char sid, unsigned char sector,
                mifare_key type, unsigned char *key, int timeout)
{
    int ret, i;
    unsigned char cmd[14], ans[6];
    size_t bytes = 0, len;

printf("sector = %x\n",sector);
printf("key= %c\n",&key);
printf("keyType= %x\n",type);
    cmd[0] = STX;
    cmd[1] = sid;
    cmd[3] = 'l';
    cmd[4] = sector;

   if (type == MIFARE_KEY_FF) {
        cmd[2] = 0x04;
        cmd[5] = 0xff;
        cmd[6] = 0xd;
        for (i = 1, cmd[7] = 0; i < 7; i++)
            cmd[7] ^= cmd[i];
        len = 9;


    } else {
        cmd[2] = 9;
        cmd[5] = (type == MIFARE_KEY_AA) ? 0xaa : 0xbb;

        memcpy(cmd + 6, key, 6 * sizeof(unsigned char));
        for (i = 1, cmd[12] = 0; i < 12; i++)
            cmd[12] ^= cmd[i];
        len = 14;
    }

    cmd[len - 1] = ETX;

printf("%x %x %x %c %x %x %x %x %x %x %x %x %x %X\n",cmd[0],cmd[1],cmd[2],cmd[3],cmd[4],cmd[5],cmd[6],cmd[7],cmd[8],cmd[9],cmd[10],cmd[11],cmd[12],cmd[13]);
   
    ret = write(fd, cmd, len);

    if (ret == -1) {

        acr120_errno = 5;

        return ACR120_ERROR;
    }
    while (bytes < sizeof(ans)) {
        if (timeout) {
            ret = acr120_timeout(fd, timeout);
            if (ret == ACR120_ERROR)
                return ret;
        }
        ret = read(fd, ans + bytes, sizeof(ans) - bytes);
        if (ret == -1) {
            acr120_errno = 6;

            return ACR120_ERROR;
        }
printf("%c \n",ans[3]);

        bytes += ret;
        if (bytes > 3) {
            switch (ans[3]) {
                case 'L':
                    acr120_errno = 1;
printf("lOGIN = %s\n",acr120_strerror());
                    return ACR120_SUCCESS;
                case 'N':
                    acr120_errno = 9;


                    return ACR120_ERROR;
                case 'F':
                    acr120_errno = 11;

                    return ACR120_ERROR;
                case 'E':
                    acr120_errno = 12;

                    return ACR120_ERROR;
            }
        }
    }

    acr120_errno = 11;
    return ACR120_ERROR;
}

int acr120_write_block(int fd, unsigned char sid, unsigned char block,
                unsigned char *data, int timeout)
{
    int ret, i;
    unsigned char cmd[23], ans[21];
    size_t bytes = 0;

    cmd[0] = STX;
    cmd[1] = sid;
    cmd[2] = 18;
    cmd[3] = 'w';
    cmd[4] = block;
    memcpy(cmd + 5, data, 16);
    cmd[22] = ETX;

    for (i = 1, cmd[21] = 0; i < 21; i++)
        cmd[21] ^= cmd[i];

    ret = write(fd, cmd, sizeof(cmd));
    if (ret == -1) {
        acr120_errno = 5;
        return ACR120_ERROR;
    }

    while (bytes < sizeof(ans)) {
        if (timeout) {
            ret = acr120_timeout(fd, timeout);
            if (ret == ACR120_ERROR)
                return ret;
        }
        ret = read(fd, ans + bytes, sizeof(ans) - bytes);
        if (ret == -1) {
            acr120_errno = 6;
            return ACR120_ERROR;
        }
        bytes += ret;
        if (bytes > 3) {
            switch (ans[3]) {
                case 'X':
                    acr120_errno = 14;
                    return ACR120_ERROR;
                case 'U':
                    acr120_errno = 15;
                    return ACR120_ERROR;
                case 'N':
                    acr120_errno = 9;
                    return ACR120_ERROR;
                case 'F':
                case 'I':
                    acr120_errno = 16;
                    return ACR120_ERROR;
            }
        }
    }
    acr120_errno = 1;
    return ACR120_SUCCESS;
}

int acr120_write_value(int fd, unsigned char sid, unsigned char block,
                unsigned int value, int timeout)
{
    int ret, i;
    unsigned char cmd[12], data[4], ans[9];
    size_t bytes = 0;

printf("value write = %d \n",value);  

    dec2nibble(value, data);
    cmd[0] = STX;
    cmd[1] = sid;
    cmd[2] = 0x7;
    cmd[3] = 'w';
    cmd[4] = 'v';
    cmd[5] = block;
    cmd[6] = data[0];
    cmd[7] = data[1];
    cmd[8] = data[2];
    cmd[9] = data[3];
    cmd[11] = ETX;

printf("data = %x\n",data);
printf("data write = %x %x %x %x \n",data[0],data[1],data[2],data[3]);
   
printf("cmd_write = %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n",cmd[0],cmd[1],cmd[2],cmd[3],cmd[4],cmd[5],cmd[6],cmd[7],cmd[8],cmd[9],cmd[10],cmd[11],cmd[12],cmd[13]);
    for (i = 1, cmd[10] = 0; i < 10; i++)
        cmd[10] ^= cmd[i];

    ret = write(fd, cmd, sizeof(cmd));
    if (ret == -1) {
        acr120_errno = 5;
        return ACR120_ERROR;
    }
   
    while (bytes < sizeof(ans)) {
        if (timeout) {
            ret = acr120_timeout(fd, timeout);
            if (ret == ACR120_ERROR)
                return ret;
        }
        ret = read(fd, ans + bytes, sizeof(ans) - bytes);
        if (ret == -1) {
            acr120_errno = 6;
            return ACR120_ERROR;
        }
        bytes += ret;
        if (bytes > 3) {
            switch (ans[3]) {
                case 'X':
                   acr120_errno = 14;
                   return ACR120_ERROR;
                case 'U':
                    acr120_errno = 15;
                    return ACR120_ERROR;
                case 'N':
                    acr120_errno = 9;
printf("ASIK\n");
                    return ACR120_ERROR;
                case 'F':
                case 'I':
                    acr120_errno = 16;
                    return ACR120_ERROR;
            }
        }
    }
    acr120_errno = 1;
    return ACR120_SUCCESS;
}

int acr120_write_register(int fd, unsigned char sid, unsigned char reg,
                unsigned char value, int timeout)
{
    unsigned char cmd[9], ans[6], check = 0;
    size_t bytes = 0, nr, nw;
    int ret;

    if (acr120_proto_mode) {
        cmd[0] = STX;
        cmd[1] = sid;
        cmd[2] = 0x4;
        cmd[3] = 'w';
        cmd[4] = 'e';
        cmd[5] = reg;
        cmd[6] = value;
        cmd[7] = cmd[1] ^ cmd[2] ^ cmd[3] ^ cmd[4] ^ cmd[5] ^ cmd[6];
        cmd[8] = ETX;
        nw = sizeof(cmd);
        nr = sizeof(ans);
    } else {
        snprintf((char*) cmd, 7 * sizeof(unsigned char),
                 "we%.2x%.2x", reg, value);
        printf("cmd is: %s\n", (char*) cmd);
        nw = 6 * sizeof(unsigned char);
        nr = 4 * sizeof(unsigned char);
    }

    ret = write(fd, cmd, nw);

    if (ret == -1) {
        acr120_errno = 5;
        return ACR120_ERROR;
    }

    while (bytes < nr) {
        if (timeout) {
            ret = acr120_timeout(fd, timeout);
            if (ret == ACR120_ERROR)
                return ret;
        }

        ret = read(fd, ans + bytes, nr - bytes);
        if (ret == -1) {
            acr120_errno = 6;
            return ACR120_ERROR;
        }
       
        bytes += ret;
        if (acr120_proto_mode && bytes > 4 * sizeof(unsigned char) && !check) {
            switch (ans[3]) {
                case 'X':
                    acr120_errno = 14;

                    return ACR120_ERROR;
                case 'U':
                    acr120_errno = 15;

                    return ACR120_ERROR;
                case 'N':
                    acr120_errno = 9;

                    return ACR120_ERROR;
                case 'I':
                    acr120_errno = 16;

                    return ACR120_ERROR;
            }
            check ^= 1;
        }
    }

    if (acr120_proto_mode) {
        if (check_bin_error(ans, sizeof(ans))) {
            acr120_errno = 24;
            return ACR120_ERROR;
        }
    } else {
        if (check_ascii_error(ans, 4)) {
            acr120_errno = 24;
            return ACR120_ERROR;
        }
    }
    acr120_errno = 1;
    return ACR120_SUCCESS;
}

int acr120_read_block(int fd, unsigned char sid, unsigned char block,
                unsigned char *data, int timeout)
{
    int ret;
    unsigned char cmd[7], ans[21];
    size_t bytes = 0;

    cmd[0] = STX;
    cmd[1] = sid;
    cmd[2] = 2;
    cmd[3] = 'r';
    cmd[4] = block;
    cmd[5] = cmd[1] ^ cmd[2] ^ cmd[3] ^ cmd[4];
    cmd[6] = ETX;

    ret = write(fd, cmd, sizeof(cmd));
    if (ret == -1) {
        acr120_errno = 5;
        return ACR120_ERROR;
    }
    while (bytes < sizeof(ans)) {
        if (timeout) {
            ret = acr120_timeout(fd, timeout);
            if (ret == ACR120_ERROR )
                return ret;
        }
        ret = read(fd, ans + bytes, sizeof(ans) - bytes);
        if (ret == -1) {
            acr120_errno = 6;
            return ACR120_ERROR;
        }
        bytes += ret;
        if (bytes > 3) {
            switch (ans[3]) {
                case 'N':
                    acr120_errno = 9;
                    return ACR120_ERROR;
                case 'F':
                    acr120_errno = 13;
                    return ACR120_ERROR;
            }
        }
    }
    if (data)
        memcpy(data, ans + 3, 16);
    acr120_errno = 1;
    return ACR120_SUCCESS;
}

int acr120_read_value(int fd, unsigned char sid, unsigned char block,
                unsigned int *value, int timeout)
{
    int ret;
    unsigned char cmd[8], ans[9], data[4];
    size_t bytes = 0;
   
    cmd[0] = STX;
    cmd[1] = sid;
    cmd[2] = 0x3;
    cmd[3] = 'r';
    cmd[4] = 'v';
    cmd[5] = block;
    cmd[6] = cmd[1] ^ cmd[2] ^ cmd[3] ^ cmd[4] ^ cmd[5];

    cmd[7] = ETX;

printf("%x %x %x %c %c %x %x %x\n",cmd[0],cmd[1],cmd[2],cmd[3],cmd[4],cmd[5],cmd[6],cmd[7]);

    ret = write(fd, cmd, sizeof(cmd));
    if (ret == -1) {
        acr120_errno = 5;
        return ACR120_ERROR;
    }
   
    while (bytes < sizeof(ans)) {
        if (timeout) {
            ret = acr120_timeout(fd, timeout);
            if (ret == ACR120_ERROR)
                return ret;
        }
        ret = read(fd, ans + bytes, sizeof(ans) - bytes);

        if (ret == -1) {
            acr120_errno = 6;
            return ACR120_ERROR;
        }
        bytes += ret;

        if (bytes > 3) {
            switch (ans[3]) {
                case 'N':
                    acr120_errno = 9;
                    return ACR120_ERROR;
                case 'I':
                    acr120_errno = 10;
                    return ACR120_ERROR;
                case 'F':
                    acr120_errno = 13;
                    return ACR120_ERROR;
            }
        }
    }

printf("%i\n",ret);
printf("%c %c %c\n",ans[3],cmd[3],cmd[4]);
printf("%x %x %x %x %x %x %x %x %x %x\n",cmd[0],cmd[1],cmd[2],cmd[3],cmd[4],cmd[5],cmd[6],cmd[7],cmd[8],cmd[9]);
    if (value) {
        memcpy(data, ans + 3, sizeof(data));  
        nibble2dec(value, data);

    }
    acr120_errno = 1;
    return ACR120_SUCCESS;
}

int acr120_read_register(int fd, unsigned char sid, unsigned char reg,
                unsigned char *value, int timeout)
{
    int ret;
    unsigned char cmd[8], ans[6], check = 0;
    size_t bytes = 0, nw, nr;

    if (acr120_proto_mode) {
        cmd[0] = STX;
        cmd[1] = sid;
        cmd[2] = 0x3;
        cmd[3] = 'r';
        cmd[4] = 'e';
        cmd[5] = reg;
        cmd[6] = cmd[1] ^ cmd[2] ^ cmd[3] ^ cmd[4] ^ cmd[5];
        cmd[7] = ETX;
        nw = sizeof(cmd);
        nr = sizeof(ans);
    } else {
        snprintf((char *) cmd, 5 * sizeof(unsigned char), "re%.2x", reg);
        nw = 4 * sizeof(unsigned char);
        nr = 4 * sizeof(unsigned char);
    }

    ret = write(fd, cmd, nw);
    if (ret == -1) {
        acr120_errno = 5;
        return ACR120_ERROR;
    }

    while (bytes < nr) {
        if (timeout) {
            ret = acr120_timeout(fd, timeout);
            if (ret == ACR120_ERROR)
                return ret;
        }
        ret = read(fd, ans + bytes, nr - bytes);
        if (ret == -1) {
            acr120_errno = 6;
            return ACR120_ERROR;
        }
        bytes += ret;
        if (acr120_proto_mode && bytes > 4 && !check) {
            switch (ans[3]) {
                case 'N':
                    acr120_errno = 9;
                    return ACR120_ERROR;
                case 'I':
                    acr120_errno = 10;
                    return ACR120_ERROR;
                case 'F':
                    acr120_errno = 13;
                    return ACR120_ERROR;
            }
            check ^= 1;
        }
    }

    if (acr120_proto_mode) {
        if (check_bin_error(ans, sizeof(ans))) {
            acr120_errno = 24;
            return ACR120_ERROR;
        }
        *value = ans[3];
    } else {
        if (check_ascii_error(ans, 4)) {
            acr120_errno = 24;
            return ACR120_ERROR;
        }
        ans[2] = 0;
        sscanf((char*) ans, "%x", (unsigned int*) value);
    }
    acr120_errno = 1;
    return ACR120_SUCCESS;
}

int acr120_copy_block(int fd, unsigned char sid, unsigned char source,
                unsigned char dest, int timeout)
{
    int ret;
    unsigned char cmd[8], ans[9];
    size_t bytes = 0;

    cmd[0] = STX;
    cmd[1] = sid;
    cmd[2] = 0x3;
    cmd[3] = '=';
    cmd[4] = source;
    cmd[5] = dest;
    cmd[6] = cmd[1] ^ cmd[2] ^ cmd[3] ^ cmd[4] ^ cmd[5];
    cmd[7] = ETX;
   
    ret = write(fd, cmd, sizeof(cmd));
    if (ret == -1) {
        acr120_errno = 5;
        return ACR120_ERROR;
    }
    while (bytes < sizeof(ans)) {
        if (timeout) {
            ret = acr120_timeout(fd, timeout);
            if (ret == ACR120_ERROR)
                return ret;
        }
        ret = read(fd, ans + bytes, sizeof(ans) - bytes);
        if (ret == -1) {
            acr120_errno = 6;
            return ACR120_ERROR;
        }
        bytes += ret;
        if (bytes > 3) {
            switch (ans[3]) {
                case 'X':
                    acr120_errno = 22;
                    return ACR120_ERROR;
                case 'N':
                    acr120_errno = 9;
                    return ACR120_ERROR;
                case 'I':
                    acr120_errno = 10;
                    return ACR120_ERROR;
                case 'F':
                    acr120_errno = 23;
                    return ACR120_ERROR;
            }
        }
    }
    acr120_errno = 1;
    return ACR120_SUCCESS;
}

int acr120_inc_value(int fd, unsigned char sid, unsigned char block,
                unsigned int inc, int timeout)
{
    int ret, i;
    unsigned char cmd[11], ans[9], data[4];
    size_t bytes = 0;

    dec2nibble(inc, data);
    cmd[0] = STX;
    cmd[1] = sid;
    cmd[2] = 6;
    cmd[3] = '+';
    cmd[4] = block;
    cmd[5] = data[0];
    cmd[6] = data[1];
    cmd[7] = data[2];
    cmd[8] = data[3];
    cmd[10] = ETX;

    for (i = 1, cmd[9] = 0; i < 9; i++)
        cmd[9] ^= cmd[i];

    ret = write(fd, cmd, sizeof(cmd));
    if (ret == -1) {
        acr120_errno = 5;
        return ACR120_ERROR;
    }
    while (bytes < sizeof(ans)) {
        if (timeout) {
            ret = acr120_timeout(fd, timeout);
            if (ret == ACR120_ERROR)
                return ret;
        }
        ret = read(fd, ans + bytes, sizeof(ans) - bytes);
        if (ret == -1) {
            acr120_errno = 6;
            return ACR120_ERROR;
        }
        bytes += ret;
        if (bytes > 3) {
            switch (ans[3]) {
                case 'X':
                    acr120_errno = 17;
                    return ACR120_ERROR;
                case 'N':
                    acr120_errno = 9;
                    return ACR120_ERROR;
                case 'I':
                    acr120_errno = 10;
                    return ACR120_ERROR;
                case 'F':
                    acr120_errno = 18;
                    return ACR120_ERROR;
            }
        }
    }
    acr120_errno = 1;
    return ACR120_SUCCESS;
}

int acr120_dec_value(int fd, unsigned char sid, unsigned char block,
                unsigned int dec, int timeout)
{
    int ret, i;
    unsigned char cmd[11], ans[9], data[4];
    size_t bytes = 0;
   
    dec2nibble(dec, data);
    cmd[0] = STX;
    cmd[1] = sid;
    cmd[2] = 6;
    cmd[3] = '-';
    cmd[4] = block;
    cmd[5] = data[0];
    cmd[6] = data[1];
    cmd[7] = data[2];
    cmd[8] = data[3];
    cmd[10] = ETX;
   
    for (i = 1, cmd[9] = 0; i < 9; i++)
        cmd[9] ^= cmd[i];

    ret = write(fd, cmd, sizeof(cmd));
    if (ret == -1) {
        acr120_errno = 5;
        return ACR120_ERROR;
    }
    while (bytes < sizeof(ans)) {
        if (timeout) {
            ret = acr120_timeout(fd, timeout);
            if (ret == ACR120_ERROR)
                return ret;
        }
        ret = read(fd, ans + bytes, sizeof(ans) - bytes);
        if (ret == -1) {
            acr120_errno = 6;
            return ACR120_ERROR;
        }
        bytes += ret;
        if (bytes > 3) {
            switch(ans[3]) {
                case 'X':
                    acr120_errno = 19;
                    return ACR120_ERROR;
                case 'N':
                    acr120_errno = 9;
                    return ACR120_ERROR;
                case 'I':
                    acr120_errno = 10;
                    return ACR120_ERROR;
                case 'F':
                case 'E':
                    acr120_errno = 20;
                    return ACR120_ERROR;
            }
        }
    }
    acr120_errno = 1;
    return ACR120_SUCCESS;
}

int acr120_power_on(int fd, unsigned char sid, int timeout)
{
    int ret;
    unsigned char cmd[8], ans[6];
    size_t bytes = 0;

    cmd[0] = STX;
    cmd[1] = sid;
    cmd[2] = 3;
    cmd[3] = 'p';
    cmd[4] = 'o';
    cmd[5] = 'n';
    cmd[6] = cmd[1] ^ cmd[2] ^ cmd[3] ^ cmd[4] ^ cmd[5];
    cmd[7] = ETX;
   
    ret = write(fd, cmd, sizeof(cmd));
    if (ret == ACR120_ERROR) {
        acr120_errno = 5;
        return ret;
    }

    /*
     * actually no error condition answer here, but the
     * reader will send 6 bytes of characters reply, so we
     * only receive the buffer to make sure it is empty
     */
    while (bytes < sizeof(ans)) {
        if (timeout) {
            ret = acr120_timeout(fd, timeout);
            if (ret == ACR120_ERROR)
                return ret;
        }
        ret = read(fd, cmd + bytes, sizeof(cmd) - bytes);
        if (ret == -1) {
            acr120_errno = 6;
            return ACR120_ERROR;
        }
        bytes += ret;
    }
    acr120_errno = 1;
    return ACR120_SUCCESS;
}

int acr120_power_off(int fd, unsigned char sid, int timeout)
{
    int ret;
    unsigned char cmd[9], ans[6];
    size_t bytes = 0;

    cmd[0] = STX;
    cmd[1] = sid;
    cmd[2] = 4;
    cmd[3] = 'p';
    cmd[4] = 'o';
    cmd[5] = 'f';
    cmd[6] = 'f';
    cmd[7] = cmd[1] ^ cmd[2] ^ cmd[3] ^ cmd[4] ^ cmd[5] ^ cmd[6];
    cmd[8] = ETX;

    ret = write(fd, cmd, sizeof(cmd));
    if (ret == ACR120_ERROR) {
        acr120_errno = 5;
        return ret;
    }
    while (bytes < sizeof(ans)) {
        if (timeout) {
            ret = acr120_timeout(fd, timeout);
            if (ret == ACR120_ERROR)
                return ret;
        }
        ret = read(fd, cmd + bytes, sizeof(cmd) - bytes);
        if (ret == -1) {
            acr120_errno = 6;
            return ACR120_ERROR;
        }
        bytes += ret;
    }
    acr120_errno = 1;
    return ACR120_SUCCESS;
}

Tidak ada komentar:

Posting Komentar