#include #include #include #include #include #include #include #include #include #include #include #include #include #define MODEMDEVICE "/dev/ttyUSB0" /* デフォルトのデバイスファイルの指定 */ class FTDI_PORT { protected: int fd; const char *port_name; struct termios oldtio; public: FTDI_PORT(const char *name, int timeout = 0, int blocklen = 0) throw(std::runtime_error) : port_name(name), fd(-1) { /* ポートオープン */ if((fd = open(port_name, O_RDWR | O_NOCTTY)) == -1){ /* O_RDWR:読み書き両用 O_NOCTTY:tty制御をしない */ perror(port_name); throw std::runtime_error("port not fount..."); } /* 現在のシリアルポートの設定を退避 * 新しいポートの設定の構造体をクリア */ tcgetattr(fd, &oldtio); struct termios newtio; bzero(&newtio, sizeof(newtio)); /* CRTSCTS:フロー制御有り * CS8:8ビット、ノンパリティ、ストップビット1 * CLOCAL:モデムの状態信号を無視 CREAD:受信可能にする */ newtio.c_cflag = (B115200 | CS8 | CLOCAL | CREAD); newtio.c_iflag = IGNPAR; ///< IGNPAR:パリティエラーの文字は無視 newtio.c_oflag = 0; ///< rawモード newtio.c_lflag = 0; ///< 非カノニカル入力 newtio.c_cc[VTIME] = timeout; ///< キャラクタ間タイマ newtio.c_cc[VMIN] = blocklen; ///< n文字受け取るまでブロックする /* ポートのクリアと設定を有効にする */ tcflush(fd,TCIFLUSH); tcsetattr(fd, TCSANOW, &newtio); } ~FTDI_PORT(){ if(fd != -1){ /* 退避させた設定に戻す */ tcsetattr(fd, TCSANOW, &oldtio); /* シリアルポートを閉じる */ close(fd); } } ssize_t push(const char *str, const size_t count) { return write(fd, str, count); } ssize_t pull(char *buf, const size_t count) { return read(fd, buf, count); } int flush(){ return tcflush(fd, TCIFLUSH); } }; class Base16{ public: static std::string encode(const std::string &src){ std::stringstream ss; ss << std::hex << std::setfill('0') << std::setw(2); for(std::string::const_iterator it(src.begin()); it != src.end(); ++it){ ss << (unsigned int)(*it); } return ss.str(); } static std::string decode(const std::string &src){ char buf[2]; std::stringstream ss; for(std::string::const_iterator it(src.begin()); it != src.end(); ++it){ if(std::distance(src.begin(), it) % 2 == 0){ buf[0] = *it; }else{ buf[1] = *it; int i; std::stringstream(std::string(buf, 2)) >> std::hex >> i; ss << (unsigned char)i; } } return ss.str(); } }; using namespace std; int main(int argc, const char *argv[]){ cout << "Content-Type: text/plain" << endl << endl; const char *env_s; string s; if(env_s = getenv("QUERY_STRING")){ s.append(env_s); }else if(env_s = getenv("CONTENT_LENGTH")){ int len(atoi(env_s)); //cerr << len << endl; char *buf(new char[len]); cin.read(buf, len); s.append(buf, len); delete [] buf; }else{ cout << "This program works only in the cgi mode." << endl; exit(-1); } size_t index(0), next_index(0); map key_values; while(((next_index = s.find("&", index)) != string::npos) || ((next_index = s.size()) > index)){ string s2(s.substr(index, next_index - index)); size_t key_index(s2.find("=")); if(key_index != string::npos){ key_values[s2.substr(0, key_index)] = s2.substr(key_index + 1); }else{ key_values[s2.substr(0, key_index)] = ""; } index = next_index + 1; } /*for(map::iterator it(key_values.begin()); it != key_values.end(); ++it){ cerr << it->first << ", " << it->second << endl; }*/ try{ int timeout(0); if(key_values.find("to") != key_values.end()){ timeout = atoi(key_values["to"].c_str()); } int blocklen(0); if(key_values.find("bl") != key_values.end()){ blocklen = atoi(key_values["bl"].c_str()); } FTDI_PORT port(MODEMDEVICE, timeout, blocklen); if(key_values.find("push") != key_values.end()){ string spec(Base16::decode(key_values["push"])); port.push(spec.c_str(), spec.size()); } if(key_values.find("pull") != key_values.end()){ int expected_pull(atoi(key_values["pull"].c_str())); char *buf(new char [expected_pull + 1]); ssize_t res = port.pull(buf, expected_pull); cout << Base16::encode(string(buf, res)); delete [] buf; } }catch(runtime_error re){ cout << re.what() << endl; } return 0; }