Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "TUSBScannerIO.h"
Toshihiro Shimizu 890ddd
#include "tsystem.h"
Toshihiro Shimizu 890ddd
#include <iostream></iostream>
Shinya Kitaoka 9eb50d
#include <strstream></strstream>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//#define HAS_LIBUSB
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if defined(HAS_LIBUSB)
Toshihiro Shimizu 890ddd
#include <usb.h></usb.h>
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <errno.h></errno.h>
Toshihiro Shimizu 890ddd
using namespace std;
Shinya Kitaoka 120a6e
class TUSBScannerIOPD {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  TUSBScannerIOPD();
Shinya Kitaoka 120a6e
  struct usb_device *m_epson;
Shinya Kitaoka 120a6e
  struct usb_dev_handle *m_handle;
Shinya Kitaoka 120a6e
  int m_epR;
Shinya Kitaoka 120a6e
  int m_epW;
Shinya Kitaoka 120a6e
  bool m_trace;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static pthread_t T = 0;
Toshihiro Shimizu 890ddd
//#define TRACE cout << __PRETTY_FUNCTION__ << endl;
Toshihiro Shimizu 890ddd
#define TRACE
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TUSBScannerIOPD::TUSBScannerIOPD()
Shinya Kitaoka 120a6e
    : m_epson(0), m_handle(0), m_epR(0), m_epW(0), m_trace(false) {
Shinya Kitaoka 120a6e
  /*initialize libusb*/
Shinya Kitaoka 120a6e
  TRACE
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (T == 0) T = pthread_self();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if defined(HAS_LIBUSB)
Shinya Kitaoka 120a6e
  usb_set_debug(9);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  usb_init();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  usb_find_busses();
Shinya Kitaoka 120a6e
  usb_find_devices();
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Shinya Kitaoka 120a6e
void buf2printable(const unsigned char *buffer, const int size,
Shinya Kitaoka 120a6e
                   ostrstream &os) {
Shinya Kitaoka 120a6e
  int i = 0;
Shinya Kitaoka 120a6e
  if ((size == 2) && (buffer[0] == 0x1b)) {
Shinya Kitaoka 120a6e
    os << "ESC ";
Shinya Kitaoka 120a6e
    char c = buffer[1];
Shinya Kitaoka 120a6e
    if (isprint(c)) os << c << " ";
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  os << std::hex;
Shinya Kitaoka 120a6e
  for (; i < std::min(size, 0x40); ++i) {
Shinya Kitaoka 120a6e
    char c = buffer[i];
Shinya Kitaoka 120a6e
    os << "0x" << (unsigned int)c << " ";
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (i < size) os << "...";
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TUSBScannerIO::TUSBScannerIO() : m_data(new TUSBScannerIOPD()) { TRACE }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if defined(HAS_LIBUSB)
Shinya Kitaoka 120a6e
// looking for an Epson device
Shinya Kitaoka 120a6e
struct usb_device *doCheck(struct usb_device *dev, int level) {
Shinya Kitaoka 120a6e
  if (!dev) return 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  cout << "checking idVendor = " << std::hex << dev->descriptor.idVendor
Shinya Kitaoka 120a6e
       << endl;
Shinya Kitaoka 120a6e
  if (dev->descriptor.idVendor == 0x04b8) return dev;
Shinya Kitaoka 120a6e
  for (int i = 0; i < dev->num_children; i++)
Shinya Kitaoka 120a6e
    if (doCheck(dev->children[i], level + 1)) return dev->children[i];
Shinya Kitaoka 120a6e
  return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TUSBScannerIO::open() {
Toshihiro Shimizu 890ddd
#if defined(HAS_LIBUSB)
Shinya Kitaoka 120a6e
  for (struct usb_bus *bus = usb_busses; bus; bus = bus->next) {
Shinya Kitaoka 120a6e
    if (bus->root_dev) {
Shinya Kitaoka 120a6e
      m_data->m_epson = doCheck(bus->root_dev, 0);
Shinya Kitaoka 120a6e
      if (m_data->m_epson) break;
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      struct usb_device *dev;
Shinya Kitaoka 120a6e
      for (dev = bus->devices; dev; dev = dev->next)
Shinya Kitaoka 120a6e
        m_data->m_epson = doCheck(dev, 0);
Shinya Kitaoka 120a6e
      if (m_data->m_epson) break;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (!m_data->m_epson) return false;
Shinya Kitaoka 120a6e
  cout << "found" << endl;
Shinya Kitaoka 120a6e
  m_data->m_handle = usb_open(m_data->m_epson);
Shinya Kitaoka 120a6e
  if (!m_data->m_handle) return false;
Shinya Kitaoka 120a6e
  cout << "opened" << endl;
Shinya Kitaoka 120a6e
  m_data->m_epR = m_data->m_epson->config[0]
Shinya Kitaoka 120a6e
                      .interface[0]
Shinya Kitaoka 120a6e
                      .altsetting[0]
Shinya Kitaoka 120a6e
                      .endpoint[0]
Shinya Kitaoka 120a6e
                      .bEndpointAddress;
Shinya Kitaoka 120a6e
  m_data->m_epW = m_data->m_epson->config[0]
Shinya Kitaoka 120a6e
                      .interface[0]
Shinya Kitaoka 120a6e
                      .altsetting[0]
Shinya Kitaoka 120a6e
                      .endpoint[1]
Shinya Kitaoka 120a6e
                      .bEndpointAddress;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int rc;
Shinya Kitaoka 120a6e
  rc = usb_set_configuration(m_data->m_handle,
Shinya Kitaoka 120a6e
                             m_data->m_epson->config[0].bConfigurationValue);
Shinya Kitaoka 120a6e
  cout << "rc (config) = " << rc << endl;
Shinya Kitaoka 120a6e
  int ifc = 0;
Shinya Kitaoka 120a6e
  rc      = usb_claim_interface(m_data->m_handle, ifc);
Shinya Kitaoka 120a6e
  if ((rc == -EBUSY) || (rc == -ENOMEM)) return false;
Shinya Kitaoka 120a6e
  cout << "rc (claim) = " << rc << endl;
Shinya Kitaoka 120a6e
  cout << "gotit!" << endl;
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
  return false;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TUSBScannerIO::close() {
Shinya Kitaoka 120a6e
  TRACE
Toshihiro Shimizu 890ddd
#if defined(HAS_LIBUSB)
Shinya Kitaoka 120a6e
  if (m_data->m_handle) {
Shinya Kitaoka 120a6e
    usb_release_interface(m_data->m_handle, 0);
Shinya Kitaoka 120a6e
    usb_close(m_data->m_handle);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  m_data->m_handle = 0;
Shinya Kitaoka 120a6e
  m_data->m_epson  = 0;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TUSBScannerIO::receive(unsigned char *buffer, int size) {
Shinya Kitaoka 120a6e
  TRACE
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if defined(HAS_LIBUSB)
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int count;
Shinya Kitaoka 120a6e
  count = usb_bulk_read(m_data->m_handle, m_data->m_epR, (char *)buffer, size,
Shinya Kitaoka 120a6e
                        30 * 1000);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_data->m_trace) {
Shinya Kitaoka 120a6e
    ostrstream os;
Shinya Kitaoka 120a6e
    os.freeze(false);
Shinya Kitaoka 120a6e
    os << "receive: size=" << size << " got = " << count << " buf=";
Shinya Kitaoka 120a6e
    buf2printable(buffer, count, os);
Shinya Kitaoka 120a6e
    os << '\n' << '\0';
Shinya Kitaoka 120a6e
    TSystem::outputDebug(os.str());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return count;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
  return 0;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TUSBScannerIO::send(unsigned char *buffer, int size) {
Shinya Kitaoka 120a6e
  TRACE
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if defined(HAS_LIBUSB)
Shinya Kitaoka 120a6e
  int count;
Shinya Kitaoka 120a6e
  if (T != pthread_self()) {
Shinya Kitaoka 120a6e
    cout << "called from another thead" << endl;
Shinya Kitaoka 120a6e
    return 0;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  count = usb_bulk_write(m_data->m_handle, m_data->m_epW, (char *)buffer, size,
Shinya Kitaoka 120a6e
                         30 * 1000);
Shinya Kitaoka 120a6e
  if (m_data->m_trace) {
Shinya Kitaoka 120a6e
    ostrstream os;
Shinya Kitaoka 120a6e
    os.freeze(false);
Shinya Kitaoka 120a6e
    os << "send: size=" << size << " wrote = " << count << " buf=";
Shinya Kitaoka 120a6e
    buf2printable(buffer, size, os);
Shinya Kitaoka 120a6e
    os << '\n' << '\0';
Shinya Kitaoka 120a6e
    TSystem::outputDebug(os.str());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return count;
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
  return 0;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TUSBScannerIO::trace(bool on) {
Shinya Kitaoka 120a6e
  TRACE
Shinya Kitaoka 120a6e
  m_data->m_trace = on;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TUSBScannerIO::~TUSBScannerIO() { TRACE }