/*
  デバイス接続のインターフェース
  Satofumi KAMIMURA
  $Id: connectionDevice.cpp 286 2008-10-20 09:40:22Z satofumi $
*/

#include "connectionDevice.h"


ConnectionDevice::ConnectionDevice(int buffer_size)
  : device_name(""), baudrate_value(0),
    recv_buffer(new RingBuffer<char>(buffer_size)) {
}


ConnectionDevice::~ConnectionDevice(void) {
  delete recv_buffer;
}


int ConnectionDevice::connect(const char* device, long baudrate) {
  device_name = device;
  baudrate_value = baudrate;

  if (isConnected()) {
    disconnect();
  }
  int ret_value = raw_connect(device, baudrate);
  if (ret_value < 0) {
    return ret_value;
  }
  ret_value = raw_setBaudrate(baudrate);
  flush();

  return ret_value;
}


void ConnectionDevice::disconnect(void) {
  if (isConnected()) {
    raw_disconnect();
  }
}


int ConnectionDevice::setBaudrate(long baudrate) {
  if (isConnected()) {
    return raw_setBaudrate(baudrate);
  }
  return NotConnected;
}


void ConnectionDevice::flush(void) {
  if (isConnected()) {
    raw_flush();
  }
  recv_buffer->clear();
}


void ConnectionDevice::check(int size, long timeout) {
  if (!isConnected()) {
    return;
  }

  int free_size = recv_buffer->free_size();
  int require_size = (size < 0) ? free_size : size;
  if (require_size > BufferSize) {
    require_size = BufferSize;
  }
  int filled = recv_buffer->size();
  int maxlen = require_size - filled;
  if (maxlen <= 0) {
    maxlen = (free_size < BufferSize) ? free_size : BufferSize;
    timeout = 0;
  }
  raw_check(maxlen, timeout);
}


int ConnectionDevice::send(const char* data, int len) {
  check(0);
  return (!isConnected()) ? NotConnected : raw_send(data, len);
}


int ConnectionDevice::recv(char* data, int maxlen, long timeout) {
  check(maxlen, timeout);
  if (!isConnected()) {
    return NotConnected;
  }

  int len = (static_cast<int>(recv_buffer->size()) >= maxlen)
    ? maxlen : static_cast<int>(recv_buffer->size());
  if (len == 0) {
    return 0;
  }
  recv_buffer->get(static_cast<char*>(data), len);

  return len;
}


int ConnectionDevice::copy(char *data, int maxlen) {
  return recv_buffer->copy(data, maxlen);
}


int ConnectionDevice::size(void) {
  check(0);
  return recv_buffer->size();
}


int ConnectionDevice::capacity(void) {
  check(0);
  return recv_buffer->free_size();
}


const char* ConnectionDevice::getDevice(void) {
  return device_name.c_str();
}


long ConnectionDevice::getBaudrate(void) {
  return baudrate_value;
}
