星期一, 8月 31, 2009

救災順利!成功救活四名專題做不出來的學弟!

我大學時代的專題老師,今年叫學弟們做 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;
}