パラレルポート入出力クラス

C++を使いたかったのでIOクラスを書いてみた。まだ途中。
かなり適当だけど、前から使ってみたかったproxyクラスを実践できたので良しとしよう。

#ifndef MAD_PARPORTIO_HPP_
#define MAD_PARPORTIO_HPP_

#include <string>
#include <stdexcept>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/ppdev.h>
#include <linux/parport.h>

namespace mad {

  class parportio
  {
  public:
    class pin_proxy
    {
    public:
      pin_proxy(parportio& ppio, size_t pin) :ppio_(ppio), pin_(pin) {}

      pin_proxy& operator=(const pin_proxy& other){
        ppio_ = other.ppio_;
        pin_ = other.pin_;
        return *this;
      }

      pin_proxy& operator=(bool on){
        char data;
        if(ioctl(ppio_.device_, PPRDATA, &data) == -1){
          throw std::runtime_error("Read error");
        }

        if(on){
          data |= (1 << pin_);
        }else{
          data &= ~(1 << pin_);
        }

        if(ioctl(ppio_.device_, PPWDATA, &data) == -1){
          throw std::runtime_error("Write error");
        }
        return *this;
      }

      operator bool() const {
        char data;
        if(ioctl(ppio_.device_, PPRDATA, &data) == -1){
          throw std::runtime_error("Read error");
        }
        return data & (1 << pin_);
      }
    private:
      parportio& ppio_;
      size_t pin_;
    }; // class pin_proxy

    parportio(const std::string& device)
      :device_(open(device.c_str(), O_RDWR))
    {
      if(device_ == -1){
        throw std::runtime_error("Open error");
      }
      if(ioctl(device_, PPCLAIM)){
        throw std::runtime_error("Claim error");
      }
    }

    ~parportio(){
      if(ioctl(device_, PPRELEASE) == -1){
        throw std::runtime_error("Release error");
      }
      close(device_);
    }

    const pin_proxy operator[](size_t pin) const {
      if(pin >= 8) throw std::out_of_range("");
      return pin_proxy(const_cast<parportio&>(*this), pin);
    }
    pin_proxy operator[](size_t pin){
      if(pin >= 8) throw std::out_of_range("");
      return pin_proxy(*this, pin);
    }

    friend class pin_proxy;
  private:
    int device_;
  }; // class parportio

} // namespace mad

#endif // MAD_PARPORTIO_HPP_

昨晩のエントリのコードは次みたいに書ける。

#include "parportio.hpp"
#include <unistd.h>

int main(void){
  mad::parportio parport("/dev/parport0");

  while(1){
    //ピン3からピン7を順番に点灯
    for(int i = 3; i < 8; ++i){
      parport[i] = 1;
      usleep(100000);
      parport[i] = 0;
    }
  }
  return 0;
}

大分楽になった。

追記

今気づいたけど、pin_proxyの代入演算子を間違えてたので直した。