int open_comm (const char* device) { if (device == NULL) return -1; int fd = open (device, O_RDWR|O_NOCTTY|O_NDELAY); return fd; }
static int speed_arr[] = {B115200, B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400, B19200, B9600, B4800, B2400, B1200, B300, }; static int name_arr[] = { 115200, 38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200, 9600, 4800, 2400, 1200, 300, }; int set_options (int fd, int speed, int databits, int stopbits, int parity) { struct termios options; int status = 0; if ((status = tcgetattr (fd, &options)) != 0) { ERROR ("fail: status=%d, %s", status, strerror (errno)); return -1; } int bSpeed = -1; for (int i = 0; i < sizeof(speed_arr) / sizeof(int); i++) { if (speed == name_arr[i]) { bSpeed = speed_arr[i]; break; } } if (bSpeed == -1) { ERROR ("wrong speed=%d", speed); return -1; } cfsetispeed (&options, bSpeed); cfsetospeed (&options, bSpeed); /*允许接收并且设置为本地模式*/ options.c_cflag |= (CLOCAL|CREAD); /*设置数据位数*/ options.c_cflag &= ~CSIZE; switch (databits) { case 7: options.c_cflag |= CS7; break; case 8: options.c_cflag |= CS8; break; default: ERROR ("Unsupported data size"); return -1; } switch (parity) { case 'n': case 'N': options.c_cflag &= ~PARENB; /* Clear parity enable */ options.c_iflag &= ~INPCK; /* Enable parity checking */ break; case 'o': case 'O': options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/ options.c_iflag |= INPCK; /* Disnable parity checking */ break; case 'e': case 'E': options.c_cflag |= PARENB; /* Enable parity */ options.c_cflag &= ~PARODD; /* 转换为偶效验*/ options.c_iflag |= INPCK; /* Disnable parity checking */ break; case 'S': case 's': /*as no parity*/ options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; break; default: ERROR ("Unsupported parity"); return -1; } /* 设置停止位*/ switch (stopbits) { case 1: options.c_cflag &= ~CSTOPB; break; case 2: options.c_cflag |= CSTOPB; break; default: ERROR ("Unsupported stop bits"); return -1; } /* Set input parity option */ //if (parity != 'n') // options.c_iflag |= INPCK; options.c_cc[VINTR] = 0; options.c_cc[VQUIT] = 0; options.c_cc[VERASE] = 0; options.c_cc[VKILL] = 0; options.c_cc[VEOF] = 0; options.c_cc[VTIME] = 1; options.c_cc[VMIN] = 0; options.c_cc[VSWTC] = 0; options.c_cc[VSTART] = 0; options.c_cc[VSTOP] = 0; options.c_cc[VSUSP] = 0; options.c_cc[VEOL] = 0; options.c_cc[VREPRINT] = 0; options.c_cc[VDISCARD] = 0; options.c_cc[VWERASE] = 0; options.c_cc[VLNEXT] = 0; options.c_cc[VEOL2] = 0; //options.c_cc[VTIME] = 150; // 15 seconds //options.c_cc[VMIN] = 0; tcflush (fd,TCIFLUSH); /* Update the options and do it NOW */ if ((status = tcsetattr (fd,TCSANOW,&options)) != 0) { ERROR ("fail: status=%d, %s", status, strerror (errno)); return -1; } return 0; }
static int cmd_read_timeout (int fd, unsigned char* buf, int msec) { if (fd < 0 || buf == NULL) { ERROR ("fd = %d, buf=%p", fd, buf); return -1; } int maxfd = fd; fd_set fdread; FD_ZERO (&fdread); FD_SET (fd, &fdread); /* set a suitable timeout to play around with */ struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = msec*1000; int nread = 0; int rc = select (maxfd+1, &fdread, NULL, NULL, &timeout); switch (rc) { case -1: ERROR ("error: %s", strerror (errno)); /* select error */ nread = -1; break; case 0: //DEBUG ("timeout!"); nread = -1; break; default: { /* readable sockets */ if (FD_ISSET (fd, &fdread)) { nread = read (fd, buf, 512); //DEBUG ("read(%d):%s\n", nread, buf); if ((buf[1] + 2) == nread) { // checksum unsigned char checksum = 0; for (int i = 0; i < nread; i++) { checksum = checksum^buf[i]; } if (checksum == 0) { // get right command. } else { nread = 0; } } else { // ERROR cmd lenght; DEBUG ("cmd length not right! got data len=%d, require=%d", nread, buf[1]+2); nread = 0; } } else { ERROR ("fd not set! maybe error!"); nread = -1; } break; } } return nread; }
//============================================ // Command List, preamble + length + command //============================================ static const unsigned char SelectCard[]= {0xBA,0x02,0x01 }; static const unsigned char LoginSector0[]= {0xBA,0x0A,0x02,0x00,0xAA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; static const unsigned char LoginSector1[]= {0xBA,0x0A,0x02,0x01,0xAA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; static const unsigned char ReadBlock1[]= {0xBA,0x03,0x03,0x01}; static const unsigned char WriteBlock1[]= {0xBA,0x13,0x04,0x01,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF}; static const unsigned char ReadValue[]= {0xBA,0x03,0x05,0x05}; static const unsigned char InitializeValue[]= {0xBA,0x07,0x06,0x04,0x00,0x00,0x00,0x01}; static const unsigned char IncrementValue[]= {0xBA,0x07,0x08,0x04,0x00,0x00,0x00,0x20}; static const unsigned char DecrementValue[]= {0xBA,0x07,0x09,0x04,0x03,0x00,0x00,0x00}; static const unsigned char CopyValue[]= {0xBA,0x04,0x0A,0x04,0x05}; static const unsigned char ReadULPage5[]= {0xBA,0x03,0x10,0x05}; static const unsigned char WriteULPage5[]= {0xBA,0x07,0x11,0x05,0x11,0x22,0x33,0x44}; static const unsigned char TurnOnRedLed[]= {0xBA,0x03,0x40,0x01}; static const unsigned char TurnOffRedLed[]= {0xBA,0x03,0x40,0x00}; static int wrap_data (unsigned char* dest, const unsigned char* src, int len) { if (dest == NULL || src == NULL || len == 0) return -1; memcpy (dest, src, len); unsigned char checksum = 0; for (int i = 0; i < len; i++) { checksum = checksum ^ src[i]; } dest[len] = checksum; return 0; } int clear_comm (int fd) { tcflush(fd,TCIFLUSH); return 0; } int read_card_id_name (int fd, unsigned char* id, unsigned char* name) { if (id == NULL || name == NULL) return -1; unsigned char data_send[512] = {0}; unsigned char data_recv[512] = {0}; int nWrite = 0; int nRead = 0; tcflush(fd,TCIFLUSH); wrap_data (data_send, SelectCard, sizeof (SelectCard)); nWrite = write (fd, data_send, sizeof (SelectCard) + 1); if ((nRead = cmd_read_timeout (fd, data_recv, 300)) <= 0) { return -1; } //DEBUG ("(%d) %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", nRead, data_recv[0], data_recv[1], data_recv[2], data_recv[3], data_recv[4], data_recv[5], data_recv[6], data_recv[7], data_recv[8], data_recv[9]); if ((data_recv[2] != 0x01) || (data_recv[3] != 0)) { return -1; } int retcode = 0; unsigned char card_type = data_recv[data_recv[1]]; switch (card_type) { case 1: case 4: memcpy (id, &data_recv[4], 4); #if 1 // verify password of sector0 wrap_data (data_send, LoginSector0, sizeof (LoginSector0)); nWrite = write (fd, data_send, sizeof (LoginSector0) + 1); if ((nRead = cmd_read_timeout (fd, data_recv, 300)) <= 0) { return -1; } if ((data_recv[2] != 0x02) || (data_recv[3] != 0x02)) { return -1; } // read data from block1 wrap_data (data_send, ReadBlock1, sizeof (ReadBlock1)); nWrite = write (fd, data_send, sizeof (ReadBlock1) + 1); if ((nRead = cmd_read_timeout (fd, data_recv, 300)) <= 0) { return -1; } if ((data_recv[2] != 0x03) || (data_recv[3] != 0)) { return -1; } memcpy (name, &data_recv[4], 16); #endif retcode = 0; break; case 3: memcpy (id, &data_recv[4], 7); retcode = -1; break; case 2: case 5: case 6: default: retcode = -1; break; } if (retcode != 0) { return retcode; } // Glare Red Led to indicate working ok wrap_data (data_send, TurnOnRedLed, sizeof (TurnOnRedLed)); nWrite = write (fd, data_send, sizeof (TurnOnRedLed) + 1); nRead = cmd_read_timeout (fd, data_recv, 300); usleep (200*1000); wrap_data (data_send, TurnOffRedLed, sizeof (TurnOffRedLed)); nWrite = write (fd, data_send, sizeof (TurnOffRedLed) + 1); nRead = cmd_read_timeout (fd, data_recv, 300); return 0; }
5,闪烁红灯,提示操作成功。
int GlareLed (int fd) { int retcode = 0; unsigned char data_send[512] = {0}; unsigned char data_recv[512] = {0}; int nWrite = 0; int nRead = 0; // Glare Red Led to indicate working ok wrap_data (data_send, TurnOnRedLed, sizeof (TurnOnRedLed)); nWrite = write (fd, data_send, sizeof (TurnOnRedLed) + 1); nRead = cmd_read_timeout (fd, data_recv, 300); DEBUG ("get %d bytes", nRead); usleep (200*1000); wrap_data (data_send, TurnOffRedLed, sizeof (TurnOffRedLed)); nWrite = write (fd, data_send, sizeof (TurnOffRedLed) + 1); nRead = cmd_read_timeout (fd, data_recv, 300); DEBUG ("get %d bytes", nRead); return 0; }
6,主函数
int main(int argc, char **argv) { const char *dev ="/dev/ttyUSB0"; if (argc > 1) dev = argv[1]; int fd = open (dev, O_RDWR|O_NOCTTY|O_NDELAY); //| O_NOCTTY | O_NDELAY if (fd < 0) { ERROR ("Can't Open Serial Port"); return -1; } if (set_options (fd, B115200, 8, 1, 'N') != 0) { ERROR ("Set Parity Error"); close (fd); return -1; } while (1) { unsigned char id[10]; unsigned char name[20]; int ret = read_card_id_name (fd, id, name); if (ret == 0) { printf ("%02x%02x%02x%02x\n ", id[0], id[1], id[2], id[3]); } //GlareLed (fd); //DEBUG (""); //string content = getdata (fd); //printf ("%s", content.c_str ()); //write(fd, "AT1", 3); usleep (300*1000); } close(fd); return 0; }
options.c_cc[VINTR] = 0; options.c_cc[VQUIT] = 0; options.c_cc[VERASE] = 0; options.c_cc[VKILL] = 0; options.c_cc[VEOF] = 0; options.c_cc[VTIME] = 1; options.c_cc[VMIN] = 0; options.c_cc[VSWTC] = 0; options.c_cc[VSTART] = 0; options.c_cc[VSTOP] = 0; options.c_cc[VSUSP] = 0; options.c_cc[VEOL] = 0; options.c_cc[VREPRINT] = 0; options.c_cc[VDISCARD] = 0; options.c_cc[VWERASE] = 0; options.c_cc[VLNEXT] = 0; options.c_cc[VEOL2] = 0;
8,有问题可以联系 [email protected]