我大學時代的專題老師,今年叫學弟們做 ARM Linux + RFID 相關的專題,主要是用來管理冰箱裡面的東西的保存期限的。
可是呢,這群學弟...
「ARM 是什麼?可以吃嗎?」
「Linux 我們不太會耶!」
「RFID Reader 只有 Windows driver (還是 VB.Net 寫的) 耶,可以拿去 Linux 上編嗎?」
所以,不知道他們從哪裡找到我,突然來問我要怎麼辦。
我想說,既然是以前的專題老師,要是這組學弟做不出來或做的不好,他也很丟臉... 而且順便也想看看 RFID 在 Linux 上到底會不會動,所以就決定下去台中一趟幫他們看看。
不看還好,一看之下才發現,他們使用的 ARM 是 s3c2410 配上一套有夠舊的 Linux(kernel 是 2.4.x......),可是使用的 SUMMIT U-Reader 在我的機器上倒是抓的到也有 driver,只是沒有 user-space tool 去 access 它而已。所以我乾脆就叫他們說,先在 PC Linux 上做,然後把移植到 arm 上當成一個「願景」。盡量使用嵌入式系統上容易找到的軟體(如 boa),如果真的要移植的話也比較方便。
SUMMIT U-Reader 其實是一個 pc210x 的 USB-to-RS232 晶片,加上他們自己家的 HF 讀卡模組(使用 RS232 介面,Windows 的 VB.Net 程式也是使用 Serial subsystem 去 access)。既然如此,事情就簡單啦!我只要弄個 serial 程式去操作它就可以了!
我目前幫他們寫到可以抓到卡號,讀取以及寫入 RFID Block 就要靠他們自己了。以下是 example code(BSD License!):
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <iostream>
#define TTYDEVICE "/dev/ttyUSB0"
#define BAUD B19200
int open_port(void)
{
int fd = open(TTYDEVICE, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1)
{
perror("open_port: Unable to open " TTYDEVICE);
return fd;
}
fcntl(fd, F_SETFL, 0);
// port settings
struct termios options;
tcgetattr(fd, &options);
cfsetispeed(&options, BAUD);
cfsetospeed(&options, BAUD);
options.c_cflag |= (CLOCAL | CREAD);
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
options.c_oflag &= ~OPOST;
options.c_iflag |= (INPCK | ISTRIP) & ~(IXON | IXOFF | IXANY);
options.c_cc[VMIN] = 0;
options.c_cc[VTIME] = 10;
tcsetattr(fd, TCSANOW, &options);
// clear I/O buffer
tcflush(fd, TCIOFLUSH);
return fd;
}
int main()
{
// get the file descriptor from open_port()
int fd = open_port();
// I/O buffer, let it be the 'I' command initially
char buf[256] = { 0x1b, 'I', '\r', 0 };
int n;
// write() the 'I' command
if ((n = write(fd, buf, 3)) < 3)
std::cerr << "write() of 3 bytes failed!\n";
else
{
std::cout << "write() " << n << " bytes: ";
for (int i = 0;i < n;++i)
{
std::cout << "0x";
std::cout.width(2);
std::cout.fill('0');
std::cout << std::hex << static_cast<int>(buf[i]) << ' ';
}
std::cout << std::endl;
}
// read the result
n = read(fd, buf, 255);
if (n < 0)
fputs("read() failed!\n", stderr);
else
{
std::cout << "read() " << n << " bytes: ";
for (int i = 0;i < n;++i)
{
std::cout << "0x";
std::cout.width(2);
std::cout.fill('0');
std::cout << std::hex << static_cast<int>(buf[i]) << ' ';
}
std::cout << std::endl;
}
close(fd);
return 0;
}